Skip to content

Commit

Permalink
feat: bintray publisher
Browse files Browse the repository at this point in the history
Closes #577
  • Loading branch information
develar committed Sep 2, 2016
1 parent eb827ea commit 138e8e2
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 45 deletions.
2 changes: 1 addition & 1 deletion docs/NSIS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 32 bit + 64 bit

If you build both ia32 and xha arch, you in any case get one installer. Appropriate arch will be installed automatically.
If you build both ia32 and x64 arch, you in any case get one installer. Appropriate arch will be installed automatically.

# Custom NSIS script

Expand Down
113 changes: 79 additions & 34 deletions src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,16 @@ import { PublishOptions, Publisher } from "./publish/publisher"
import { GitHubPublisher } from "./publish/gitHubPublisher"
import { executeFinally } from "./util/promise"
import { Promise as BluebirdPromise } from "bluebird"
import { isEmptyOrSpaces, isCi } from "./util/util"
import { isEmptyOrSpaces, isCi, asArray, debug } from "./util/util"
import { log, warn } from "./util/log"
import { Platform, Arch, archFromString } from "./metadata"
import { getRepositoryInfo } from "./repositoryInfo"
import { DIR_TARGET } from "./targets/targetFactory"
import { BintrayPublisher, BintrayConfiguration } from "./publish/BintrayPublisher"

//noinspection JSUnusedLocalSymbols
const __awaiter = require("./util/awaiter")

export async function createPublisher(packager: Packager, options: PublishOptions, isPublishOptionGuessed: boolean = false): Promise<Publisher | null> {
const info = await getRepositoryInfo(packager.metadata, packager.devMetadata)
if (info == null) {
if (isPublishOptionGuessed) {
return null
}

warn("Cannot detect repository by .git/config")
throw new Error(`Please specify 'repository' in the dev package.json ('${packager.devPackageFile}')`)
}
else {
const version = packager.metadata.version!
log(`Creating Github Publisher — user: ${info.user}, project: ${info.project}, version: ${version}`)
return new GitHubPublisher(info.user, info.project, version, options, isPublishOptionGuessed)
}
}

export interface BuildOptions extends PackagerOptions, PublishOptions {
}

