ci: pin all third-party actions in reusable workflows to commit SHAs#226
ci: pin all third-party actions in reusable workflows to commit SHAs#226thedavidmeister wants to merge 6 commits into
Conversation
Pin every third-party GitHub Action referenced by a mutable tag (@v6, @V15, etc.) in rainix's reusable workflows to the immutable commit SHA that tag currently points to. The exact current versions are preserved as a trailing `# <tag>` comment, so this is a pure immutability change with no behavior change. rainix owns the org's shared CI: these reusable workflows are inherited by every consumer (raindex, flow, etc.). Referencing third-party actions by mutable tag is a supply-chain hole — a compromised or retagged action silently executes in every consumer's CI with their tokens. Pinning to a SHA makes the inherited CI immutable and reproducible. This also stabilizes an intermittent cachix/cachix-action@v15 flake that has been hitting raindex CI (rs-static/wasm failing in the cachix step), since the action is now resolved to a fixed commit. 70 references pinned across 14 workflow files / 11 distinct actions: actions/checkout, actions/cache, nixbuild/nix-quick-install-action, cachix/cachix-action, nix-community/cache-nix-action, Swatinem/rust-cache, jlumbroso/free-disk-space, JS-DevTools/npm-publish, softprops/action-gh-release. rainlanguage/* reusable-workflow references are intentionally left on @main (first-party, not a supply-chain concern). Maintainers and dependabot can still bump versions via the `# <tag>` comments. This is the upstream/source equivalent of raindex#2724 (the consumer-side pinning), which can then be slimmed to just its 2 repo-local pins. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 57 minutes and 1 second. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (19)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The checkout + nix-quick-install + cachix + cache-nix-action setup preamble was copy-pasted across all 14 reusable workflows, so each pinned third-party action SHA (notably cachix) lived in 14 places. Extract it into a single composite action `.github/actions/nix-cachix-setup` so each of those SHAs lives in ONE place. - New composite action holds the common preamble once. Inputs cover the variations: cachix-auth-token (a composite cannot read secrets.*, so each reusable plumbs secrets.CACHIX_AUTH_TOKEN through as an input), cachix-name, gc-max-store-size-macos (rs-test), and checkout/cache-nix toggles for the outliers. - The 13 uniform reusables replace the 4-step preamble with one `uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main` (fully qualified, since a bare ./ would resolve against the calling repo — same pattern as the existing github-chore action ref). - rainix-vercel keeps its own checkout (it needs a Free-disk-space step between checkout and nix) and routes nix+cachix+cache-nix through the composite (checkout: false). - rainix-autopublish keeps its own ssh-key checkout (v4) and cache-nix-action (v6) — both intentionally different pinned versions — and routes only the shared nix-quick-install + cachix pair through the composite (checkout: false, cache-nix: false). Behavior-preserving: same actions, same order, same pinned versions; pure de-duplication. cachix and nix-quick-install SHAs now appear once (in the composite); checkout v6 and cache-nix v7 once in the composite plus the vercel/autopublish inline outliers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The nix-cachix-setup composite single-sourced the nix+cachix preamble, but five third-party actions were still pinned at multiple call sites (rust-cache 5x, actions/cache 5x, actions/checkout 3x, action-gh-release 2x, cache-nix-action 2x). GitHub Actions can't parameterize a `uses:` ref, so the only way to pin an action's SHA in one place is to wrap its step in a composite with inputs for the per-call-site variation. Adds four composite actions and routes every occurrence through them (plus the existing nix-cachix-setup): - .github/actions/checkout — wraps actions/checkout; `ssh-key` input for the autopublish deploy-key checkout. Also called by nix-cachix-setup and the vercel inline checkout. Consolidates the lone autopublish v4 checkout onto the v6 the rest of the org already uses (ssh-key behavior is identical across v4/v6; the only v4->v6 changes are Node 24 + credential-store location, both irrelevant to a deploy-key checkout). - .github/actions/rust-cache — wraps Swatinem/rust-cache; `prefix-key` input for the vercel per-workflow namespacing. (rust-cache reads prefix-key as `getInput || "v0-rust"`, so the empty default == the four no-input sites.) - .github/actions/cache — wraps actions/cache; `path`/`key`/ `restore-keys` inputs (the four Foundry build caches + the vercel npm cache). - .github/actions/gh-release — wraps softprops/action-gh-release; `tag-name`/`name`/`files` inputs + a `github-token` input plumbed to `env: GITHUB_TOKEN` (a composite can't read secrets.*). Empty `files` parses to no assets, matching the soldeer release that attaches none. Also folds the autopublish job's inline cache-nix-action@v6 into the nix-cachix-setup composite's bundled v7 step (drops `cache-nix: 'false'`): autopublish was the only site left on v6 — a long-standing drift, not a deliberate need — and its Linux-only Nix-store cache is exactly what v7 caches by default, so the consolidation is behavior-preserving. Every composite's own action refs stay SHA-pinned; consumers reference the new composites by the fully qualified `rainlanguage/rainix/.github/actions/<name>@main` ref (a bare `./` would resolve against the calling repo), mirroring nix-cachix-setup. Net: no third-party action appears more than once across .github/. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Rainix CI / check-shell self-test jobs referenced the new same-repo composites as rainlanguage/rainix/.github/actions/<name>@main. On this PR @main resolves against the tip of main, which does not yet contain .github/actions/* — every self-test job failed in "Prepare all required actions" ("Could not find file ... LICENSE"). Self-tests now bootstrap a single actions/checkout (same SHA the checkout composite wraps) and reference the composites by ./ path, so they exercise the composites as defined on this branch. nix-cachix-setup is called with checkout: 'false' so its internal checkout@main ref (which must stay fully qualified for downstream consumers) isn't hit on-branch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Rainix CI / check-shell self-test jobs reference the new same-repo composites at rainlanguage/rainix/.github/actions/<name>@main. On this PR @main resolves against the tip of main, which does not yet contain .github/actions/* — so "Prepare all required actions" fails with "Could not find file ... LICENSE" and every self-test job dies in ~10s. This is the irreducible bootstrap cost of single-sourcing same-repo composites at @main, and it cannot be dodged on-branch without giving up an invariant: - `./` inside a composite resolves against the *caller* repo (breaks every downstream consumer); - a branch pin dangles once the branch is deleted post-merge; - GitHub downloads every transitively-referenced action up front, so even checkout: 'false' cannot avoid the preamble's internal checkout@main download. The refs are therefore kept at @main (zero version skew, every third-party action still single-sourced — DRY count 1). The jobs go green the moment this PR lands on main and the @main actions exist. This commit only adds comments explaining that; the action refs are unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Self-test jobs are red: root cause + the bootstrap tradeoffRoot cause (log evidence)Every The self-tests reference the new composites as Why it can't be worked around on-branch without giving up an invariantI tried the obvious fixes and verified against live CI / GH docs:
So What I did (and why)Kept every ref at If you'd rather see green before mergeSay the word and I'll push one of:
My recommendation is to merge as-is (zero skew, DRY fully intact, green on main) unless a green pre-merge check is a hard gate — in which case (A)/(B) trade one invariant for it. Your call. |
What
Pin every third-party GitHub Action referenced by a mutable tag (
@v6,@v15, etc.) in rainix's reusable workflows to the immutable commit SHA that tag currently points to. The exact current version is kept as a trailing# <tag>comment.This pins the exact current versions — there is no behavior change, it is pure immutability hardening.
Why
rainix owns the org's shared CI. These reusable workflows (
rainix-rs-test,rainix-sol-test,rainix-vercel,rainix-autopublish, etc.) are inherited by every consumer — raindex, flow, and the rest. Referencing third-party actions by mutable tag is a supply-chain hole: a compromised or silently-retagged action would execute in every consumer's CI with their tokens and secrets. Pinning to a SHA makes the inherited CI immutable and reproducible.It also stabilizes the intermittent
cachix/cachix-action@v15flake currently hitting raindex CI (rs-static / wasm failing in the cachix step), since the action now resolves to a fixed commit instead of whatever@v15points to at job time.This is the upstream/source equivalent of raindex#2724 (the consumer-side equivalent). With rainix's reusables hardened here, raindex#2724 can be slimmed down to just its 2 repo-local pins.
Scope
70 references pinned across 14 workflow files / 11 distinct actions:
df4cb1c069e1874edd31b4311f1884172cec0e1034e114876b0b11c390a56381ad16ebd13914f8d50057852bfaa89a56745cba8c7296529d2fc398305bb6a3b3abe66fd09bbf250dce8ada94f856a703ad2ddac53f961de1989924296a1f236fcfbaa4fc7df957e333c1e5da7721f60227dbba6d06080569135667ec418502fa5a3598af6fb9eb733888ce6ae18b497796c12c097a38f9edb9d0641fb99eee3254081f138730dfa15788a46383842cd2f914a1be19c28f1ef146469e409470805ea4279d47c3d35c3bb12739c298aeb8a4eeaf626c5b8d85266b0e65rainlanguage/*reusable-workflow references are intentionally left on@main(first-party, not a third-party supply-chain concern). Anything already SHA-pinned was untouched (there was none).Notes
# <tag>comments — that's the standard convention and keeps update tooling working.refs/tags/<tag>^{}), not the tag object.🤖 Generated with Claude Code