Skip to content

Commit

Permalink
fix: github as a provider — latest.yml is not published
Browse files Browse the repository at this point in the history
Closes #868
  • Loading branch information
develar committed Nov 7, 2016
1 parent 265ad20 commit e920584
Show file tree
Hide file tree
Showing 16 changed files with 125 additions and 92 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,18 @@
"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",
"cuint": "^0.2.2",
"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",
Expand Down Expand Up @@ -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",
Expand Down
33 changes: 24 additions & 9 deletions src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,25 +250,40 @@ function isAuthTokenSet() {

function publishManager(packager: Packager, publishTasks: Array<BluebirdPromise<any>>, options: BuildOptions, isPublishOptionGuessed: boolean) {
const nameToPublisher = new Map<string, Promise<Publisher>>()

function getOrCreatePublisher(publishConfig: PublishConfiguration): Promise<Publisher | null> {
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`)
return
}

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

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

if (event.file == null) {
return publishTasks.push(<BluebirdPromise<any>>it.uploadData(event.data!, event.artifactName!))
}
else {
return publishTasks.push(<BluebirdPromise<any>>it.upload(event.file!, event.artifactName))
}
})
}
}
})
Expand Down
7 changes: 4 additions & 3 deletions src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
this.info.eventEmitter.emit("artifactCreated", {
file: file,
artifactName: artifactName,
platform: this.platform,
packager: this,
})
}
Expand Down Expand Up @@ -491,10 +490,12 @@ export function getArchSuffix(arch: Arch): string {
export interface ArtifactCreated {
readonly packager: PlatformPackager<any>

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
Expand Down
18 changes: 8 additions & 10 deletions src/publish/BintrayPublisher.ts
Original file line number Diff line number Diff line change
@@ -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<Version>

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
Expand Down Expand Up @@ -46,15 +46,13 @@ export class BintrayPublisher implements Publisher {
}
}

async upload(file: string, artifactName?: string): Promise<any> {
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 {
Expand All @@ -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
Expand Down
16 changes: 7 additions & 9 deletions src/publish/gitHubPublisher.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -25,7 +23,7 @@ interface Asset {
name: string
}

export class GitHubPublisher implements Publisher {
export class GitHubPublisher extends Publisher {
private tag: string
private _releasePromise: BluebirdPromise<Release>

Expand All @@ -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
Expand Down Expand Up @@ -92,16 +92,14 @@ export class GitHubPublisher implements Publisher {
}
}

async upload(file: string, artifactName?: string): Promise<void> {
const fileName = artifactName || basename(file)
protected async doUpload(fileName: string, dataLength: number, requestProcessor: (request: ClientRequest, reject: (error: Error) => void) => void): Promise<void> {
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`)
return
}

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 {
Expand All @@ -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) {
Expand Down
22 changes: 20 additions & 2 deletions src/publish/publisher.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -7,6 +12,19 @@ export interface PublishOptions {
prerelease?: boolean
}

export interface Publisher {
upload(file: string, artifactName?: string): Promise<any>
export abstract class Publisher {
async upload(file: string, artifactName?: string): Promise<any> {
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<any> {
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<any>
}
4 changes: 2 additions & 2 deletions src/publish/restApiRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ export function request<T>(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"
Expand All @@ -43,6 +41,8 @@ export function request<T>(url: Url, token: string | null = null, data: { [name:
}

export function doApiRequest<T>(options: RequestOptions, token: string | null, requestProcessor: (request: ClientRequest, reject: (error: Error) => void) => void, redirectCount: number = 0): Promise<T> {
debug(`HTTPS request: ${JSON.stringify(options, null, 2)}`)

if (token != null) {
(<any>options.headers).authorization = token.startsWith("Basic") ? token : `token ${token}`
}
Expand Down
36 changes: 24 additions & 12 deletions src/targets/nsis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<string>()
let sha2: string | null = null
for (let publishConfig of publishConfigs) {
if (publishConfig.provider === "generic" || publishConfig.provider === "github") {
Expand All @@ -213,21 +216,30 @@ export default class NsisTarget extends TargetEx {
}

const channel = (<GenericServerOptions>publishConfig).channel || "latest"
if (writtenChannels.has(channel)) {
continue
if (publishConfig.provider === "generic") {
await writeFile(path.join(this.outDir, `${channel}.yml`), safeDump(<UpdateInfo>{
version: version,
path: installerFilename,
sha2: sha2,
}))
}
else {
packager.info.eventEmitter.emit("artifactCreated", <ArtifactCreated>{
data: new Buffer(safeDump(<UpdateInfo>{
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(<UpdateInfo>{
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) {
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/app-executable-deps/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"build": {
"electronVersion": "1.4.0",
"electronVersion": "1.4.5",
"category": "public.app-category.business"
}
}
2 changes: 1 addition & 1 deletion test/fixtures/test-app-one/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"author": "Foo Bar <[email protected]>",
"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",
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/test-app/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
2 changes: 1 addition & 1 deletion test/src/helpers/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
export const ELECTRON_VERSION = "1.4.5"
4 changes: 2 additions & 2 deletions test/src/helpers/packTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@ async function packAndCheck(outDir: string, packagerOptions: PackagerOptions, ch
const artifacts: Map<Platform, Array<ArtifactCreated>> = 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)
})
Expand Down
Loading

0 comments on commit e920584

Please sign in to comment.