Skip to content

Commit b1ae7d5

Browse files
committed
fix(nsis): correctly await update info writing and archive creation #529
1 parent ac5da57 commit b1ae7d5

19 files changed

+4095
-85
lines changed

.gitignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
node_modules/
22
*.log
33
out/
4-
npm-debug.log
54
dist/
65
/.idea/compiler.xml
76
/.idea/encodings.xml
@@ -14,5 +13,4 @@ dist/
1413
.DS_Store
1514
.idea/shelf/
1615
/test/typings/electron-builder.d.ts
17-
/test/typings/electron-auto-updater.d.ts
18-
/nsis-auto-updater/nm
16+
/test/typings/electron-auto-updater.d.ts

.idea/dictionaries/develar.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

nsis-auto-updater/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "electron-auto-updater",
3-
"version": "0.0.1",
3+
"version": "0.0.2",
44
"description": "NSIS Auto Updater",
55
"main": "out/nsis-auto-updater/src/main.js",
66
"author": "Vladimir Krivosheev",
@@ -14,16 +14,16 @@
1414
"dependencies": {
1515
"bluebird": "^3.4.6",
1616
"fs-extra-p": "^1.1.10",
17-
"semver": "^5.3.0",
1817
"ini": "^1.3.4",
18+
"semver": "^5.3.0",
1919
"tunnel-agent": "^0.4.3"
2020
},
2121
"bundledDependencies": [
2222
"bluebird",
2323
"fs-extra-p",
24-
"semver",
2524
"ini",
25+
"semver",
2626
"tunnel-agent"
2727
],
2828
"typings": "./out/electron-auto-updater.d.ts"
29-
}
29+
}

nsis-auto-updater/src/NsisUpdater.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,33 +83,38 @@ export class NsisUpdater extends EventEmitter {
8383
this.updateAvailable = true
8484
this.emit("update-available")
8585

86-
const mkdtemp: any = BluebirdPromise.promisify(require("fs").mkdtemp)
86+
const mkdtemp: (prefix: string) => Promise<string> = require("fs-extra-p").mkdtemp
8787
return {
8888
versionInfo: versionInfo,
8989
fileInfo: fileInfo,
9090
downloadPromise: mkdtemp(`${path.join(tmpdir(), "up")}-`)
91-
.then((it: string) => {
92-
this.setupPath = path.join(it, fileInfo.name)
93-
return download(fileInfo.url, this.setupPath)
94-
}),
91+
.then(it => download(fileInfo.url, path.join(it, fileInfo.name)))
92+
.then(it => {
93+
this.setupPath = it
94+
this.emit("update-downloaded", {}, null, versionInfo.version, null, null, () => {
95+
this.quitAndInstall()
96+
})
97+
return it
98+
})
99+
.catch(error => this.emitError(error)),
95100
}
96101
}
97102

