Skip to content

Commit

Permalink
fix(builder-util): Retry flaky builder operations
Browse files Browse the repository at this point in the history
Close #4657
  • Loading branch information
abettadapur authored and develar committed Mar 3, 2020
1 parent 07693b3 commit b03f2c1
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 29 deletions.
2 changes: 1 addition & 1 deletion packages/app-builder-lib/src/winPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ export class WinPackager extends PlatformPackager<WindowsConfiguration> {
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)
Expand Down
81 changes: 53 additions & 28 deletions packages/builder-util/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,36 +334,61 @@ export class InvalidConfigurationError extends Error {
}
}

export function executeAppBuilder(args: Array<string>, childProcessConsumer?: (childProcess: ChildProcess) => void, extraOptions: SpawnOptions = {}): Promise<string> {
return new Promise<string>((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<string>, childProcessConsumer?: (childProcess: ChildProcess) => void, extraOptions: SpawnOptions = {}, maxRetries = 0): Promise<string> {
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<string>((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<T>(task: () => Promise<T>, retriesLeft: number, interval: number): Promise<T> {
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
}
}
}

0 comments on commit b03f2c1

Please sign in to comment.