diff --git a/packages/app-builder-lib/src/winPackager.ts b/packages/app-builder-lib/src/winPackager.ts index d7ad40ad5d3..b81d7d2f94e 100644 --- a/packages/app-builder-lib/src/winPackager.ts +++ b/packages/app-builder-lib/src/winPackager.ts @@ -317,7 +317,7 @@ export class WinPackager extends PlatformPackager { const timer = time("wine&sign") // rcedit crashed of executed using wine, resourcehacker works if (process.platform === "win32" || this.info.framework.name === "electron") { - await executeAppBuilder(["rcedit", "--args", JSON.stringify(args)]) + await executeAppBuilder(["rcedit", "--args", JSON.stringify(args)], undefined /* child-process */, {}, 3 /* retry five times */) } await this.sign(file) diff --git a/packages/builder-util/src/util.ts b/packages/builder-util/src/util.ts index f0e49c6b980..fde4441802b 100644 --- a/packages/builder-util/src/util.ts +++ b/packages/builder-util/src/util.ts @@ -334,36 +334,61 @@ export class InvalidConfigurationError extends Error { } } -export function executeAppBuilder(args: Array, childProcessConsumer?: (childProcess: ChildProcess) => void, extraOptions: SpawnOptions = {}): Promise { - return new Promise((resolve, reject) => { - const command = appBuilderPath - const env: any = { - ...process.env, - SZA_PATH: path7za, - FORCE_COLOR: chalk.level === 0 ? "0" : "1", - } - const cacheEnv = process.env.ELECTRON_BUILDER_CACHE - if (cacheEnv != null && cacheEnv.length > 0) { - env.ELECTRON_BUILDER_CACHE = path.resolve(cacheEnv) - } +export function executeAppBuilder(args: Array, childProcessConsumer?: (childProcess: ChildProcess) => void, extraOptions: SpawnOptions = {}, maxRetries = 0): Promise { + const command = appBuilderPath + const env: any = { + ...process.env, + SZA_PATH: path7za, + FORCE_COLOR: chalk.level === 0 ? "0" : "1", + } + const cacheEnv = process.env.ELECTRON_BUILDER_CACHE + if (cacheEnv != null && cacheEnv.length > 0) { + env.ELECTRON_BUILDER_CACHE = path.resolve(cacheEnv) + } - if (extraOptions.env != null) { - Object.assign(env, extraOptions.env) - } + if (extraOptions.env != null) { + Object.assign(env, extraOptions.env) + } - const childProcess = doSpawn(command, args, { - env, - stdio: ["ignore", "pipe", process.stdout], - ...extraOptions, - }) - if (childProcessConsumer != null) { - childProcessConsumer(childProcess) - } - handleProcess("close", childProcess, command, resolve, error => { - if (error instanceof ExecError && error.exitCode === 2) { - error.alreadyLogged = true + function runCommand() { + return new Promise((resolve, reject) => { + const childProcess = doSpawn(command, args, { + env, + stdio: ["ignore", "pipe", process.stdout], + ...extraOptions + }) + if (childProcessConsumer != null) { + childProcessConsumer(childProcess) } - reject(error) + handleProcess("close", childProcess, command, resolve, error => { + if (error instanceof ExecError && error.exitCode === 2) { + error.alreadyLogged = true + } + reject(error) + }) }) - }) + } + + if (maxRetries === 0) { + return runCommand() + } + else { + return retry(runCommand, maxRetries, 1000) + } } + +async function retry(task: () => Promise, retriesLeft: number, interval: number): Promise { + try { + return await task() + } + catch (error) { + log.info(`Above command failed, retrying ${retriesLeft} more times`) + if (retriesLeft > 0) { + await new Promise(resolve => setTimeout(resolve, interval)) + return await retry(task, retriesLeft - 1, interval) + } + else { + throw error + } + } +} \ No newline at end of file