98103
quitAndInstall(): void {
99-
const setupPath = this.setupPath
100-
if (!this.updateAvailable || setupPath == null) {
101-
this.emitError("No update available, can't quit and install")
104+
if (this.quitAndInstallCalled) {
102105
return
103106
}
104107

105-
if (this.quitAndInstallCalled) {
108+
const setupPath = this.setupPath
109+
if (!this.updateAvailable || setupPath == null) {
110+
this.emitError("No update available, can't quit and install")
106111
return
107112
}
108113

109114
// prevent calling several times
110115
this.quitAndInstallCalled = true
111116

112-
spawn(setupPath!!, ["/S"], {
117+
spawn(setupPath, ["/S"], {
113118
detached: true,
114119
stdio: "ignore",
115120
}).unref()

package.json

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@
2323
"pretest": "npm run compile && npm run lint && npm run pack-updater",
2424
"test": "node ./test/out/helpers/runTests.js",
2525
"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",
26-
"pack-updater": "cd nsis-auto-updater && npm install --production --no-bin-links && npm prune --production && cd ..",
26+
"pack-updater": "cd nsis-auto-updater && npm install --production --no-bin-links && cd ..",
2727
"semantic-release": "semantic-release pre && npm publish && semantic-release post",
2828
"//": "Update wiki if docs changed. Update only if functionalily are generally available (latest release, not next)",
2929
"update-wiki": "git subtree split -b wiki --prefix docs/ && git push -f wiki wiki:master",
3030
"whitespace": "whitespace 'src/**/*.ts'",
31-
"docker-images": "docker/build.sh"
31+
"docker-images": "docker/build.sh",
32+
"precommit": "validate-commit-msg"
3233
},
3334
"repository": "electron-userland/electron-builder",
3435
"engines": {
@@ -93,34 +94,27 @@
9394
"uuid-1345": "^0.99.6",
9495
"yargs": "^6.0.0"
9596
},
96-
"config": {
97-
"pre-git": {
98-
"commit-msg": "conventional"
99-
},
100-
"pre-commit": [
101-
"npm run whitespace"
102-
]
103-
},
10497
"devDependencies": {
10598
"@develar/semantic-release": "^6.3.6",
10699
"@types/debug": "0.0.29",
107100
"@types/mime": "0.0.29",
108101
"@types/progress": "^1.1.28",
109102
"@types/semver": "^5.3.30",
110103
"@types/source-map-support": "^0.2.28",
111-
"ava-tf": "^0.16.0",
104+
"ava-tf": "^0.16.2",
112105
"babel-plugin-array-includes": "^2.0.3",
113106
"babel-plugin-transform-es2015-destructuring": "^6.16.0",
114107
"babel-plugin-transform-es2015-parameters": "^6.17.0",
115108
"babel-plugin-transform-es2015-spread": "^6.8.0",
116109
"decompress-zip": "^0.3.0",
117110
"diff": "^3.0.1",
111+
"husky": "^0.11.9",
118112
"json8": "^0.9.2",
119113
"path-sort": "^0.1.0",
120-
"pre-git": "^3.10.0",
121114
"ts-babel": "^1.0.13",
122115
"tslint": "^3.15.1",
123116
"typescript": "^2.0.3",
117+
"validate-commit-msg": "^2.8.2",
124118
"whitespace": "^2.1.0"
125119
},
126120
"babel": {

src/builder.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -193,12 +193,6 @@ export async function build(rawOptions?: CliOptions): Promise<void> {
193193
if (options.cscInstallerKeyPassword === undefined && !isEmptyOrSpaces(process.env.CSC_INSTALLER_KEY_PASSWORD)) {
194194
options.cscInstallerKeyPassword = process.env.CSC_INSTALLER_KEY_PASSWORD
195195
}
196-
if (options.githubToken === undefined && !isEmptyOrSpaces(process.env.GH_TOKEN)) {
197-
options.githubToken = process.env.GH_TOKEN
198-
}
199-
if (options.bintrayToken === undefined && !isEmptyOrSpaces(process.env.BT_TOKEN)) {
200-
options.bintrayToken = process.env.BT_TOKEN
201-
}
202196

203197
if (options.draft === undefined && !isEmptyOrSpaces(process.env.EP_DRAFT)) {
204198
options.draft = process.env.EP_DRAFT.toLowerCase() === "true"
@@ -212,7 +206,7 @@ export async function build(rawOptions?: CliOptions): Promise<void> {
212206
if (process.env.npm_lifecycle_event === "release") {
213207
options.publish = "always"
214208
}
215-
else if (options.githubToken != null) {
209+
else if (isAuthTokenSet() ) {
216210
const tag = process.env.TRAVIS_TAG || process.env.APPVEYOR_REPO_TAG_NAME || process.env.CIRCLE_TAG
217211
if (!isEmptyOrSpaces(tag)) {
218212
log(`Tag ${tag} is defined, so artifacts will be published`)
@@ -231,7 +225,8 @@ export async function build(rawOptions?: CliOptions): Promise<void> {
231225
const publishTasks: Array<BluebirdPromise<any>> = []
232226

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

250+
function isAuthTokenSet() {
251+
return !isEmptyOrSpaces(process.env.GH_TOKEN) || !isEmptyOrSpaces(process.env.BT_TOKEN)
252+
}
253+
255254
function publishManager(packager: Packager, publishTasks: Array<BluebirdPromise<any>>, options: BuildOptions, isPublishOptionGuessed: boolean) {
256255
const nameToPublisher = new Map<string, Promise<Publisher>>()
257256
packager.artifactCreated(event => {
@@ -266,7 +265,7 @@ function publishManager(packager: Packager, publishTasks: Array<BluebirdPromise<
266265
const provider = publishConfig.provider
267266
let publisher = nameToPublisher.get(provider)
268267
if (publisher == null) {
269-
publisher = createPublisher(packager, options, publishConfig, isPublishOptionGuessed)
268+
publisher = createPublisher(packager, publishConfig, options, isPublishOptionGuessed)
270269
nameToPublisher.set(provider, publisher)
271270
}
272271

@@ -278,7 +277,7 @@ function publishManager(packager: Packager, publishTasks: Array<BluebirdPromise<
278277
})
279278
}
280279

281-
export async function createPublisher(packager: Packager, options: PublishOptions, publishConfig: PublishConfiguration | GithubOptions | BintrayOptions, isPublishOptionGuessed: boolean = false): Promise<Publisher | null> {
280+
export async function createPublisher(packager: Packager, publishConfig: PublishConfiguration | GithubOptions | BintrayOptions, options?: PublishOptions, isPublishOptionGuessed: boolean = false): Promise<Publisher | null> {
282281
const config = await getResolvedPublishConfig(packager, publishConfig, isPublishOptionGuessed)
283282
if (config == null) {
284283
return null
@@ -288,7 +287,7 @@ export async function createPublisher(packager: Packager, options: PublishOption
288287
if (publishConfig.provider === "github") {
289288
const githubInfo: GithubOptions = config
290289
log(`Creating Github Publisher — owner: ${githubInfo.owner}, project: ${githubInfo.repo}, version: ${version}`)
291-
return new GitHubPublisher(githubInfo.owner!, githubInfo.repo!, version, options, isPublishOptionGuessed, githubInfo)
290+
return new GitHubPublisher(githubInfo, version, options, isPublishOptionGuessed, githubInfo)
292291
}
293292
if (publishConfig.provider === "bintray") {
294293
const bintrayInfo: BintrayOptions = config

src/options/publishOptions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export interface PublishConfiguration {
1818
The owner.
1919
*/
2020
owner?: string
21+
22+
token?: string
2123
}
2224

2325
/*

src/platformPackager.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export class Target {
8787
}
8888

8989
export abstract class TargetEx extends Target {
90-
abstract async build(appOutDir: string, arch: Arch): Promise<any>
90+
abstract build(appOutDir: string, arch: Arch): Promise<any>
9191
}
9292

9393
export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions> {
@@ -537,11 +537,11 @@ export function getPublishConfigs(packager: PlatformPackager<any>, platformSpeci
537537
return null
538538
}
539539

540-
if (publishers == null && packager.info.options.githubToken != null) {
540+
if (publishers == null && !isEmptyOrSpaces(process.env.GH_TOKEN)) {
541541
publishers = [{provider: "github"}]
542542
}
543543
// if both tokens are set — still publish to github (because default publisher is github)
544-
if (publishers == null && packager.info.options.bintrayToken != null) {
544+
if (publishers == null && !isEmptyOrSpaces(process.env.BT_TOKEN)) {
545545
publishers = [{provider: "bintray"}]
546546
}
547547
}

src/publish/BintrayPublisher.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Promise as BluebirdPromise } from "bluebird"
33
import { HttpError, doApiRequest } from "./restApiRequest"
44
import { uploadFile } from "./uploader"
55
import { log } from "../util/log"
6-
import { debug } from "../util/util"
6+
import { debug, isEmptyOrSpaces } from "../util/util"
77
import { basename } from "path"
88
import { stat } from "fs-extra-p"
99
import { BintrayClient, Version } from "./bintray"
@@ -17,8 +17,16 @@ export class BintrayPublisher implements Publisher {
1717

1818
private readonly client: BintrayClient
1919

20-
constructor(private info: BintrayOptions, private version: string, private options: PublishOptions) {
21-
this.client = new BintrayClient(info.owner!, info.package!, info.repo, options.bintrayToken)
20+
constructor(private info: BintrayOptions, private version: string, private options?: PublishOptions) {
21+
let token = info.token
22+
if (isEmptyOrSpaces(token)) {
23+
token = process.env.BT_TOKEN
24+
if (isEmptyOrSpaces(token)) {
25+
throw new Error(`Bintray token is not set, neither programmatically, nor using env "BT_TOKEN"`)
26+
}
27+
}
28+
29+
this.client = new BintrayClient(info.owner!, info.package!, info.repo, token)
2230
this._versionPromise = <BluebirdPromise<Version>>this.init()
2331
}
2432

@@ -28,7 +36,7 @@ export class BintrayPublisher implements Publisher {
2836
}
2937
catch (e) {
3038
if (e instanceof HttpError && e.response.statusCode === 404) {
31-
if (this.options.publish !== "onTagOrDraft") {
39+
if (this.options != null && this.options.publish !== "onTagOrDraft") {
3240
log(`Version ${this.version} doesn't exist, creating one`)
3341
return this.client.createVersion(this.version)
3442
}

src/publish/gitHubPublisher.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,22 @@ export class GitHubPublisher implements Publisher {
3535
private readonly token: string
3636
private readonly policy: PublishPolicy
3737

38+
private readonly options: PublishOptions
39+
3840
get releasePromise(): Promise<Release | null> {
3941
return this._releasePromise
4042
}
4143

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

47-
this.token = options.githubToken!
48-
this.policy = options.publish || "always"
51+
this.token = token!
52+
this.options = options || {}
53+
this.policy = this.options.publish || "always"
4954

5055
if (version.startsWith("v")) {
5156
throw new Error(`Version must not starts with "v": ${version}`)
@@ -58,7 +63,7 @@ export class GitHubPublisher implements Publisher {
5863
private async init(): Promise<Release | null> {
5964
const createReleaseIfNotExists = this.policy !== "onTagOrDraft"
6065
// 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
61-
const releases = await githubRequest<Array<Release>>(`/repos/${this.owner}/${this.repo}/releases`, this.token)
66+
const releases = await githubRequest<Array<Release>>(`/repos/${this.info.owner}/${this.info.repo}/releases`, this.token)
6267
for (let release of releases) {
6368
if (release.tag_name === this.tag || release.tag_name === this.version) {
6469
if (release.draft) {
@@ -120,10 +125,10 @@ export class GitHubPublisher implements Publisher {
120125
if (e.response.statusCode === 422 && e.description != null && e.description.errors != null && e.description.errors[0].code === "already_exists") {
121126
// delete old artifact and re-upload
122127
log(`Artifact ${fileName} already exists, overwrite one`)
123-
const assets = await githubRequest<Array<Asset>>(`/repos/${this.owner}/${this.repo}/releases/${release.id}/assets`, this.token)
128+
const assets = await githubRequest<Array<Asset>>(`/repos/${this.info.owner}/${this.info.repo}/releases/${release.id}/assets`, this.token)
124129
for (let asset of assets) {
125130
if (asset!.name === fileName) {
126-
await githubRequest<void>(`/repos/${this.owner}/${this.repo}/releases/assets/${asset!.id}`, this.token, null, "DELETE")
131+
await githubRequest<void>(`/repos/${this.info.owner}/${this.info.repo}/releases/assets/${asset!.id}`, this.token, null, "DELETE")
127132
continue uploadAttempt
128133
}
129134
}
@@ -142,7 +147,7 @@ export class GitHubPublisher implements Publisher {
142147
}
143148

144149
private createRelease() {
145-
return githubRequest<Release>(`/repos/${this.owner}/${this.repo}/releases`, this.token, {
150+
return githubRequest<Release>(`/repos/${this.info.owner}/${this.info.repo}/releases`, this.token, {
146151
tag_name: this.tag,
147152
name: this.version,
148153
draft: this.options.draft == null || this.options.draft,
@@ -153,7 +158,7 @@ export class GitHubPublisher implements Publisher {
153158
// test only
154159
//noinspection JSUnusedGlobalSymbols
155160
async getRelease(): Promise<any> {
156-
return githubRequest<Release>(`/repos/${this.owner}/${this.repo}/releases/${this._releasePromise.value().id}`, this.token)
161+
return githubRequest<Release>(`/repos/${this.info.owner}/${this.info.repo}/releases/${this._releasePromise.value().id}`, this.token)
157162
}
158163

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

170175
for (let i = 0; i < 3; i++) {
171176
try {
172-
return await githubRequest(`/repos/${this.owner}/${this.repo}/releases/${release.id}`, this.token, null, "DELETE")
177+
return await githubRequest(`/repos/${this.info.owner}/${this.info.repo}/releases/${release.id}`, this.token, null, "DELETE")
173178
}
174179
catch (e) {
175180
if (e instanceof HttpError && (e.response.statusCode === 405 || e.response.statusCode === 502)) {

0 commit comments

Comments
 (0)