Skip to content

Commit

Permalink
fix(nsis): correctly await update info writing and archive creation #529
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Oct 16, 2016
1 parent ac5da57 commit b1ae7d5
Show file tree
Hide file tree
Showing 19 changed files with 4,095 additions and 85 deletions.
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
node_modules/
*.log
out/
npm-debug.log
dist/
/.idea/compiler.xml
/.idea/encodings.xml
Expand All @@ -14,5 +13,4 @@ dist/
.DS_Store
.idea/shelf/
/test/typings/electron-builder.d.ts
/test/typings/electron-auto-updater.d.ts
/nsis-auto-updater/nm
/test/typings/electron-auto-updater.d.ts
1 change: 1 addition & 0 deletions .idea/dictionaries/develar.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions nsis-auto-updater/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "electron-auto-updater",
"version": "0.0.1",
"version": "0.0.2",
"description": "NSIS Auto Updater",
"main": "out/nsis-auto-updater/src/main.js",
"author": "Vladimir Krivosheev",
Expand All @@ -14,16 +14,16 @@
"dependencies": {
"bluebird": "^3.4.6",
"fs-extra-p": "^1.1.10",
"semver": "^5.3.0",
"ini": "^1.3.4",
"semver": "^5.3.0",
"tunnel-agent": "^0.4.3"
},
"bundledDependencies": [
"bluebird",
"fs-extra-p",
"semver",
"ini",
"semver",
"tunnel-agent"
],
"typings": "./out/electron-auto-updater.d.ts"
}
}
25 changes: 15 additions & 10 deletions nsis-auto-updater/src/NsisUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,33 +83,38 @@ export class NsisUpdater extends EventEmitter {
this.updateAvailable = true
this.emit("update-available")

const mkdtemp: any = BluebirdPromise.promisify(require("fs").mkdtemp)
const mkdtemp: (prefix: string) => Promise<string> = require("fs-extra-p").mkdtemp
return {
versionInfo: versionInfo,
fileInfo: fileInfo,
downloadPromise: mkdtemp(`${path.join(tmpdir(), "up")}-`)
.then((it: string) => {
this.setupPath = path.join(it, fileInfo.name)
return download(fileInfo.url, this.setupPath)
}),
.then(it => download(fileInfo.url, path.join(it, fileInfo.name)))
.then(it => {
this.setupPath = it
this.emit("update-downloaded", {}, null, versionInfo.version, null, null, () => {
this.quitAndInstall()
})
return it
})
.catch(error => this.emitError(error)),
}
}