Expand Down Expand Up @@ -210,6 +194,9 @@ export async function build(rawOptions?: CliOptions): Promise<void> {
if (options.githubToken === undefined && !isEmptyOrSpaces(process.env.GH_TOKEN)) {
options.githubToken = process.env.GH_TOKEN
}
if (options.bintrayToken === undefined && !isEmptyOrSpaces(process.env.BT_TOKEN)) {
options.bintrayToken = process.env.BT_TOKEN
}

if (options.draft === undefined && !isEmptyOrSpaces(process.env.EP_DRAFT)) {
options.draft = process.env.EP_DRAFT.toLowerCase() === "true"
Expand Down Expand Up @@ -238,24 +225,16 @@ export async function build(rawOptions?: CliOptions): Promise<void> {
}
}

if (options.publish !== "never" && options.githubToken == null && isCi()) {
log(`CI detected, publish is set to ${options.publish}, but GH_TOKEN is not set, so artifacts will be not published`)
}

const publishTasks: Array<BluebirdPromise<any>> = []
const packager = new Packager(options)
if (options.publish != null && options.publish !== "never") {
let publisher: Promise<Publisher> | null = null
packager.artifactCreated(event => {
if (publisher == null) {
publisher = createPublisher(packager, options, isPublishOptionGuessed)
}
const publishTasks: Array<BluebirdPromise<any>> = []

if (publisher) {
publisher
.then(it => publishTasks.push(<BluebirdPromise<any>>it.upload(event.file, event.artifactName)))
}
})
if (options.publish != null && options.publish !== "never") {
if (options.githubToken != null || options.bintrayToken != null) {
publishManager(packager, publishTasks, options, isPublishOptionGuessed)
}
else if (isCi()) {
log(`CI detected, publish is set to ${options.publish}, but neither GH_TOKEN nor BT_TOKEN is not set, so artifacts will be not published`)
}
}

await executeFinally(packager.build(), errorOccurred => {
Expand All @@ -270,3 +249,69 @@ export async function build(rawOptions?: CliOptions): Promise<void> {
}
})
}

function publishManager(packager: Packager, publishTasks: Array<BluebirdPromise<any>>, options: BuildOptions, isPublishOptionGuessed: boolean) {
const nameToPublisher = new Map<string, Promise<Publisher>>()
packager.artifactCreated(event => {
let publishers = event.packager.platformSpecificBuildOptions.publish
// if explicitly set to null - do not publish
if (publishers === null) {
debug(`${event.file} is not published: publish set to null`)
return
}

if (publishers == null) {
publishers = event.packager.info.devMetadata.build.publish
if (publishers === null) {
debug(`${event.file} is not published: publish set to null in the "build"`)
return
}

if (publishers == null && options.githubToken != null) {
publishers = ["github"]
}
// if both tokens are set — still publish to github (because default publisher is github)
if (publishers == null && options.bintrayToken != null) {
publishers = ["bintray"]
}
}

for (let publisherName of asArray(publishers)) {
let publisher = nameToPublisher.get(publisherName)
if (publisher == null) {
publisher = createPublisher(packager, options, publisherName, isPublishOptionGuessed)
nameToPublisher.set(publisherName, publisher)
}

if (publisher != null) {
publisher
.then(it => it == null ? null : publishTasks.push(<BluebirdPromise<any>>it.upload(event.file, event.artifactName)))
}
}
})
}

export async function createPublisher(packager: Packager, options: PublishOptions, publisherName: string, isPublishOptionGuessed: boolean = false): Promise<Publisher | null> {
const info = await getRepositoryInfo(packager.metadata, packager.devMetadata)
if (info == null) {
if (isPublishOptionGuessed) {
return null
}

warn("Cannot detect repository by .git/config")
throw new Error(`Please specify 'repository' in the dev package.json ('${packager.devPackageFile}')`)
}

if (publisherName === "github") {
const version = packager.metadata.version!
log(`Creating Github Publisher — user: ${info.user}, project: ${info.project}, version: ${version}`)
return new GitHubPublisher(info.user, info.project, version, options, isPublishOptionGuessed)
}
if (publisherName === "bintray") {
const version = packager.metadata.version!
const bintrayInfo: BintrayConfiguration = {user: info.user, packageName: info.project, repo: "generic"}
log(`Creating Bintray Publisher — user: ${bintrayInfo.user}, package: ${bintrayInfo.packageName}, repository: ${bintrayInfo.repo}, version: ${version}`)
return new BintrayPublisher(bintrayInfo, version, options)
}
return null
}
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { Packager } from "./packager"
export { PackagerOptions, ArtifactCreated, BuildInfo } from "./platformPackager"
export { DIR_TARGET, DEFAULT_TARGET } from "./targets/targetFactory"
export { BuildOptions, build, createPublisher, CliOptions, createTargets } from "./builder"
export { BuildOptions, build, CliOptions, createTargets } from "./builder"
export { PublishOptions, Publisher } from "./publish/publisher"
export { AppMetadata, DevMetadata, Platform, Arch, archFromString, BuildMetadata, MacOptions, WinBuildOptions, LinuxBuildOptions, CompressionLevel } from "./metadata"
4 changes: 4 additions & 0 deletions src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ export interface BuildMetadata {
readonly "app-bundle-id"?: string | null

readonly dereference?: boolean

readonly publish?: string | Array<string> | null
}

export interface AfterPackContext {
Expand Down Expand Up @@ -571,6 +573,8 @@ export interface PlatformSpecificBuildOptions {
readonly icon?: string | null

readonly fileAssociations?: Array<FileAssociation> | FileAssociation

readonly publish?: string | Array<string> | null
}

export class Platform {
Expand Down
3 changes: 3 additions & 0 deletions src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
file: file,
artifactName: artifactName,
platform: this.platform,
packager: this,
})
}

Expand Down Expand Up @@ -459,6 +460,8 @@ export function getArchSuffix(arch: Arch): string {
}

