Surfaced as a run annotation while adding the frontend lint gate (#315):
Node.js 20 is deprecated. The following actions target Node.js 20 but are being forced to run on Node.js 24: actions/checkout@v4, actions/setup-node@v4
That run only uses two actions. The problem is repo-wide: 12 of the 16 distinct actions in .github/workflows/ declare runs.using: node20, and every one of the 16 workflow files pins at least one.
Inventory
Verified by reading action.yml at each pinned ref; "latest" from each repo's latest release.
| Action |
Pinned |
runs.using |
Latest |
Uses / files |
actions/checkout |
v4 |
node20 |
v7.0.1 |
25 / 16 |
actions/setup-go |
v5 |
node20 |
v7.0.0 |
15 / 12 |
actions/upload-artifact |
v4 |
node20 |
v7.0.1 |
10 / 6 |
actions/download-artifact |
v4 |
node20 |
v8.0.1 |
5 / 3 |
docker/build-push-action |
v5 |
node20 |
v7.3.0 |
5 / 1 |
actions/setup-node |
v4 |
node20 |
v7.0.0 |
4 / 4 |
actions/cache |
v4 |
node20 |
v6.1.0 |
4 / 2 |
cloudflare/wrangler-action |
v3 |
node20 |
v4.0.0 |
3 / 3 |
docker/setup-qemu-action |
v3 |
node20 |
v4.2.0 |
1 / 1 |
docker/setup-buildx-action |
v3 |
node20 |
v4.3.0 |
1 / 1 |
docker/login-action |
v3 |
node20 |
v4.6.0 |
1 / 1 |
azure/setup-helm |
v4 |
node20 |
v5.0.1 |
1 / 1 |
Already fine, no action needed: golangci/golangci-lint-action@v9 (node24), Swatinem/rust-cache@v2 (node24), sigstore/cosign-installer@v3 and anthropics/claude-code-action@v1 (both composite).
frontend.yml, incoming via #315, adds two more @v4 pins (checkout, setup-node) — worth bumping in the same pass rather than landing it already stale.
Why it matters
Today it is only an annotation: the runner silently executes the node20 shim on Node 24. But the forcing is the last step before removal, and the failure mode when it lands is that every workflow breaks at once, including release-traceway.yml, release-cli.yml, release-helm.yml, release-docs.yml and release-website.yml. Losing the ability to cut a release is a bad way to discover this.
Not a sweep — these are multi-major jumps
sed -i 's/@v4/@v7/' is the wrong move; several of these skip 2-3 majors and have real behaviour changes.
Suggested grouping, riskiest last:
- Low risk, high coverage —
checkout v4→v7, setup-go v5→v7, setup-node v4→v7. Setup/checkout actions, no artifact or registry semantics. Covers 44 of the 68 pins.
- Needs reading the changelogs —
upload-artifact v4→v7 and download-artifact v4→v8. Note the majors are already mismatched (v7 vs v8) and the artifact actions changed immutability/naming semantics across v4+. The six benchmark workflows pass artifacts between jobs, so a mistake here silently breaks result collection rather than failing loudly.
- Publish path, verify before merging — the four
docker/* bumps plus cloudflare/wrangler-action v3→v4 and azure/setup-helm v4→v5. All sit on release workflows, so they cannot be validated by a PR label; they want a workflow_dispatch dry run.
actions/cache v4→v6 — cache key/restore behaviour changed; worst case is a silent cache miss, which shows up as slower CI rather than a failure.
Groups 1 and 2 are label-validatable on a PR (backend.yml, cli*.yml, frontend.yml and the benchmarks all run on the ci label). Group 3 is the one that needs a maintainer to dispatch manually.
Note
Unrelated to the Go toolchain bump in #307 and the engines.node change in f95424cc — both of those are language runtime versions. This is the Node version the action wrapper itself executes on, and would still fire regardless of what Go or Node the jobs install.
Surfaced as a run annotation while adding the frontend lint gate (#315):
That run only uses two actions. The problem is repo-wide: 12 of the 16 distinct actions in
.github/workflows/declareruns.using: node20, and every one of the 16 workflow files pins at least one.Inventory
Verified by reading
action.ymlat each pinned ref; "latest" from each repo's latest release.runs.usingactions/checkoutactions/setup-goactions/upload-artifactactions/download-artifactdocker/build-push-actionactions/setup-nodeactions/cachecloudflare/wrangler-actiondocker/setup-qemu-actiondocker/setup-buildx-actiondocker/login-actionazure/setup-helmAlready fine, no action needed:
golangci/golangci-lint-action@v9(node24),Swatinem/rust-cache@v2(node24),sigstore/cosign-installer@v3andanthropics/claude-code-action@v1(both composite).frontend.yml, incoming via #315, adds two more@v4pins (checkout,setup-node) — worth bumping in the same pass rather than landing it already stale.Why it matters
Today it is only an annotation: the runner silently executes the node20 shim on Node 24. But the forcing is the last step before removal, and the failure mode when it lands is that every workflow breaks at once, including
release-traceway.yml,release-cli.yml,release-helm.yml,release-docs.ymlandrelease-website.yml. Losing the ability to cut a release is a bad way to discover this.Not a sweep — these are multi-major jumps
sed -i 's/@v4/@v7/'is the wrong move; several of these skip 2-3 majors and have real behaviour changes.Suggested grouping, riskiest last:
checkoutv4→v7,setup-gov5→v7,setup-nodev4→v7. Setup/checkout actions, no artifact or registry semantics. Covers 44 of the 68 pins.upload-artifactv4→v7 anddownload-artifactv4→v8. Note the majors are already mismatched (v7 vs v8) and the artifact actions changed immutability/naming semantics across v4+. The six benchmark workflows pass artifacts between jobs, so a mistake here silently breaks result collection rather than failing loudly.docker/*bumps pluscloudflare/wrangler-actionv3→v4 andazure/setup-helmv4→v5. All sit on release workflows, so they cannot be validated by a PR label; they want aworkflow_dispatchdry run.actions/cachev4→v6 — cache key/restore behaviour changed; worst case is a silent cache miss, which shows up as slower CI rather than a failure.Groups 1 and 2 are label-validatable on a PR (
backend.yml,cli*.yml,frontend.ymland the benchmarks all run on thecilabel). Group 3 is the one that needs a maintainer to dispatch manually.Note
Unrelated to the Go toolchain bump in #307 and the
engines.nodechange inf95424cc— both of those are language runtime versions. This is the Node version the action wrapper itself executes on, and would still fire regardless of what Go or Node the jobs install.