Repository navigation
ci: pin credential-holding third-party actions by sha, and pass the Turbo cache credentials only to merge-queue and main runs - #25559
Merged
Conversation
docker/setup-qemu-action, docker/setup-buildx-action, docker/login-action, docker/metadata-action and docker/build-push-action in docker-publish.yml (a packages: write job), lycheeverse/lychee-action in check-links.yml and dorny/paths-filter in ci.yml each name the commit their floating major resolved to, with a trailing version comment, as release.yml already does for changesets/action. Claude-Session: https://claude.ai/code/session_01W9H2WdXx3kPkf6moDnRdRE Co-authored-by: Claude <noreply@anthropic.com>
…ain runs TURBO_TOKEN and TURBO_REMOTE_CACHE_SIGNATURE_KEY now reach a carrier only on merge_group or a run on refs/heads/main, in all twelve carriers (ci.yml x7, lint.yml x5). A pull_request run builds from the restored Actions-cache seed; `remote:r` was a client setting, while the token can write and the key can sign. assert-turbo-remote-cache reports such a run as a notice (credentials withheld by design) instead of a warning, with a self-test battery for the condition. Claude-Session: https://claude.ai/code/session_01W9H2WdXx3kPkf6moDnRdRE Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W9H2WdXx3kPkf6moDnRdRE Co-authored-by: Claude <noreply@anthropic.com>
os-zhuang
approved these changes
Oct 24, 2026
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 free
to 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.
Requested by Tesla · project thread
CI supply-chain hardening, two commits that can land or be dropped independently:
96212c2).7ea2af7).1. Third-party actions pinned by sha
Each names the commit its floating major resolved to when this was written (read with
git ls-remoteagainst the upstream repository), with a trailing version comment, the formrelease.ymlalready uses forchangesets/action.docker-publish.ymldocker/setup-qemu-action@v499012661954931238ded8c8b007157a8430204e1# v4.4.0packages: writejobdocker-publish.ymldocker/setup-buildx-action@v4f87e5991a6d7451dcb8d9637bfbc97413f497069# v4.4.1packages: writejobdocker-publish.ymldocker/login-action@v481c6f93d4bc991e510b342a00b419b3bb4efc5c6# v4.7.0GITHUB_TOKENas registry passworddocker-publish.ymldocker/metadata-action@v6dc802804100637a589fabce1cb79ff13a1411302# v6.2.0packages: writejobdocker-publish.ymldocker/build-push-action@v7c3c9e263c25d99ce0380d002d59b67737d91b0dc# v7.4.0check-links.yml(2 steps)lycheeverse/lychee-action@v2e7477775783ea5526144ba13e8db5eec57747ce8# v2.9.0tokeninput defaults to the job tokenci.yml(filter job)dorny/paths-filter@v4ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d# v4.0.3tokeninput defaults to the job tokenAlready pinned and untouched:
changesets/action(release.yml),google/osv-scanner-action(validate-deps.yml). Left on tags: first-partyactions/*andgithub/codeql-action(GitHub-owned);pnpm/action-setupinshowcase-smoke.ymlreceives no credential. The readers of the paths-filter ref (check-ci-filter-parity.mjs,dispatch-gates.mjs) match the action by prefix, so a pinned ref reads the same.2. Turbo remote-cache credentials scoped by event
Before: every same-repo
pull_requestrun receivedTURBO_TOKENandTURBO_REMOTE_CACHE_SIGNATURE_KEY. The read-onlyremote:rsetting is turbo client configuration; the token itself can write and the key can sign, so any code a PR runs during its build could upload a signed artifact that a later queue or main build replays.After, in all twelve carriers (
ci.yml×7,lint.yml×5), both secrets are gated on the same condition:merge_group, and every run onrefs/heads/main(push, the hourly schedule,workflow_dispatchon main). Not credentialed:pull_request, and a dispatch on any other branch.TURBO_CACHEandTURBO_TEAMare unchanged, so the write rule is exactly as before.remoteCache.signature: trueturbo needs the key to verify a download, which is the same key that signs. So a PR run cannot read the remote without holding both; the answer is not at all. A PR run builds from the restored Actions-cache seed (local:rw), whichmainsaves.api.vercel.comfrom this container (egress refused), so the "reads need the token" half is read from turbo's behaviour asassert-turbo-remote-cache.mjsalready documents it (any of the three unset turns the remote off), not from a live probe; this PR's own CI run is the first live reading.mainsaves:7ea2af7(00:27Z, before PR ci: prune each Test Core Turbo seed to its own run's tasks before saving it #25523 landed): Build Core76 build task(s) -- 0 remote hit(s), 0 local hit(s), 76 miss(es), build step 6 m 4 s. A credentialed PR in the same window read 53 remote / 0 local / 23 miss (1 m 40 s), so the seed was contributing nothing to anyone, most likely because the 2.4 GB Test Core seed snowball (ci: Turbo seeds vs the 10 GB Actions cache pool — measure the pool, then shrink or retire the per-sha seeds #25452) was flushing the 10 GB pool on every merge.945502c(01:34Z, after PR ci: prune each Test Core Turbo seed to its own run's tasks before saving it #25523, the merge of main): Build Core76 build task(s) -- 0 remote hit(s), 76 local hit(s), 0 miss(es), build step 911 ms, entirely from the seed.assert-turbo-remote-cachenotice prints the local-hit count on every PR run, so a regression is visible in the log.assert-turbo-remote-cache.mjsgainsisCredentialedRun()(same condition) and reports a disabled remote on a non-credentialed run as anotice("withheld by design"), not a warning. Writing runs still red when the remote is off. New self-test batterycredentialed run(5 cases): 37 cases across 7 batteries, exit 0.Verification
Gates derived with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat7ea2af7; results under "Gates" below.Gates (local, head
7ea2af7)node scripts/pm/dispatch-gates.mjs --commandsderived 70 families from the diff; 66 exit 0; 4 NOT MEASURED (exit 3, prerequisite: they read builtdist/, and no package source is in this diff):check:dts-closure,check:dual-build-cjs-loads,check:lean-entry-closure,check:sourcemap-no-sources-content. CI runs them on a real build.dispatch-gates.mjs --ranreports "70 derived families accounted for — 66 run, 4 NOT-MEASURED", exit 0.check:ci-filter-parity(+ self-test),check:required-contexts,check:pm-governed-merges,check:select-gate-families,check:self-test-wired,check:workflow-step-name-quoting,check:nul-bytes, andassert-turbo-remote-cache.mjs --self-test(37 cases, 7 batteries)..github/workflows/**andscripts/ci/**, which no package publishes (skip-changeset).维护者速读(草稿)
Session:
https://claude.ai/code/session_01W9H2WdXx3kPkf6moDnRdRE🤖 Generated with Claude Code
https://claude.ai/code/session_01W9H2WdXx3kPkf6moDnRdRE