-
Notifications
You must be signed in to change notification settings - Fork 5.1k
ci: fail loudly when artifact download times out #29039
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔴 The PR only checks
error === "timeout"but does not check theokfield, leaving all other spawnSafe failure modes (non-zero exit codes like"code 1","spawn error", signals like"SIGKILL") silently ignored. When buildkite-agent artifact download fails for any non-timeout reason, the code falls through toreaddirSync(releasePath)and — if a stale or partial zip exists from a prior run or an earlier loop iteration — breaks out of the download loop and proceeds to use that wrong binary. This is the exact silent fallback the PR description says it wants to prevent; the fix only closes it for the timeout case. To fix, also captureokand throw when!ok:const { ok, error } = await spawnSafe({...}); if (!ok) { throw new Error(...); }Extended reasoning...
What the bug is and how it manifests
The PR introduces a check for
error === "timeout"after callingspawnSafeforbuildkite-agent artifact download, but it never checks theokfield thatspawnSafereturns. Theokfield isexitCode === 0 && !signalCode && !spawnError— so it isfalsefor any non-zero exit code, spawn errors, and signals, not just timeouts. Whenbuildkite-agentexits non-zero for reasons other than the 120 s timeout (authentication failure, a transient network reset that causes exit code 1, an internal buildkite-agent timeout returning a signal, etc.), the code silently swallows the error and drops straight intoreaddirSync(releasePath).The specific code path that triggers it
At lines 1975-1988, the destructuring
const { error } = await spawnSafe(...)discards theokfield. Only theerror === "timeout"case is handled. All other failure values forerror("code 1", "spawn error", "SIGKILL", etc.) cause the code to fall through directly toreaddirSync(releasePath). If any zip is found there,zipPathis set,break downloadLoopfires, and the stale artifact is used.Why existing code does not prevent it
The final safety check (
throw new Error("Could not find ${target}.zip")) only fires whenzipPathis undefined after all 10 iterations. If any zip file is present inreleasePath— from a previous CI build (Buildkite agents commonly reuse workspaces), from a partial write by a prior loop iteration, or from a prior run of the same job — thereaddirSynccall finds it and the loop breaks immediately with that stale artifact. The sort logic preferring*-profile.zipmirrors the exact scenario from the PR description (profile zip vs release zip).Step-by-step proof of the scenario
release/directory already containsbun-windows-x64.zipfrom the previous build.buildkite-agent artifact downloadstarts downloading but exits with code 1 (e.g., network reset mid-transfer, or an auth error).spawnSafereturns{ ok: false, error: "code 1", ... }.if (error === "timeout")check is false — no throw.readdirSync(releasePath)findsbun-windows-x64.zip(the stale one from the previous build).zipPathis set,break downloadLoopfires.bun.exefrom the previous build is used for the entire test run — exactly the "silently fell back to the wrong binary" scenario the PR description explicitly called out.What the impact would be
CI jobs would silently use the wrong binary (wrong commit, wrong profile/release variant) and potentially report misleading test results — the same class of failure the PR was written to fix. The error is completely invisible in the logs since
spawnSafedoes not throw.How to fix it
Capture and check
okalongsideerror:This closes the gap for all failure modes, not just timeouts. If retry behavior is desired for transient non-timeout failures, the loop should at minimum
continuerather than fall through toreaddirSyncso that a stale zip is never used.