quitAndInstall(): void {
const setupPath = this.setupPath
if (!this.updateAvailable || setupPath == null) {
this.emitError("No update available, can't quit and install")
if (this.quitAndInstallCalled) {
return
}

if (this.quitAndInstallCalled) {
const setupPath = this.setupPath
if (!this.updateAvailable || setupPath == null) {
this.emitError("No update available, can't quit and install")
return
}

// prevent calling several times
this.quitAndInstallCalled = true

spawn(setupPath!!, ["/S"], {
spawn(setupPath, ["/S"], {
detached: true,
stdio: "ignore",
}).unref()
Expand Down
18 changes: 6 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@
"pretest": "npm run compile && npm run lint && npm run pack-updater",
"test": "node ./test/out/helpers/runTests.js",
"test-linux": "docker run --rm -ti -v ${PWD}:/project -v ${PWD##*/}-node-modules:/project/node_modules -v ~/.electron:/root/.electron electronuserland/electron-builder:wine /test.sh",
"pack-updater": "cd nsis-auto-updater && npm install --production --no-bin-links && npm prune --production && cd ..",
"pack-updater": "cd nsis-auto-updater && npm install --production --no-bin-links && cd ..",
"semantic-release": "semantic-release pre && npm publish && semantic-release post",
"//": "Update wiki if docs changed. Update only if functionalily are generally available (latest release, not next)",
"update-wiki": "git subtree split -b wiki --prefix docs/ && git push -f wiki wiki:master",
"whitespace": "whitespace 'src/**/*.ts'",
"docker-images": "docker/build.sh"
"docker-images": "docker/build.sh",
"precommit": "validate-commit-msg"
},
"repository": "electron-userland/electron-builder",
"engines": {
Expand Down Expand Up @@ -93,34 +94,27 @@
"uuid-1345": "^0.99.6",
"yargs": "^6.0.0"
},
"config": {
"pre-git": {
"commit-msg": "conventional"
},
"pre-commit": [
"npm run whitespace"
]
},
"devDependencies": {
"@develar/semantic-release": "^6.3.6",
"@types/debug": "0.0.29",
"@types/mime": "0.0.29",
"@types/progress": "^1.1.28",
"@types/semver": "^5.3.30",
"@types/source-map-support": "^0.2.28",
"ava-tf": "^0.16.0",
"ava-tf": "^0.16.2",
"babel-plugin-array-includes": "^2.0.3",
"babel-plugin-transform-es2015-destructuring": "^6.16.0",
"babel-plugin-transform-es2015-parameters": "^6.17.0",
"babel-plugin-transform-es2015-spread": "^6.8.0",
"decompress-zip": "^0.3.0",
"diff": "^3.0.1",
"husky": "^0.11.9",
"json8": "^0.9.2",
"path-sort": "^0.1.0",
"pre-git": "^3.10.0",
"ts-babel": "^1.0.13",
"tslint": "^3.15.1",
"typescript": "^2.0.3",
"validate-commit-msg": "^2.8.2",
"whitespace": "^2.1.0"
},
"babel": {
Expand Down
21 changes: 10 additions & 11 deletions src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,6 @@ export async function build(rawOptions?: CliOptions): Promise<void> {
if (options.cscInstallerKeyPassword === undefined && !isEmptyOrSpaces(process.env.CSC_INSTALLER_KEY_PASSWORD)) {
options.cscInstallerKeyPassword = process.env.CSC_INSTALLER_KEY_PASSWORD
}
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 All @@ -212,7 +206,7 @@ export async function build(rawOptions?: CliOptions): Promise<void> {
if (process.env.npm_lifecycle_event === "release") {
options.publish = "always"
}
else if (options.githubToken != null) {
else if (isAuthTokenSet() ) {
const tag = process.env.TRAVIS_TAG || process.env.APPVEYOR_REPO_TAG_NAME || process.env.CIRCLE_TAG
if (!isEmptyOrSpaces(tag)) {
log(`Tag ${tag} is defined, so artifacts will be published`)
Expand All @@ -231,7 +225,8 @@ export async function build(rawOptions?: CliOptions): Promise<void> {
const publishTasks: Array<BluebirdPromise<any>> = []

if (options.publish != null && options.publish !== "never") {
if (options.githubToken != null || options.bintrayToken != null) {
// todo if token set as option
if (isAuthTokenSet()) {
publishManager(packager, publishTasks, options, isPublishOptionGuessed)
}
else if (isCi()) {
Expand All @@ -252,6 +247,10 @@ export async function build(rawOptions?: CliOptions): Promise<void> {
})
}

function isAuthTokenSet() {
return !isEmptyOrSpaces(process.env.GH_TOKEN) || !isEmptyOrSpaces(process.env.BT_TOKEN)
}

function publishManager(packager: Packager, publishTasks: Array<BluebirdPromise<any>>, options: BuildOptions, isPublishOptionGuessed: boolean) {
const nameToPublisher = new Map<string, Promise<Publisher>>()
packager.artifactCreated(event => {
Expand All @@ -266,7 +265,7 @@ function publishManager(packager: Packager, publishTasks: Array<BluebirdPromise<
const provider = publishConfig.provider
let publisher = nameToPublisher.get(provider)
if (publisher == null) {
publisher = createPublisher(packager, options, publishConfig, isPublishOptionGuessed)
publisher = createPublisher(packager, publishConfig, options, isPublishOptionGuessed)
nameToPublisher.set(provider, publisher)
}

Expand All @@ -278,7 +277,7 @@ function publishManager(packager: Packager, publishTasks: Array<BluebirdPromise<
})
}

export async function createPublisher(packager: Packager, options: PublishOptions, publishConfig: PublishConfiguration | GithubOptions | BintrayOptions, isPublishOptionGuessed: boolean = false): Promise<Publisher | null> {
export async function createPublisher(packager: Packager, publishConfig: PublishConfiguration | GithubOptions | BintrayOptions, options?: PublishOptions, isPublishOptionGuessed: boolean = false): Promise<Publisher | null> {
const config = await getResolvedPublishConfig(packager, publishConfig, isPublishOptionGuessed)
if (config == null) {
return null
Expand All @@ -288,7 +287,7 @@ export async function createPublisher(packager: Packager, options: PublishOption
if (publishConfig.provider === "github") {
const githubInfo: GithubOptions = config
log(`Creating Github Publisher — owner: ${githubInfo.owner}, project: ${githubInfo.repo}, version: ${version}`)
return new GitHubPublisher(githubInfo.owner!, githubInfo.repo!, version, options, isPublishOptionGuessed, githubInfo)
return new GitHubPublisher(githubInfo, version, options, isPublishOptionGuessed, githubInfo)
}
if (publishConfig.provider === "bintray") {
const bintrayInfo: BintrayOptions = config
Expand Down
2 changes: 2 additions & 0 deletions src/options/publishOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export interface PublishConfiguration {
The owner.
*/
owner?: string

token?: string
}

/*
Expand Down
6 changes: 3 additions & 3 deletions src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export class Target {
}

export abstract class TargetEx extends Target {
abstract async build(appOutDir: string, arch: Arch): Promise<any>
abstract build(appOutDir: string, arch: Arch): Promise<any>
}

export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions> {
Expand Down Expand Up @@ -537,11 +537,11 @@ export function getPublishConfigs(packager: PlatformPackager<any>, platformSpeci
return null
}

if (publishers == null && packager.info.options.githubToken != null) {
if (publishers == null && !isEmptyOrSpaces(process.env.GH_TOKEN)) {
publishers = [{provider: "github"}]
}
// if both tokens are set — still publish to github (because default publisher is github)
if (publishers == null && packager.info.options.bintrayToken != null) {
if (publishers == null && !isEmptyOrSpaces(process.env.BT_TOKEN)) {
publishers = [{provider: "bintray"}]
}
}
Expand Down
16 changes: 12 additions & 4 deletions src/publish/BintrayPublisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Promise as BluebirdPromise } from "bluebird"
import { HttpError, doApiRequest } from "./restApiRequest"
import { uploadFile } from "./uploader"
import { log } from "../util/log"
import { debug } from "../util/util"
import { debug, isEmptyOrSpaces } from "../util/util"
import { basename } from "path"
import { stat } from "fs-extra-p"
import { BintrayClient, Version } from "./bintray"
Expand All @@ -17,8 +17,16 @@ export class BintrayPublisher implements Publisher {

private readonly client: BintrayClient

constructor(private info: BintrayOptions, private version: string, private options: PublishOptions) {
this.client = new BintrayClient(info.owner!, info.package!, info.repo, options.bintrayToken)
constructor(private info: BintrayOptions, private version: string, private options?: PublishOptions) {
let token = info.token
if (isEmptyOrSpaces(token)) {
token = process.env.BT_TOKEN
if (isEmptyOrSpaces(token)) {
throw new Error(`Bintray token is not set, neither programmatically, nor using env "BT_TOKEN"`)
}
}

this.client = new BintrayClient(info.owner!, info.package!, info.repo, token)
this._versionPromise = <BluebirdPromise<Version>>this.init()
}

Expand All @@ -28,7 +36,7 @@ export class BintrayPublisher implements Publisher {
}
catch (e) {
if (e instanceof HttpError && e.response.statusCode === 404) {
if (this.options.publish !== "onTagOrDraft") {
if (this.options != null && this.options.publish !== "onTagOrDraft") {
log(`Version ${this.version} doesn't exist, creating one`)
return this.client.createVersion(this.version)
}
Expand Down
27 changes: 16 additions & 11 deletions src/publish/gitHubPublisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,22 @@ export class GitHubPublisher implements Publisher {
private readonly token: string
private readonly policy: PublishPolicy

private readonly options: PublishOptions

get releasePromise(): Promise<Release | null> {
return this._releasePromise
}

constructor(private owner: string, private repo: string, private version: string, private options: PublishOptions, private isPublishOptionGuessed: boolean = false, config?: GithubOptions | null) {
if (isEmptyOrSpaces(options.githubToken)) {
throw new Error("GitHub Personal Access Token is not specified")
constructor(private info: GithubOptions, private version: string, options?: PublishOptions, private isPublishOptionGuessed: boolean = false, config?: GithubOptions | null) {
let token = info.token
if (isEmptyOrSpaces(token)) {
token = process.env.GH_TOKEN
throw new Error(`GitHub Personal Access Token is not set, neither programmatically, nor using env "GH_TOKEN"`)
}

this.token = options.githubToken!
this.policy = options.publish || "always"
this.token = token!
this.options = options || {}
this.policy = this.options.publish || "always"

if (version.startsWith("v")) {
throw new Error(`Version must not starts with "v": ${version}`)
Expand All @@ -58,7 +63,7 @@ export class GitHubPublisher implements Publisher {
private async init(): Promise<Release | null> {
const createReleaseIfNotExists = this.policy !== "onTagOrDraft"
// we don't use "Get a release by tag name" because "tag name" means existing git tag, but we draft release and don't create git tag
const releases = await githubRequest<Array<Release>>(`/repos/${this.owner}/${this.repo}/releases`, this.token)
const releases = await githubRequest<Array<Release>>(`/repos/${this.info.owner}/${this.info.repo}/releases`, this.token)
for (let release of releases) {
if (release.tag_name === this.tag || release.tag_name === this.version) {
if (release.draft) {
Expand Down Expand Up @@ -120,10 +125,10 @@ export class GitHubPublisher implements Publisher {
if (e.response.statusCode === 422 && e.description != null && e.description.errors != null && e.description.errors[0].code === "already_exists") {
// delete old artifact and re-upload
log(`Artifact ${fileName} already exists, overwrite one`)
const assets = await githubRequest<Array<Asset>>(`/repos/${this.owner}/${this.repo}/releases/${release.id}/assets`, this.token)
const assets = await githubRequest<Array<Asset>>(`/repos/${this.info.owner}/${this.info.repo}/releases/${release.id}/assets`, this.token)
for (let asset of assets) {
if (asset!.name === fileName) {
await githubRequest<void>(`/repos/${this.owner}/${this.repo}/releases/assets/${asset!.id}`, this.token, null, "DELETE")
await githubRequest<void>(`/repos/${this.info.owner}/${this.info.repo}/releases/assets/${asset!.id}`, this.token, null, "DELETE")
continue uploadAttempt
}
}
Expand All @@ -142,7 +147,7 @@ export class GitHubPublisher implements Publisher {
}

private createRelease() {
return githubRequest<Release>(`/repos/${this.owner}/${this.repo}/releases`, this.token, {
return githubRequest<Release>(`/repos/${this.info.owner}/${this.info.repo}/releases`, this.token, {
tag_name: this.tag,
name: this.version,
draft: this.options.draft == null || this.options.draft,
Expand All @@ -153,7 +158,7 @@ export class GitHubPublisher implements Publisher {
// test only
//noinspection JSUnusedGlobalSymbols
async getRelease(): Promise<any> {
return githubRequest<Release>(`/repos/${this.owner}/${this.repo}/releases/${this._releasePromise.value().id}`, this.token)
return githubRequest<Release>(`/repos/${this.info.owner}/${this.info.repo}/releases/${this._releasePromise.value().id}`, this.token)
}

//noinspection JSUnusedGlobalSymbols
Expand All @@ -169,7 +174,7 @@ export class GitHubPublisher implements Publisher {

for (let i = 0; i < 3; i++) {
try {
return await githubRequest(`/repos/${this.owner}/${this.repo}/releases/${release.id}`, this.token, null, "DELETE")
return await githubRequest(`/repos/${this.info.owner}/${this.info.repo}/releases/${release.id}`, this.token, null, "DELETE")
}
catch (e) {
if (e instanceof HttpError && (e.response.statusCode === 405 || e.response.statusCode === 502)) {
Expand Down
2 changes: 0 additions & 2 deletions src/publish/publisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ 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
Loading

0 comments on commit b1ae7d5

Please sign in to comment.