diff --git a/package.json b/package.json index 7303c7a3aa9..e88499d82b8 100644 --- a/package.json +++ b/package.json @@ -59,10 +59,10 @@ "dependencies": { "7zip-bin": "^2.0.4", "ansi-escapes": "^1.4.0", - "archiver": "^1.1.0", + "archiver": "^1.2.0", "archiver-utils": "^1.3.0", "asar-electron-builder": "^0.13.5", - "bluebird-lst-c": "^1.0.2", + "bluebird-lst-c": "^1.0.3", "chalk": "^1.1.3", "chromium-pickle-js": "^0.2.0", "cli-cursor": "^1.0.2", @@ -70,7 +70,7 @@ "debug": "^2.2.0", "electron-download": "2.1.2", "electron-osx-sign-tf": "~1.1.0", - "fs-extra-p": "^2.0.3", + "fs-extra-p": "^2.0.5", "hosted-git-info": "^2.1.5", "ini": "^1.3.4", "isbinaryfile": "^3.0.1", @@ -112,7 +112,7 @@ "husky": "^0.11.9", "json8": "^0.9.2", "path-sort": "^0.1.0", - "ts-babel": "^1.1.3", + "ts-babel": "^1.1.4", "tslint": "^4.0.0-dev.1", "typescript": "^2.1.0-dev.20161101", "validate-commit-msg": "^2.8.2", diff --git a/src/builder.ts b/src/builder.ts index 99cac984f68..2485f7cebe8 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -250,8 +250,18 @@ function isAuthTokenSet() { function publishManager(packager: Packager, publishTasks: Array>, options: BuildOptions, isPublishOptionGuessed: boolean) { const nameToPublisher = new Map>() + + function getOrCreatePublisher(publishConfig: PublishConfiguration): Promise { + let publisher = nameToPublisher.get(publishConfig.provider) + if (publisher == null) { + publisher = createPublisher(packager, publishConfig, options, isPublishOptionGuessed) + nameToPublisher.set(publishConfig.provider, publisher) + } + return publisher + } + packager.artifactCreated(event => { - const publishers = getPublishConfigs(event.packager, event.packager.platformSpecificBuildOptions) + const publishers = event.publishConfig == null ? getPublishConfigs(event.packager, event.packager.platformSpecificBuildOptions) : [event.publishConfig] // if explicitly set to null - do not publish if (publishers === null) { debug(`${event.file} is not published: publish is set to null`) @@ -259,16 +269,21 @@ function publishManager(packager: Packager, publishTasks: Array it == null ? null : publishTasks.push(>it.upload(event.file, event.artifactName))) + .then(it => { + if (it == null) { + return null + } + + if (event.file == null) { + return publishTasks.push(>it.uploadData(event.data!, event.artifactName!)) + } + else { + return publishTasks.push(>it.upload(event.file!, event.artifactName)) + } + }) } } }) diff --git a/src/platformPackager.ts b/src/platformPackager.ts index a6a85f445bc..600e96ebf73 100644 --- a/src/platformPackager.ts +++ b/src/platformPackager.ts @@ -158,7 +158,6 @@ export abstract class PlatformPackager this.info.eventEmitter.emit("artifactCreated", { file: file, artifactName: artifactName, - platform: this.platform, packager: this, }) } @@ -491,10 +490,12 @@ export function getArchSuffix(arch: Arch): string { export interface ArtifactCreated { readonly packager: PlatformPackager - readonly file: string + readonly file?: string + readonly data?: Buffer + readonly artifactName?: string - readonly platform: Platform + readonly publishConfig?: PublishConfiguration } // fpm bug - rpm build --description is not escaped, well... decided to replace quite to smart quote diff --git a/src/publish/BintrayPublisher.ts b/src/publish/BintrayPublisher.ts index 8274f07ce82..f93f1aba4b5 100644 --- a/src/publish/BintrayPublisher.ts +++ b/src/publish/BintrayPublisher.ts @@ -1,20 +1,20 @@ import { Publisher, PublishOptions } from "./publisher" import BluebirdPromise from "bluebird-lst-c" import { HttpError, doApiRequest } from "./restApiRequest" -import { uploadFile } from "./uploader" import { log } from "../util/log" import { debug, isEmptyOrSpaces } from "../util/util" -import { basename } from "path" -import { stat } from "fs-extra-p" import { BintrayClient, Version } from "./bintray" import { BintrayOptions } from "../options/publishOptions" +import { ClientRequest } from "http" -export class BintrayPublisher implements Publisher { +export class BintrayPublisher extends Publisher { private _versionPromise: BluebirdPromise private readonly client: BintrayClient constructor(info: BintrayOptions, private readonly version: string, private readonly options: PublishOptions = {}) { + super() + let token = info.token if (isEmptyOrSpaces(token)) { token = process.env.BT_TOKEN @@ -46,15 +46,13 @@ export class BintrayPublisher implements Publisher { } } - async upload(file: string, artifactName?: string): Promise { - const fileName = artifactName || basename(file) + protected async doUpload(fileName: string, dataLength: number, requestProcessor: (request: ClientRequest, reject: (error: Error) => void) => void) { const version = await this._versionPromise if (version == null) { debug(`Version ${this.version} doesn't exist and is not created, artifact ${fileName} is not published`) return } - const fileStat = await stat(file) let badGatewayCount = 0 for (let i = 0; i < 3; i++) { try { @@ -64,15 +62,15 @@ export class BintrayPublisher implements Publisher { method: "PUT", headers: { "User-Agent": "electron-builder", - "Content-Length": fileStat.size, + "Content-Length": dataLength, "X-Bintray-Override": "1", "X-Bintray-Publish": "1", } - }, this.client.auth, uploadFile.bind(this, file, fileStat, fileName)) + }, this.client.auth, requestProcessor) } catch (e) { if (e instanceof HttpError && e.response.statusCode === 502 && badGatewayCount++ < 3) { - continue + continue } throw e diff --git a/src/publish/gitHubPublisher.ts b/src/publish/gitHubPublisher.ts index 504babeeed5..f8f7271f629 100644 --- a/src/publish/gitHubPublisher.ts +++ b/src/publish/gitHubPublisher.ts @@ -1,15 +1,13 @@ import { isEmptyOrSpaces } from "../util/util" import { log, warn } from "../util/log" import { debug } from "../util/util" -import { basename } from "path" import { parse as parseUrl } from "url" import mime from "mime" -import { stat } from "fs-extra-p" import { githubRequest, HttpError, doApiRequest } from "./restApiRequest" import BluebirdPromise from "bluebird-lst-c" import { PublishPolicy, PublishOptions, Publisher } from "./publisher" -import { uploadFile } from "./uploader" import { GithubOptions } from "../options/publishOptions" +import { ClientRequest } from "http" export interface Release { id: number @@ -25,7 +23,7 @@ interface Asset { name: string } -export class GitHubPublisher implements Publisher { +export class GitHubPublisher extends Publisher { private tag: string private _releasePromise: BluebirdPromise @@ -37,6 +35,8 @@ export class GitHubPublisher implements Publisher { } constructor(private readonly info: GithubOptions, private readonly version: string, private readonly options: PublishOptions = {}, private readonly isPublishOptionGuessed: boolean = false) { + super() + let token = info.token if (isEmptyOrSpaces(token)) { token = process.env.GH_TOKEN @@ -92,8 +92,7 @@ export class GitHubPublisher implements Publisher { } } - async upload(file: string, artifactName?: string): Promise { - const fileName = artifactName || basename(file) + protected async doUpload(fileName: string, dataLength: number, requestProcessor: (request: ClientRequest, reject: (error: Error) => void) => void): Promise { const release = await this.releasePromise if (release == null) { debug(`Release with tag ${this.tag} doesn't exist and is not created, artifact ${fileName} is not published`) @@ -101,7 +100,6 @@ export class GitHubPublisher implements Publisher { } const parsedUrl = parseUrl(release.upload_url.substring(0, release.upload_url.indexOf("{")) + "?name=" + fileName) - const fileStat = await stat(file) let badGatewayCount = 0 uploadAttempt: for (let i = 0; i < 3; i++) { try { @@ -113,9 +111,9 @@ export class GitHubPublisher implements Publisher { Accept: "application/vnd.github.v3+json", "User-Agent": "electron-builder", "Content-Type": mime.lookup(fileName), - "Content-Length": fileStat.size + "Content-Length": dataLength } - }, this.token, uploadFile.bind(this, file, fileStat, fileName)) + }, this.token, requestProcessor) } catch (e) { if (e instanceof HttpError) { diff --git a/src/publish/publisher.ts b/src/publish/publisher.ts index 356e52c93c8..7bef5c12bbb 100644 --- a/src/publish/publisher.ts +++ b/src/publish/publisher.ts @@ -1,3 +1,8 @@ +import { ClientRequest } from "http" +import { uploadFile } from "./uploader" +import { stat } from "fs-extra-p" +import { basename } from "path" + export type PublishPolicy = "onTag" | "onTagOrDraft" | "always" | "never" export interface PublishOptions { @@ -7,6 +12,19 @@ export interface PublishOptions { prerelease?: boolean } -export interface Publisher { - upload(file: string, artifactName?: string): Promise +export abstract class Publisher { + async upload(file: string, artifactName?: string): Promise { + const fileName = artifactName || basename(file) + const fileStat = await stat(file) + await this.doUpload(fileName, fileStat.size, uploadFile.bind(this, file, fileStat, fileName)) + } + + uploadData(data: Buffer, fileName: string): Promise { + if (data == null || fileName == null) { + throw new Error("data or fileName is null") + } + return this.doUpload(fileName, data.length, it => it.end(data)) + } + + protected abstract doUpload(fileName: string, dataLength: number, requestProcessor: (request: ClientRequest, reject: (error: Error) => void) => void): Promise } \ No newline at end of file diff --git a/src/publish/restApiRequest.ts b/src/publish/restApiRequest.ts index bac78a5812d..298fcccee49 100644 --- a/src/publish/restApiRequest.ts +++ b/src/publish/restApiRequest.ts @@ -31,8 +31,6 @@ export function request(url: Url, token: string | null = null, data: { [name: options.headers.Accept = "application/vnd.github.v3+json" } - debug(`HTTPS request: ${JSON.stringify(options, null, 2)}`) - const encodedData = data == null ? null : new Buffer(JSON.stringify(data)) if (encodedData != null) { options.method = "post" @@ -43,6 +41,8 @@ export function request(url: Url, token: string | null = null, data: { [name: } export function doApiRequest(options: RequestOptions, token: string | null, requestProcessor: (request: ClientRequest, reject: (error: Error) => void) => void, redirectCount: number = 0): Promise { + debug(`HTTPS request: ${JSON.stringify(options, null, 2)}`) + if (token != null) { (options.headers).authorization = token.startsWith("Basic") ? token : `token ${token}` } diff --git a/src/targets/nsis.ts b/src/targets/nsis.ts index 41e46ef963f..1c3ae2ba355 100644 --- a/src/targets/nsis.ts +++ b/src/targets/nsis.ts @@ -5,7 +5,10 @@ import * as path from "path" import BluebirdPromise from "bluebird-lst-c" import { getBinFromBintray } from "../util/binDownload" import { v5 as uuid5 } from "uuid-1345" -import { normalizeExt, TargetEx, getPublishConfigs, getResolvedPublishConfig } from "../platformPackager" +import { + normalizeExt, TargetEx, getPublishConfigs, getResolvedPublishConfig, + ArtifactCreated +} from "../platformPackager" import { archiveApp } from "./archive" import { subTask, task, log } from "../util/log" import { unlink, readFile, writeFile, createReadStream } from "fs-extra-p" @@ -203,8 +206,8 @@ export default class NsisTarget extends TargetEx { await packager.sign(installerPath) const publishConfigs = await this.publishConfigs + const githubArtifactName = `${appInfo.name}-Setup-${version}.exe` if (publishConfigs != null) { - const writtenChannels = new Set() let sha2: string | null = null for (let publishConfig of publishConfigs) { if (publishConfig.provider === "generic" || publishConfig.provider === "github") { @@ -213,21 +216,30 @@ export default class NsisTarget extends TargetEx { } const channel = (publishConfig).channel || "latest" - if (writtenChannels.has(channel)) { - continue + if (publishConfig.provider === "generic") { + await writeFile(path.join(this.outDir, `${channel}.yml`), safeDump({ + version: version, + path: installerFilename, + sha2: sha2, + })) + } + else { + packager.info.eventEmitter.emit("artifactCreated", { + data: new Buffer(safeDump({ + version: version, + path: githubArtifactName, + sha2: sha2, + })), + artifactName: `${channel}.yml`, + packager: packager, + publishConfig: publishConfig, + }) } - writtenChannels.add(channel) - - await writeFile(path.join(this.outDir, `${channel}.yml`), safeDump({ - version: version, - path: installerFilename, - sha2: sha2, - })) } } } - this.packager.dispatchArtifactCreated(installerPath, `${appInfo.name}-Setup-${version}.exe`) + packager.dispatchArtifactCreated(installerPath, githubArtifactName) } private async executeMakensis(defines: any, commands: any, isInstaller: boolean, originalScript: string) { diff --git a/test/fixtures/app-executable-deps/package.json b/test/fixtures/app-executable-deps/package.json index bbf0e40862a..bbb14cbbbda 100644 --- a/test/fixtures/app-executable-deps/package.json +++ b/test/fixtures/app-executable-deps/package.json @@ -1,6 +1,6 @@ { "build": { - "electronVersion": "1.4.0", + "electronVersion": "1.4.5", "category": "public.app-category.business" } } diff --git a/test/fixtures/test-app-one/package.json b/test/fixtures/test-app-one/package.json index d0612291ce4..39e6921f118 100755 --- a/test/fixtures/test-app-one/package.json +++ b/test/fixtures/test-app-one/package.json @@ -8,7 +8,7 @@ "author": "Foo Bar ", "license": "MIT", "build": { - "electronVersion": "1.4.0", + "electronVersion": "1.4.5", "appId": "org.electron-builder.testApp", "iconUrl": "https://raw.githubusercontent.com/szwacz/electron-boilerplate/master/resources/windows/icon.ico", "compression": "store", diff --git a/test/fixtures/test-app/package.json b/test/fixtures/test-app/package.json index 38bd8dd9c8b..1e2a1678185 100755 --- a/test/fixtures/test-app/package.json +++ b/test/fixtures/test-app/package.json @@ -1,7 +1,7 @@ { "private": true, "build": { - "electronVersion": "1.4.0", + "electronVersion": "1.4.5", "appId": "org.electron-builder.testApp", "category": "your.app.category.type", "iconUrl": "https://raw.githubusercontent.com/szwacz/electron-boilerplate/master/resources/windows/icon.ico", diff --git a/test/src/helpers/config.ts b/test/src/helpers/config.ts index 885e0bb198f..d99f6c2b312 100644 --- a/test/src/helpers/config.ts +++ b/test/src/helpers/config.ts @@ -5,4 +5,4 @@ import { createHash } from "crypto" // reuse to avoid stale data (maybe not removed correctly on test stop) // use __dirname to allow run in parallel from different project clones export const TEST_DIR = path.join(tmpdir(), `et-${createHash("md5").update(__dirname).digest("hex")}`) -export const ELECTRON_VERSION = "1.4.0" \ No newline at end of file +export const ELECTRON_VERSION = "1.4.5" \ No newline at end of file diff --git a/test/src/helpers/packTester.ts b/test/src/helpers/packTester.ts index ce2bc873fdd..35c1b186141 100755 --- a/test/src/helpers/packTester.ts +++ b/test/src/helpers/packTester.ts @@ -146,10 +146,10 @@ async function packAndCheck(outDir: string, packagerOptions: PackagerOptions, ch const artifacts: Map> = new Map() packager.artifactCreated(event => { assertThat(event.file).isAbsolute() - let list = artifacts.get(event.platform) + let list = artifacts.get(event.packager.platform) if (list == null) { list = [] - artifacts.set(event.platform, list) + artifacts.set(event.packager.platform, list) } list.push(event) }) diff --git a/yarn.lock b/yarn.lock index 016b8346b1a..6efea4e1024 100644 --- a/yarn.lock +++ b/yarn.lock @@ -137,7 +137,7 @@ archiver-utils@^1.3.0: normalize-path "^2.0.0" readable-stream "^2.0.0" -archiver@^1.1.0: +archiver@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/archiver/-/archiver-1.2.0.tgz#fb5c6af5443b3fa6a426344753bad2a7b444aadd" dependencies: @@ -378,7 +378,7 @@ babel-code-frame@^6.16.0: esutils "^2.0.2" js-tokens "^2.0.0" -babel-core@^6.17.0, babel-core@^6.18.0: +babel-core@^6.17.0, babel-core@^6.18.0, babel-core@^6.18.2: version "6.18.2" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.18.2.tgz#d8bb14dd6986fa4f3566a26ceda3964fa0e04e5b" dependencies: @@ -1013,9 +1013,9 @@ block-stream@*: dependencies: inherits "~2.0.0" -bluebird-lst-c@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bluebird-lst-c/-/bluebird-lst-c-1.0.2.tgz#b9800c878d83bda4630f5ffbc0e39cc5f8a193e7" +bluebird-lst-c@^1.0.2, bluebird-lst-c@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/bluebird-lst-c/-/bluebird-lst-c-1.0.3.tgz#5bd879f3de7288201b08f31e2fe5d5c11e2b61de" dependencies: bluebird "^3.4.6" @@ -1870,21 +1870,14 @@ from@~0: version "0.1.3" resolved "https://registry.yarnpkg.com/from/-/from-0.1.3.tgz#ef63ac2062ac32acf7862e0d40b44b896f22f3bc" -fs-extra-p@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fs-extra-p/-/fs-extra-p-1.2.0.tgz#16abed58ec63219cf9244a5a54ba200d4864b347" - dependencies: - bluebird "^3.4.6" - fs-extra-tf "^0.30.3" - -fs-extra-p@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/fs-extra-p/-/fs-extra-p-2.0.3.tgz#570072384028c95193a158b4ff080be0200fd007" +fs-extra-p@^2.0.3, fs-extra-p@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/fs-extra-p/-/fs-extra-p-2.0.5.tgz#a9f9bee515880198da4528d81a85f43e0cf9837b" dependencies: - bluebird "^3.4.6" + bluebird-lst-c "^1.0.3" fs-extra-tf "^0.30.4" -fs-extra-tf@^0.30.3, fs-extra-tf@^0.30.4: +fs-extra-tf@^0.30.4: version "0.30.4" resolved "https://registry.yarnpkg.com/fs-extra-tf/-/fs-extra-tf-0.30.4.tgz#c31e0c83a92201bd948e788563e1c02f35583e8f" dependencies: @@ -2729,7 +2722,7 @@ map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" -markdown-it@^8.0.1: +markdown-it@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.1.0.tgz#38902d4e7bac2260c073eb67be623211fbb2c2e3" dependencies: @@ -3673,7 +3666,7 @@ sort-keys@^1.1.1: dependencies: is-plain-obj "^1.0.0" -source-map-support@^0.4.2, source-map-support@^0.4.4, source-map-support@^0.4.5, source-map-support@^0.4.6: +source-map-support@^0.4.2, source-map-support@^0.4.4, source-map-support@^0.4.6: version "0.4.6" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.6.tgz#32552aa64b458392a85eab3b0b5ee61527167aeb" dependencies: @@ -3946,16 +3939,16 @@ truncate-utf8-bytes@^1.0.0: dependencies: utf8-byte-length "^1.0.1" -ts-babel@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/ts-babel/-/ts-babel-1.1.3.tgz#e5565661bd940fe6cfdf42519340c0dcc08c9f8b" +ts-babel@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/ts-babel/-/ts-babel-1.1.4.tgz#69339a1cc69e57c07bd4202eec01ca55092c9f4e" dependencies: - babel-core "^6.17.0" - bluebird "^3.4.6" + babel-core "^6.18.2" + bluebird-lst-c "^1.0.3" chalk "^1.1.3" - fs-extra-p "^1.2.0" - markdown-it "^8.0.1" - source-map-support "^0.4.5" + fs-extra-p "^2.0.5" + markdown-it "^8.1.0" + source-map-support "^0.4.6" tslint@^4.0.0-dev.1: version "4.0.0-dev.1" @@ -3986,8 +3979,8 @@ typedarray@~0.0.5: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" typescript@^2.1.0-dev.20161101: - version "2.1.0-dev.20161106" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.1.0-dev.20161106.tgz#f6197280f92e2b306f40c0bc89ccece954b5764d" + version "2.1.0-dev.20161107" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.1.0-dev.20161107.tgz#420e8ea43693dde3ab62853fd1edbafce53087a3" uc.micro@^1.0.1, uc.micro@^1.0.3: version "1.0.3" @@ -4227,8 +4220,8 @@ yargs-parser@^2.4.1: lodash.assign "^4.0.6" yargs-parser@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.0.2.tgz#7f7173a8c7cca1d81dc7c18692fc07c2c2e2b1e0" + version "4.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.1.0.tgz#313df030f20124124aeae8fbab2da53ec28c56d7" dependencies: camelcase "^3.0.0"