ci: bump the remaining Node20-pinned actions to Node24 majors - #274
Merged
Conversation
Every uses: in .github/workflows/ already resolved to actions/checkout v7.0.1, actions/cache v6.1.0, actions/upload-artifact v7.0.1, actions/download-artifact v8.0.1, and github/codeql-action/upload-sarif v4.37.3 (all node24, confirmed by reading action.yml at each pinned SHA) — PR #244 bumped these SHAs to their current majors as a side effect of its hash-pinning pass, ahead of this issue landing. Nothing left to bump. What remained was #246's AC4: one dispatch-verified green run of each affected workflow with zero "forced to run on Node.js 24" lines, quoted in the PR — and AC3: the upload-artifact/download-artifact round trip in release.yml proven by one real run. release.yml is push-tag-only, so proving that round trip meant either cutting a real release (out of scope: it would publish a real PyPI version and GitHub Release for a CI verification) or adding the seam to test it safely. Add workflow_dispatch to release.yml, gated so a manual run exercises checkout/cache/upload-artifact/download-artifact exactly as a real release would, but never creates a GitHub Release, never attaches assets to one, and never publishes to PyPI: - github-release job: if: github.event_name == 'push' - build job's "Attach attested distributions" step: same guard (softprops/action-gh-release creates the tag_name release if absent — an unguarded dispatch run would forge one) - sbom job's "Upload SBOM" step: same guard - publish-pypi job: only the pypa/gh-action-pypi-publish step is guarded; the download-artifact step above it stays unconditional, since that is the exact half of the round trip this exists to verify Refs #246.
) Real dispatch-verification run (30498168023) caught what #246's own investigation missed: this action's `runs.using: composite` at v2.4.0 still shells out internally to `attest-build-provenance/predicate@1176ef5` and an older `actions/attest`, both node20 -- a real "forced to run on Node.js 24" warning fired twice in that run (sbom job, build job), on an action #246 had listed as needing no change. v3.0.0's release notes (actions/attest-build-provenance#691, #693) name the fix directly: "Bump actions/attest ... Bump to node24 runtime" + "Bump attest-build-provenance/predicate to v2.0.0 ... Bump to node24 runtime". v4.0.0 restructures further: the composite step now calls actions/attest@v4.1.1 (SHA a1948c3f..., confirmed node24 by reading its action.yml) directly, dropping the separate predicate step. Inputs are unchanged (subject-path/subject-digest/subject-name/... identical names in v4.1.1's action.yml vs our v2 usage) -- no call-site change needed. Refs #246.
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.
Closes #246.
Summary
Every
uses:in.github/workflows/release.yml,publish-ccplugins.yml,marketplace-pins.yml,mcp-toplist-badge.yml,sync-ccplugins-fork.ymland
scorecard.yml— the five actions #246 named as still-Node20(
actions/checkout,actions/cache,actions/upload-artifact,actions/download-artifact,github/codeql-action/upload-sarif) — wasalready on its Node24-current SHA before this PR: PR #244 ("hash-pin
every dependency install") bumped these SHAs to their latest majors as a
side effect of its own pass, landing after #246 was filed but before this
PR started. Verified by reading
action.ymlat each pinned SHA (not theversion comment) — all report
runs.using: node24— and confirmed thoseare still the latest available release for each action (
repos/<action>/releases/latest).What #246's own investigation got wrong: it listed
actions/attest-build-provenanceunder "already resolves to node24, composite, or docker and needs no
change." That's false for the pinned
v2.4.0— a dispatch-verified realrun (AC4) caught it:
v2.4.0's composite action internally shells out toattest-build-provenance/predicate@1176ef5...and an oldactions/attest,both still Node20, producing a real
forced to run on Node.js 24warningtwice (SBOM job, build job) in run
https://github.com/cdeust/Cortex/actions/runs/30498168023. Fixed by bumping
to
v4.1.1(0f67c3f4...), whose composite step callsactions/attest@v4.1.1(
a1948c3f..., confirmednode24) directly — the predicate/attest split isgone as of the v4 rewrite (release notes: actions/attest-build-provenance#691/#693,
"Bump to node24 runtime"). Inputs are unchanged (
subject-pathet al.,confirmed against v4.1.1's
action.yml) — no call-site change beyond the pin.release.ymlis push-tag-only, so no PR CI ever exercises itsbuild → upload-artifact → download-artifact round trip (the actual
concern AC3/AC5 of #246 raise — the round trip changed shape across
actions/artifactv2 → v4). Cutting a real tag just to verify a CI-actionbump was out of scope (it would publish a real GitHub Release + PyPI
version). Instead,
release.ymlgained aworkflow_dispatchtrigger,gated so a manual run exercises every Node24-relevant action exactly as a
real release would, but never creates a GitHub Release, never attaches
assets to one, and never publishes to PyPI:
github-releasejob:if: github.event_name == 'push'buildjob's "Attach attested distributions" step: same guard(
softprops/action-gh-releasecreates thetag_namerelease if it'sabsent — unguarded, a dispatch run would forge one)
sbomjob's "Upload SBOM" step: same guardpublish-pypijob: only thepypa/gh-action-pypi-publishstep isguarded; the
download-artifactstep above it stays unconditional,since that's the exact half of the round trip this exists to verify
fuzz.yml(introduced by #244, which #246 flagged as needing "adopt theNode24 SHAs" if it landed unmerged) uses
google/clusterfuzzlite/actions/*pinned actions, which are
runs.using: docker— not Node-version-gated atall, confirmed by reading their
action.yml. Nothing to bump there.Acceptance criteria (from #246) — evidence
AC1 — every
uses:resolves tonode24/composite/dockerat thepinned SHA, verified by reading
action.yml, not the comment:runs.usingactions/checkout3d3c42e5...(v7.0.1)node24actions/cache55cc8345...(v6.1.0)node24actions/upload-artifact043fb46d...(v7.0.1)node24actions/download-artifact3e5f45b2...(v8.0.1)node24github/codeql-action/upload-sarifc54b30b7...(v4.37.3)node24actions/attest-build-provenance(this PR)0f67c3f4...(v4.1.1)actions/attest@a1948c3f...(v4.1.1) →node24All five #246-named SHAs are each still their action's
releases/latesttag as of this PR (re-verified at edit time, per the issue's own caveat
that "releases move").
AC2 — every
uses:pinned to a 40-hex SHA with a matching# vX.Y.Zcomment: unchanged by this PR for the 5 named actions (already true);
the 2
attest-build-provenancesites now read@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1.AC3 —
upload-artifact/download-artifactinrelease.ymlbumpedtogether, round trip proven by one real run: both already at their
Node24 majors (v7.0.1/v8.0.1, bumped together by #244). Round trip proven
by dispatch run https://github.com/cdeust/Cortex/actions/runs/30498850545 —
buildjob's "Upload build artifacts" step runsactions/upload-artifact@043fb46d...,publish-pypijob's "Download build artifacts" step runsactions/download-artifact@3e5f45b2...immediately after, unconditionalin both dispatch and push, and the job that downloads it completed
success.AC4 — one dispatch-verified green run of each affected workflow, 0
"forced to run on Node.js 24" lines, quoted:
release.ymlmarketplace-pins.ymlscorecard.ymlpublish-ccplugins.ymlsync-ccplugins-fork.ymlmcp-toplist-badge.yml(†)
publish-ccplugins.yml/sync-ccplugins-fork.yml: the repo has noCCPLUGINS_PATsecret configured (gh api repos/cdeust/Cortex/actions/secretsreturns an empty list), so both workflows' own "skip cleanly when
CCPLUGINS_PAT is missing" guard short-circuits before
actions/checkoutever runs. The 0-count is real but the checkout action itself is not
exercised in these two workflows — it IS exercised, successfully, with
the identical pinned SHA, in
marketplace-pins.yml,scorecard.yml, andevery
ci.ymlPR run. Not a gap in this PR's evidence; a pre-existingrepo secret gap outside #246's blast radius.
(‡)
mcp-toplist-badge.yml:actions/checkout,actions/setup-python,and the badge-regeneration step all ran and succeeded (confirmed in the
log); the run's overall
failurecomes frompeter-evans/create-pull-request'sPR-creation step, which fails with
GitHub Actions is not permitted to create or approve pull requests— a repo Settings→Actions permission gap,unrelated to Node20/24 and pre-existing (would fail identically on
maintoday with no PR open). Filed as #273 with reproduction + acceptance
criteria; not fixed here (flipping a repo-wide Actions permission is a
security-relevant decision outside a CI-action-version-bump PR's blast
radius). The stray
chore/mcp-toplist-badge-refreshbranch that runpushed before failing was deleted.
AC5 — Scorecard
Pinned-Dependenciesdoes not regress (pairedcontrol):
f606c377f3ebf9Improved, not regressed (this PR touches no
uses:pin lines beyond theattest-build-provenancebump, itself pinned to a 40-hex SHA — no newunpinned dependency introduced).
Boy-scout (§14) — defects seen while verifying
Ran
actionlint(not yet wired into CI — that's issue #247, owned by aconcurrent session/worktree) across
.github/workflows/as part of my ownverification. 11 pre-existing shellcheck findings total: 6 already
tracked by #247 (
release.yml×5,sync-ccplugins-fork.yml×1); theother 5, in
publish-ccplugins.yml, were not in #247's originalenumeration — I posted them as a comment on #247
(#247 (comment))
rather than opening a duplicate issue, since it's the same repo-wide gate
#247 already owns. None are in files this PR modifies beyond
release.yml,whose findings are unchanged by this diff (confirmed:
actionlinton thefinal
release.ymlreports the identical 5 findings, same line content,before and after).
Rules compliance
.github/workflows/is CI configuration, notmcp_server/source; no layer touchedrelease.ymlis 329 lines (was already 302 before this PR, over the repo's 300-line convention). Treated as out of the strict gate's scope for CI YAML — no prior enforcement exists for workflow files (ci.ymlsits at 641 lines,publish-ccplugins.ymlat 221, neither ever flagged), and a workflow file isn't a "function"/"class" in Martin's Clean Code sense the rule targets. Flagged here rather than silently passed over.gh api repos/<action>/releases/latest+git/ref/tags/<tag>read, or a real dispatch run log, quoted abovemcp-toplist-badge.yml's PR-creation failure) is unrelated to the issue's subject and filed as #273, not silently droppedStakes classification
Medium — CI/CD workflow files, not
auth//billing//crypto/concurrency/migration;
release.ymlis imported by no other file (composition root)but does gate the supply-chain-hardened release path (issue #178), so
full Move 1/3/7/8 discipline applied (real dispatch verification rather
than reading YAML, per the issue's own "why blind wasn't good enough"
rationale).
Self-flagged risk
None outstanding for #246's scope. Filed, not deferred-in-prose: #273
(mcp-toplist-badge.yml PR-creation permission gap) and the #247 comment
(5 additional actionlint findings in
publish-ccplugins.yml).