export interface ArtifactCreated {
readonly packager: PlatformPackager<any>

readonly file: string
readonly artifactName?: string

Expand Down
12 changes: 9 additions & 3 deletions src/publish/BintrayPublisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ import { BintrayClient, Version } from "./bintray"
//noinspection JSUnusedLocalSymbols
const __awaiter = require("../util/awaiter")

export interface BintrayConfiguration {
readonly user: string
readonly packageName: string
readonly repo?: string
}

export class BintrayPublisher implements Publisher {
private _versionPromise: BluebirdPromise<Version>

private readonly client: BintrayClient

constructor(private user: string, apiKey: string, private version: string, private packageName: string, private repo: string = "generic", private options: PublishOptions = {}) {
this.client = new BintrayClient(user, packageName, repo, apiKey)
constructor(private info: BintrayConfiguration, private version: string, private options: PublishOptions) {
this.client = new BintrayClient(info.user, info.packageName, info.repo || "generic", options.bintrayToken)
this._versionPromise = <BluebirdPromise<Version>>this.init()
}

Expand Down Expand Up @@ -54,7 +60,7 @@ export class BintrayPublisher implements Publisher {
try {
return await doApiRequest<any>({
hostname: "api.bintray.com",
path: `/content/${this.user}/${this.repo}/${this.packageName}/${version.name}/${fileName}`,
path: `/content/${this.client.user}/${this.client.repo}/${this.client.packageName}/${version.name}/${fileName}`,
method: "PUT",
headers: {
"User-Agent": "electron-builder",
Expand Down
2 changes: 1 addition & 1 deletion src/publish/bintray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class BintrayClient {
private readonly basePath: string
readonly auth: string | null

constructor(private user: string, private packageName: string, private repo: string = "generic", apiKey?: string | null) {
constructor(public user: string, public packageName: string, public repo: string = "generic", apiKey?: string | null) {
this.auth = apiKey == null ? null : `Basic ${new Buffer(`${user}:${apiKey}`).toString("base64")}`
this.basePath = `/packages/${this.user}/${this.repo}/${this.packageName}`
}
Expand Down
2 changes: 1 addition & 1 deletion src/publish/gitHubPublisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class GitHubPublisher implements Publisher {
}

this.tag = `v${version}`
this._releasePromise = <BluebirdPromise<Release>>this.init()
this._releasePromise = this.token === "__test__" ? BluebirdPromise.resolve(<any>null) : <BluebirdPromise<Release>>this.init()
}

private async init(): Promise<Release | null> {
Expand Down
1 change: 1 addition & 0 deletions src/publish/publisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export type PublishPolicy = "onTag" | "onTagOrDraft" | "always" | "never"
export interface PublishOptions {
publish?: PublishPolicy | null
githubToken?: string | null
bintrayToken?: string | null

draft?: boolean
prerelease?: boolean
Expand Down
2 changes: 2 additions & 0 deletions src/targets/squirrelPack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { remove, copy, createWriteStream, unlink, ensureDir } from "fs-extra-p"
import { spawn, exec } from "../util/util"
import { debug } from "../util/util"
import { WinPackager } from "../winPackager"
import { log } from "../util/log"

const archiverUtil = require("archiver-utils")
const archiver = require("archiver")
Expand All @@ -23,6 +24,7 @@ export function convertVersion(version: string): string {
}

function syncReleases(outputDirectory: string, options: SquirrelOptions) {
log("Sync releases to build delta package")
const args = prepareArgs(["-u", options.remoteReleases!, "-r", outputDirectory], path.join(options.vendorPath, "SyncReleases.exe"))
if (options.remoteToken) {
args.push("-t", options.remoteToken)
Expand Down
4 changes: 1 addition & 3 deletions src/winPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,8 @@ export class WinPackager extends PlatformPackager<WinBuildOptions> {
}

async pack(outDir: string, arch: Arch, targets: Array<Target>, postAsyncTasks: Array<Promise<any>>): Promise<any> {
const packOptions = await this.computePackOptions()
const appOutDir = this.computeAppOutDir(outDir, arch)
await this.doPack(packOptions, outDir, appOutDir, this.platform.nodeName, arch, this.platformSpecificBuildOptions)
await this.sign(path.join(appOutDir, `${this.appInfo.productFilename}.exe`))
await this.doPack(await this.computePackOptions(), outDir, appOutDir, this.platform.nodeName, arch, this.platformSpecificBuildOptions)
this.packageInDistributableFormat(outDir, appOutDir, arch, targets, postAsyncTasks)
}

Expand Down
24 changes: 23 additions & 1 deletion test/src/ArtifactPublisherTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { HttpError } from "out/publish/restApiRequest"
import { join } from "path"
import { assertThat } from "./helpers/fileAssert"
import { BintrayPublisher } from "out/publish/BintrayPublisher"
import { createPublisher } from "out/builder"

//noinspection JSUnusedLocalSymbols
const __awaiter = require("out/util/awaiter")
Expand Down Expand Up @@ -53,7 +54,7 @@ function testAndIgnoreApiRate(name: string, testFunction: () => Promise<any>) {
test("Bintray upload", async () => {
const version = versionNumber()
//noinspection SpellCheckingInspection
const publisher = new BintrayPublisher("actperepo", "5df2cadec86dff91392e4c419540785813c3db15", version, "test")
const publisher = new BintrayPublisher({user: "actperepo", packageName: "test", repo: "generic"}, version, {bintrayToken: "5df2cadec86dff91392e4c419540785813c3db15"})
try {
const artifactName = `icon-${version}.icns`
await publisher.upload(iconPath, artifactName)
Expand Down Expand Up @@ -132,4 +133,25 @@ testAndIgnoreApiRate("GitHub upload org", async () => {
finally {
await publisher.deleteRelease()
}
})

test("create publisher", async () => {
const packager: any = {
metadata: {
version: "2.0.0",
},
devMetadata: {
repository: "develar/test"
},
}
const publisher = await createPublisher(packager, {
githubToken: "__test__",
}, "github")

assertThat(publisher).hasProperties({
"owner": "develar",
"repo": "test",
"token": "__test__",
"version": "2.0.0",
})
})

0 comments on commit 138e8e2

Please sign in to comment.