Chore: Trying to fix CI random failure (#15461)

This commit is contained in:
Laurent Cozic authored and GitHub committed 2026-05-17 14:12:56 +01:00
1 parent b8b0545edf
commit a36b659146
2 files changed
+31 -10

No files matched your search

@@ -104,7 +104,9 @@ const buildPlugin = async (pluginId: string, repositoryData: RepositoryData, out
await options.beforeInstall(buildDir, pluginId);
logStatus('Installing dependencies.');
await execCommand('npm install');
// `npm install` occasionally crashes on Windows CI with STATUS_STACK_BUFFER_OVERRUN
// (exit code 3221226505), hence the retry.
await execCommand('npm install --no-audit --no-fund --prefer-offline', { retryCount: 3 });
const jplFiles = await glob('publish/*.jpl');
logStatus(`Found built .jpl files: ${JSON.stringify(jplFiles)}`);
+28 -9
View File
@@ -10,6 +10,8 @@ interface ExecCommandOptions {
quiet?: boolean;
env?: Record<string, string | undefined>;
detached?: boolean;
// Number of times to retry the command if it fails. 0 (the default) means no retry.
retryCount?: number;
}
export default async (command: string | string[], options: ExecCommandOptions | null = null): Promise<string> => {
@@ -24,6 +26,7 @@ export default async (command: string | string[], options: ExecCommandOptions |
showStderr: !detached,
quiet: false,
env: {},
retryCount: 0,
...options,
};
@@ -41,13 +44,29 @@ export default async (command: string | string[], options: ExecCommandOptions |
}
}
const args: string[] = typeof command === 'string' ? splitCommandString(command) : command as string[];
const executableName = args[0];
args.splice(0, 1);
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Workaround for type definition conflicts. Expo currently overrides NodeJs.ProcessEnv, making NODE_ENV required. This changes the type of the "env" argument to execa.
const promise = execa(executableName, args, { env: options.env as any });
if (options.showStdout && promise.stdout) promise.stdout.pipe(process.stdout);
if (options.showStderr && promise.stderr) promise.stderr.pipe(process.stderr);
const result = await promise;
return result.stdout.trim();
const runOnce = async () => {
const args: string[] = typeof command === 'string' ? splitCommandString(command) : [...command as string[]];
const executableName = args[0];
args.splice(0, 1);
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Workaround for type definition conflicts. Expo currently overrides NodeJs.ProcessEnv, making NODE_ENV required. This changes the type of the "env" argument to execa.
const promise = execa(executableName, args, { env: options.env as any });
if (options.showStdout && promise.stdout) promise.stdout.pipe(process.stdout);
if (options.showStderr && promise.stderr) promise.stderr.pipe(process.stderr);
const result = await promise;
return result.stdout.trim();
};
const maxAttempts = (options.retryCount ?? 0) + 1;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await runOnce();
} catch (error) {
if (attempt === maxAttempts) throw error;
stdout.write(`Command failed (attempt ${attempt}/${maxAttempts}): ${error}. Retrying...\n`);
await new Promise(resolve => setTimeout(resolve, 5000 * attempt));
}
}
// Unreachable: the loop above either returns or throws.
throw new Error('execCommand: unreachable');
};