Uh oh!
There was an error while loading. Please reload this page.
ci: materialise pnpm from a cached Corepack store instead of downloading per job - #11370
Merged
Merged
Conversation
…ing per job `corepack enable` only writes shims; the pnpm tarball is fetched from registry.npmjs.org on the first pnpm invocation in the job. A merge-queue build is 24 jobs, so one merge attempt made 24 independent registry calls before any test ran, and any one of them could eject the PR and force every PR behind it to rebuild. Add a `.github/actions/setup-pnpm` composite action that restores the Corepack store (COREPACK_HOME) from the actions cache, keyed on the packageManager pin, then materialises pnpm from it. A warm store makes the happy path fully network-free. A bounded retry covers the cold-cache case only. Applied uniformly to all 7 Corepack sites in ci.yml, including the one at the temporal-conformance job that had no paired verify step. `actions/setup-node` deliberately stays in the workflow at all 7 sites: scripts/check-node-version.mjs scans .github/workflows/*.yml only and reports how many setup-node steps it audited, so moving those steps into the composite would drop them from its census while it still printed OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx
This was referenced Aug 23, 2026
os-steve
marked this pull request as ready for review
August 23, 2026 14:53
Uh oh!
There was an error while loading. Please reload this page.
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
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Fixes#11300
Measurement first
The card asked how many recent queue failures actually carry this signature. Measured over
merge_groupruns from2026-08-21T00:45Zto2026-08-23T09:02Z, classified at step levelvia the jobs API (not by log grep, so nothing is missed for want of a parseable test name):
merge_groupruns in windowPer-job crash rate 0.046%; across 24 draws that is 1.11% per queue build, predicting
5.0 ejection-causing builds over the window against 4 observed. The premise holds — this
is a recurring ~2/day tax, not a one-off.
Verify pnpm versionis a sound proxy: it runs onlypnpm --version, so the only way it failsis Corepack materialisation.
The card's signature undercounts the defect by one failure mode. Four of the five carry the
undici assertion; the fifth is the same Corepack download failing differently:
So the right frame is "Corepack downloads pnpm per job", not "undici has a bug" — the
assertion is one of at least two ways that download dies.
Amplification worth naming: each primary crash also reds the aggregator gates downstream, which
fail on the missing shard attestation (
test-4-of-6 MISSING) rather than on anything real.One network hiccup manufactures several red checks.
File surface — the card undercounted it
The card named three
Verify pnpm versionsites. The tree has six, plus sevencorepack enable, the seventh (temporal-conformance) having no paired verify step. All sevenare changed; a three-site patch would have left four live and made the survivors look deliberate.
The fix
.github/actions/setup-pnpmrestores the Corepack store (COREPACK_HOME) from the actionscache, keyed on the
packageManagerpin, then materialises pnpm from it. A warm store nevercontacts the registry.
Why this and not the alternatives.
restore is a different failure domain (GitHub's own cache service) and is non-fatal — a
restore failure degrades to a download rather than failing the job.
setup-nodepackageManager-aware caching (rejected). That caches the pnpm store(dependencies), not the pnpm binary; this repo already does it in the adjacent
Setup pnpm cachesteps, and it did not prevent any of the five failures.symptom and leaves the exposure intact. It is kept strictly as the cold-cache backstop,
which matters only on the first build after a
packageManagerbump, when every job misses atonce.
.nvmrcandcheck:node-version; the crash is in that major's bundled undici, and the ECONNRESET variantshows the download is fragile regardless of which crash mode Node happens to produce.
actions/setup-nodedeliberately stays in the workflow at all 7 sites.scripts/check-node-version.mjsscans.github/workflows/*.ymlonly, and reports how manysetup-node steps it audited. Folding those steps into the composite would have dropped 7 from its
census while it still printed
OK— a gate silently auditing less than it claims. Its reading isunchanged: 32 setup-node steps across 26 workflows, before and after.
What the local evidence covers, and what only the queue can prove
Proven locally (mechanism, with a live control):
installVersion/fetchTarballURLAndSignature— the same code path as the CI crashcorepack installandpnpm --versionboth exit 0,10.31.0::warning::/::error::annotations, exit 1 — a permanent failure is not maskedThe composite's two shell bodies were extracted from the shipped
action.ymland executedagainst a simulated Actions environment (
GITHUB_OUTPUT/GITHUB_ENV/RUNNER_TEMP), so thetested text is the shipped text.
Only the queue can prove: that
actions/cacherestores this path across real runners, thereal cache hit rate under 24-way concurrency, and the first cold-key build (24 simultaneous
misses, each saving ~22MB — expected once per
packageManagerbump).Gates
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackderived 10 families fromthe real changeset. All 10 green, plus
check:nul-bytes, re-run at final commit5742da3:Repo-wide
pnpm lintis provably irrelevant to this diff rather than skipped: eslint's ownconfig reports
File ignored because no matching configuration was suppliedfor both changedpaths, so neither is in the linted population, and since the diff changes only
.ymlno verdicton any untouched file can move.
Scope
lint.yml(5 sites) andspec-liveness-check.yml(1 site) carry the same defect — together theother 7 of the 24 jobs in a queue build — but are outside this card's declared file surface.
Filed separately as #11369 so the composite can be adopted there without widening this PR.
Generated by Claude Code