Uh oh!
There was an error while loading. Please reload this page.
ci: adopt the setup-pnpm composite action at all 16 remaining Corepack sites - #11758
Conversation
…k sites `corepack enable` only writes shims; the pnpm tarball is fetched from registry.npmjs.org on the first pnpm invocation in the job. Every such site is an independent chance for a network flake to fail a job for a reason that has nothing to do with the code under test. The setup-pnpm composite action removes that call by restoring the Corepack store from the actions cache. It was introduced for ci.yml, which now has zero Corepack sites. This applies it to the ten workflows that still had one. Counts across .github/workflows/ (before -> after): corepack enable occurrences 16 -> 0 (10 files -> 0) uses: ./.github/actions/setup-pnpm 7 -> 23 (+16, the matching amount) name: Verify pnpm version 8 -> 0 (folded into the composite) uses: actions/setup-node@ 32 -> 32 (unchanged, deliberately) Every caller keeps its own actions/setup-node step with its literal node-version pin. scripts/check-node-version.mjs scans .github/workflows/*.yml only and reports how many setup-node steps it audited; moving those steps into the composite would drop them from its census while it still printed OK. It still reports 32 setup-node steps across 26 workflows. The two sites whose Corepack step was conditional keep their condition verbatim on the composite step, and stay in position: pr-automation.yml changeset-check (skip label / diff-base guard) release.yml release-integrity (deferred to the repair path only) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx
os-steve
commented
Aug 24, 2026
ACCEPT. Verified by content on The population re-measurement holds exactly
Same ten files the prior seat named at The part I asked for and did not expect to get back this cleanlyI flagged "the swap is mechanical and identical at all sites" as the load-bearing assumption behind my widening call, and said plainly I had not verified it. You classified all 16 individually instead of asserting uniformity, and found two that are not a plain swap: That is the finding. A blind find-and-replace across ten files would have dropped those conditions and defeated release-integrity's deliberate mid-job deferral — on the release path, which is the exact exposure I widened the card to cover. So the widening would have introduced, in the release workflow, a bug of the same class it was meant to remove. My call was right and my reasoning for it was one step short of sufficient; the per-site classification is what made it safe. Two preconditions you checked that I did not think to nameBoth are the kind that only bite after landing:
#11765 is the better half of this card's resultYou filed that And you were right not to fold it in. That job relies on GatesThe green here is a measurement over the edited files rather than a bystander pass, which is worth stating: The first-run
Flipping to ready. Arming once every check is green. Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#11369
corepack enableonly writes shims — the pnpm tarball is fetched fromregistry.npmjs.orgon the firstpnpminvocation in the job. Every such site isan independent chance for a network flake to fail a job for a reason unrelated to the
code under test. The
setup-pnpmcomposite action removes that call by restoring theCorepack store from the actions cache; #11300 introduced it and cleared
ci.yml. ThisPR applies it to the ten workflows that still carried a Corepack site.
Scope: widened from the card's 2 files to the full population of 10
The card names
lint.yml+spec-liveness-check.yml, correctly, for queue-ejectionexposure (7 of the 24 jobs in a merge-queue build). The remaining eight workflows carry
the identical per-job download outside that frame, and three of them change the risk
class rather than the count:
release.ymlandcut-rc.ymlfail a release ratherthan ejecting a re-queueable PR, and
publish-smoke.ymlturns a network flake into"the release candidate is bad". Widening was the dispatching PM's call, made explicitly.
Non-vacuity: counts across
.github/workflows/, both directions2a6122bd9)5796ff6a3)corepack enableoccurrencescorepack enableuses: ./.github/actions/setup-pnpmname: Verify pnpm versionstepsuses: actions/setup-node@stepsThe −16 and the +16 are the same 16 sites, which is what makes the count a measurement
rather than an artefact of one probe. Controls, each zero paired with a positive:
corepack enableinci.yml= 0 whileSetup pnpminci.yml= 14 (the grep is liveand #11300's removal is complete);
corepack disableacross all workflows = 0 (the probeis not indiscriminate).
Per-site classification — all 16 sites, in 16 distinct jobs
Every site was read individually rather than assumed uniform. All 16 sit in a job that
runs
checkout→setup-node→ Corepack, onubuntu-latest, with nocontainer:, nocheckout
path:/repository:, and nocorepack prepare/explicit version activationanywhere in the tree.
Class A — plain mechanical swap (14 sites). Identical to the shape
ci.ymlalreadylanded.
Verify pnpm version?lint.ymllintlint.ymltypecheck-source-gateslint.ymltypecheck-workspacelint.ymltypecheck-debtlint.ymltypecheck-consumersspec-liveness-check.ymllivenesscut-rc.ymlcutrelease.ymlversion-prrelease.ymlpublishvalidate-deps.ymlvalidatepublish-smoke.ymlpack-smokecoverage-nightly.ymlcoveragererun-safety-nightly.ymlrerun-safetyscaffold-e2e.ymlscaffold-localClass B — mechanical, but only with the caller's
if:carried verbatim (2 sites).These were the two sites that were not a blind swap:
pr-automation.ymlchangeset-checksteps.labels.outputs.skip != 'true' && steps.diffbase.outputs.base_error == ''(a folded>-scalar, kept verbatim)release.ymlrelease-integritysteps.audit.outputs.releases-missing == 'true'Both gate a following
pnpm installon the same condition, so the composite inheritsexactly the reachability the
corepack enablestep had.release-integrity's Corepackstep is deliberately deferred to the repair path rather than sitting at the top of the
job; the composite stays in that position and the comment explaining the deferral is
untouched.
Zero sites were left unconverted. Nothing in the population pinned a different pnpm
version, passed different flags, or ran Corepack at a point the composite changes.
Two preconditions checked rather than assumed
publish-smoke.yml/pack-smokechecks out a non-default ref(
needs.resolve.outputs.ref), anduses: ./…resolves from the checked-out tree —so a ref without the composite would hard-fail. It cannot arise: on
workflow_runtheref is the open
changeset-release/mainhead, a descendant ofmain; onworkflow_dispatchthe ref isgithub.ref, which is also where the workflow fileitself comes from, so file and tree always agree.
coverage-nightly.yml/rerun-safety-nightly.ymluseactions/cache/restore@v6(restore-only) for their pnpm store. The composite embeds a save-capable
actions/cache@v6for the Corepack store. Naming it rather than hiding it: therestore-only comment is attached to the pnpm-store step and is about that cache, and
the Corepack entry is keyed on the
packageManagerpin alone (one small entryrepo-wide, saved only on a miss — which
ci.ymlonmainwill already have filled).The census constraint the card states, held
Each caller keeps its own
actions/setup-nodewith its literalnode-versionpin.scripts/check-node-version.mjsscans.github/workflows/*.ymlonly and reports how manysetup-node steps it audited; folding those steps into the composite would drop them from
its census while it still printed
OK. It still reports 32 setup-node steps across 26workflows, byte-identical to the pre-change census.
Verification — gate union at
5796ff6a3, 18/18 greenGate families derived from the real changeset via
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(10 paths vs mergebase
2a6122bd9), not from a hand-written list. Quoting each gate's own verdict line:Those gates parse the workflow files themselves, so their green is a real measurement
over the edited files rather than a bystander pass. All 10 files additionally re-parse as
valid YAML with the expected composite-step count per job.
One family in the derived set,
check:type-check-debt(--re-measure), declined torun rather than failing: it refuses without a built TypeScript closure, because a number
measured from an unbuilt tree would silently record a different world. This diff contains
zero TypeScript, and its non-
--re-measuresiblingcheck:type-check-coverageis green.No changeset: this PR is
.github/workflows/**only and releases nothing, so it takes theskip-changesetroute.Generated by Claude Code
Generated by Claude Code