From 4834e0d8f31d381a8120562ad359a396b6f05f22 Mon Sep 17 00:00:00 2001 From: Caleb Ukle Date: Wed, 15 Oct 2025 09:49:30 -0500 Subject: [PATCH] fix(checkout): improve debug-ability of checkout step if a command hangs it can be tricky to know what is going on so we: 1. force using stdio: inherit (even though it _should_ be default) 2. log before each command to know where in the steps we are unrelated, but refactored to pass command string to execSync inside runWithRetries instead of passing `() => execSync(command)` every time --- workflow-steps/checkout/main.ts | 32 +++++++++++++++---------- workflow-steps/checkout/output/main.js | 33 ++++++++++++++++---------- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/workflow-steps/checkout/main.ts b/workflow-steps/checkout/main.ts index 1624179..4bbf846 100644 --- a/workflow-steps/checkout/main.ts +++ b/workflow-steps/checkout/main.ts @@ -9,11 +9,19 @@ const maxRetries = 3; async function main() { if (process.platform != 'win32') { - execSync(`git config --global --add safe.directory $PWD`); + runWithRetries( + `git config --global --add safe.directory $PWD`, + 'set safe directory', + 1, + ); } - execSync('git init .'); - execSync(`git remote add origin ${repoUrl}`); - execSync(`echo "GIT_REPOSITORY_URL=''" >> $NX_CLOUD_ENV`); + runWithRetries('git init .', 'git init', 1); + runWithRetries(`git remote add origin ${repoUrl}`, 'git remote add', 1); + runWithRetries( + `echo "GIT_REPOSITORY_URL=''" >> $NX_CLOUD_ENV`, + 'persist git url', + 1, + ); let fetchCommand: string; if (commitSha.startsWith('origin/')) { @@ -28,25 +36,22 @@ async function main() { } } - await runWithRetries(() => execSync(fetchCommand), 'git fetch', maxRetries); + await runWithRetries(fetchCommand, 'git fetch', maxRetries); const checkoutCommand = `git checkout --progress --force -B ${nxBranch} ${commitSha}`; - await runWithRetries( - () => execSync(checkoutCommand), - 'git checkout', - maxRetries, - ); + await runWithRetries(checkoutCommand, 'git checkout', maxRetries); } async function runWithRetries( - fn: () => void, + command: string, label: string, maxRetriesLocal: number, ) { let attempt = 0; while (attempt < maxRetriesLocal) { try { - fn(); + console.log(`\n--- ${command} attempt ${attempt + 1} ---`); + execSync(command, { stdio: 'inherit' }); return; } catch (e) { attempt++; @@ -54,8 +59,9 @@ async function runWithRetries( if (attempt >= maxRetriesLocal) { throw e; } + const jitter = Math.floor(Math.random() * 1_000); + const delayMs = (attempt === 1 ? 10_000 : 60_000) + jitter; - const delayMs = attempt === 1 ? 10_000 : 60_000; const stderr = (e as any)?.stderr?.toString?.() || ''; const stdout = (e as any)?.stdout?.toString?.() || ''; if (stderr) { diff --git a/workflow-steps/checkout/output/main.js b/workflow-steps/checkout/output/main.js index 720ca67..dd9e64f 100644 --- a/workflow-steps/checkout/output/main.js +++ b/workflow-steps/checkout/output/main.js @@ -8,11 +8,19 @@ var fetchTags = process.env.GIT_FETCH_TAGS === "true"; var maxRetries = 3; async function main() { if (process.platform != "win32") { - (0, import_child_process.execSync)(`git config --global --add safe.directory $PWD`); + runWithRetries( + `git config --global --add safe.directory $PWD`, + "set safe directory", + 1 + ); } - (0, import_child_process.execSync)("git init ."); - (0, import_child_process.execSync)(`git remote add origin ${repoUrl}`); - (0, import_child_process.execSync)(`echo "GIT_REPOSITORY_URL=''" >> $NX_CLOUD_ENV`); + runWithRetries("git init .", "git init", 1); + runWithRetries(`git remote add origin ${repoUrl}`, "git remote add", 1); + runWithRetries( + `echo "GIT_REPOSITORY_URL=''" >> $NX_CLOUD_ENV`, + "persist git url", + 1 + ); let fetchCommand; if (commitSha.startsWith("origin/")) { fetchCommand = `git fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 origin ${nxBranch}`; @@ -24,26 +32,25 @@ async function main() { fetchCommand = `git fetch ${tagsArg} --prune --progress --no-recurse-submodules --depth=${depth} origin ${commitSha}`; } } - await runWithRetries(() => (0, import_child_process.execSync)(fetchCommand), "git fetch", maxRetries); + await runWithRetries(fetchCommand, "git fetch", maxRetries); const checkoutCommand = `git checkout --progress --force -B ${nxBranch} ${commitSha}`; - await runWithRetries( - () => (0, import_child_process.execSync)(checkoutCommand), - "git checkout", - maxRetries - ); + await runWithRetries(checkoutCommand, "git checkout", maxRetries); } -async function runWithRetries(fn, label, maxRetriesLocal) { +async function runWithRetries(command, label, maxRetriesLocal) { let attempt = 0; while (attempt < maxRetriesLocal) { try { - fn(); + console.log(` +--- ${command} attempt ${attempt + 1} ---`); + (0, import_child_process.execSync)(command, { stdio: "inherit" }); return; } catch (e) { attempt++; if (attempt >= maxRetriesLocal) { throw e; } - const delayMs = attempt === 1 ? 1e4 : 6e4; + const jitter = Math.floor(Math.random() * 1e3); + const delayMs = (attempt === 1 ? 1e4 : 6e4) + jitter; const stderr = e?.stderr?.toString?.() || ""; const stdout = e?.stdout?.toString?.() || ""; if (stderr) {