Skip to content

Commit 645e2ab

Browse files
authored
fix: remove concurrency of windows codesign to resolve azure trusted signing file locks(#8632)
1 parent 96f5c3e commit 645e2ab

3 files changed

Lines changed: 38 additions & 34 deletions

File tree

.changeset/sour-points-refuse.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"app-builder-lib": patch
3+
---
4+
5+
fix: only sign concurrently when using local signtool. azure can't be in parallel due to resources being locked during usage

packages/app-builder-lib/src/codeSign/windowsCodeSign.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { log } from "builder-util"
1+
import { log, retry } from "builder-util"
22
import { WindowsConfiguration } from "../options/winOptions"
33
import { VmManager } from "../vm/vm"
44
import { WinPackager } from "../winPackager"
@@ -11,7 +11,8 @@ export interface WindowsSignOptions {
1111
export async function signWindows(options: WindowsSignOptions, packager: WinPackager): Promise<boolean> {
1212
if (options.options.azureSignOptions) {
1313
log.info({ path: log.filePath(options.path) }, "signing with Azure Trusted Signing (beta)")
14-
return (await packager.azureSignManager.value).signUsingAzureTrustedSigning(options)
14+
const packageManager = await packager.azureSignManager.value
15+
return signWithRetry(async () => packageManager.signUsingAzureTrustedSigning(options))
1516
}
1617

1718
log.info({ path: log.filePath(options.path) }, "signing with signtool.exe")
@@ -34,7 +35,24 @@ export async function signWindows(options: WindowsSignOptions, packager: WinPack
3435
if (fields.length) {
3536
log.warn({ fields, reason: "please move to win.signtoolOptions.<field_name>" }, `deprecated field`)
3637
}
37-
return (await packager.signtoolManager.value).signUsingSigntool(options)
38+
const packageManager = await packager.signtoolManager.value
39+
return signWithRetry(async () => packageManager.signUsingSigntool(options))
40+
}
41+
42+
function signWithRetry(signer: () => Promise<boolean>): Promise<boolean> {
43+
return retry(signer, 3, 1000, 1000, 0, (e: any) => {
44+
const message = e.message
45+
if (
46+
// https://github.com/electron-userland/electron-builder/issues/1414
47+
message?.includes("Couldn't resolve host name") ||
48+
// https://github.com/electron-userland/electron-builder/issues/8615
49+
message?.includes("being used by another process.")
50+
) {
51+
log.warn({ error: message }, "attempt to sign failed, another attempt will be made")
52+
return true
53+
}
54+
return false
55+
})
3856
}
3957

4058
export async function getPSCmd(vm: VmManager): Promise<string> {

packages/app-builder-lib/src/winPackager.ts

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import BluebirdPromise from "bluebird-lst"
2-
import { Arch, InvalidConfigurationError, log, use, executeAppBuilder, CopyFileTransformer, FileTransformer, walk, retry } from "builder-util"
1+
import { Arch, CopyFileTransformer, executeAppBuilder, FileTransformer, InvalidConfigurationError, use, walk } from "builder-util"
32
import { createHash } from "crypto"
43
import { readdir } from "fs/promises"
54
import * as isCI from "is-ci"
65
import { Lazy } from "lazy-val"
76
import * as path from "path"
7+
import { signWindows, WindowsSignOptions } from "./codeSign/windowsCodeSign"
8+
import { WindowsSignAzureManager } from "./codeSign/windowsSignAzureManager"
89
import { FileCodeSigningInfo, getSignVendorPath, WindowsSignToolManager } from "./codeSign/windowsSignToolManager"
910
import { AfterPackContext } from "./configuration"
1011
import { DIR_TARGET, Platform, Target } from "./core"
@@ -23,9 +24,6 @@ import { isBuildCacheEnabled } from "./util/flags"
2324
import { time } from "./util/timer"
2425
import { getWindowsVm, VmManager } from "./vm/vm"
2526
import { execWine } from "./wine"
26-
import { signWindows } from "./codeSign/windowsCodeSign"
27-
import { WindowsSignOptions } from "./codeSign/windowsCodeSign"
28-
import { WindowsSignAzureManager } from "./codeSign/windowsSignAzureManager"
2927

3028
export class WinPackager extends PlatformPackager<WindowsConfiguration> {
3129
_iconPath = new Lazy(() => this.getOrConvertIcon("ico"))
@@ -128,7 +126,7 @@ export class WinPackager extends PlatformPackager<WindowsConfiguration> {
128126
options: this.platformSpecificBuildOptions,
129127
}
130128

131-
const didSignSuccessfully = await this.doSign(signOptions)
129+
const didSignSuccessfully = await signWindows(signOptions, this)
132130
if (!didSignSuccessfully && this.forceCodeSigning) {
133131
throw new InvalidConfigurationError(
134132
`App is not signed and "forceCodeSigning" is set to true, please ensure that code signing configuration is correct, please see https://electron.build/code-signing`
@@ -137,25 +135,6 @@ export class WinPackager extends PlatformPackager<WindowsConfiguration> {
137135
return didSignSuccessfully
138136
}
139137

140-
private async doSign(options: WindowsSignOptions) {
141-
return retry(
142-
() => signWindows(options, this),
143-
3,
144-
500,
145-
500,
146-
0,
147-
(e: any) => {
148-
// https://github.com/electron-userland/electron-builder/issues/1414
149-
const message = e.message
150-
if (message != null && message.includes("Couldn't resolve host name")) {
151-
log.warn({ error: message }, `cannot sign`)
152-
return true
153-
}
154-
return false
155-
}
156-
)
157-
}
158-
159138
async signAndEditResources(file: string, arch: Arch, outDir: string, internalName?: string | null, requestedExecutionLevel?: RequestedExecutionLevel | null) {
160139
const appInfo = this.appInfo
161140

@@ -267,20 +246,20 @@ export class WinPackager extends PlatformPackager<WindowsConfiguration> {
267246
return false
268247
}
269248

270-
await BluebirdPromise.map(readdir(packContext.appOutDir), (file: string): any => {
249+
const files = await readdir(packContext.appOutDir)
250+
for (const file of files) {
271251
if (file === exeFileName) {
272-
return this.signAndEditResources(
252+
await this.signAndEditResources(
273253
path.join(packContext.appOutDir, exeFileName),
274254
packContext.arch,
275255
packContext.outDir,
276256
path.basename(exeFileName, ".exe"),
277257
this.platformSpecificBuildOptions.requestedExecutionLevel
278258
)
279259
} else if (this.shouldSignFile(file)) {
280-
return this.sign(path.join(packContext.appOutDir, file))
260+
await this.sign(path.join(packContext.appOutDir, file))
281261
}
282-
return null
283-
})
262+
}
284263

285264
if (!isAsar) {
286265
return true
@@ -291,7 +270,9 @@ export class WinPackager extends PlatformPackager<WindowsConfiguration> {
291270
return walk(outDir, (file, stat) => stat.isDirectory() || this.shouldSignFile(file))
292271
}
293272
const filesToSign = await Promise.all([filesPromise(["resources", "app.asar.unpacked"]), filesPromise(["swiftshader"])])
294-
await BluebirdPromise.map(filesToSign.flat(1), file => this.sign(file), { concurrency: 4 })
273+
for (const file of filesToSign.flat(1)) {
274+
await this.sign(file)
275+
}
295276

296277
return true
297278
}

0 commit comments

Comments
 (0)