Skip to content

ci: migrate every action off the deprecated Node 20 runtime - #1236

Merged
xiaolai merged 1 commit into
mainfrom
chore/node24-actions
Aug 8, 2026
Merged

ci: migrate every action off the deprecated Node 20 runtime#1236
xiaolai merged 1 commit into
mainfrom
chore/node24-actions

Conversation

@xiaolai

@xiaolai xiaolai commented Aug 8, 2026

Copy link
Copy Markdown
Owner

ci: migrate every action off the deprecated Node 20 runtime

GitHub is forcing node20 actions onto Node 24 ahead of removing the runtime
(changelog 2025-09-19); download-artifact@v4 was the one warning in the log,
but an audit of every pinned ref found six.

Each action's declared runtime was read from its own action.yml at the exact
ref this repo pins, rather than inferred from version numbers:

Action Was Now
actions/upload-artifact (x6) v4 node20 v7 node24
actions/download-artifact v4 node20 v8 node24
actions/deploy-pages v4 node20 v5 node24
actions/upload-pages-artifact v3 composite v5
actions/checkout (soak) v4 node20 v7
actions/setup-node (soak) v4 node20 v7
pnpm/action-setup (soak) v4 node20 pinned SHA, node24

upload-pages-artifact is the one a grep for node20 could not find: it is a
composite, and v3 wrapped upload-artifact@v4 internally. v5 wraps v7.0.0. The
whole transitive chain is now node24 — the other composites (rust-toolchain,
install-action) run only run: steps, and claude-code-action's setup-bun is
node24.

soak.yml had drifted furthest: it was the only workflow still on checkout@v4
and setup-node@v4, and the only one spelling pnpm/action-setup as a floating
tag while the other seven pin the SHA. It now matches.

Breaking changes checked, not assumed:

  • download-artifact v5 changed path layout for single downloads BY ID; ci.yml
    downloads by pattern with merge-multiple, so it does not apply.
  • v8 stops unzipping non-zipped downloads and defaults digest-mismatch to
    error. Our artifacts are zipped (archive defaults true), and failing on
    a hash mismatch is the loud default.
  • merge-multiple, include-hidden-files and if-no-files-found all still
    exist — the coverage gate depends on the last two, and the comment above
    them records the silent-skip bug that cost a debugging round already.
  • v6/v7 require runner >= 2.327.1; all jobs use GitHub-hosted runners.

Verified: gate tier 645 tests (including the ci.yml parity and byte-identity
checks, which read the file at runtime and no import graph can see), the GHA
suite's 575 tests including the round-trip over real workflow files, and all
workflow YAML parses.

GitHub is forcing node20 actions onto Node 24 ahead of removing the runtime
(changelog 2025-09-19); download-artifact@v4 was the one warning in the log,
but an audit of every pinned ref found six.

Each action's declared runtime was read from its own action.yml at the exact
ref this repo pins, rather than inferred from version numbers:

| Action | Was | Now |
|---|---|---|
| actions/upload-artifact (x6) | v4 node20 | v7 node24 |
| actions/download-artifact | v4 node20 | v8 node24 |
| actions/deploy-pages | v4 node20 | v5 node24 |
| actions/upload-pages-artifact | v3 composite | v5 |
| actions/checkout (soak) | v4 node20 | v7 |
| actions/setup-node (soak) | v4 node20 | v7 |
| pnpm/action-setup (soak) | v4 node20 | pinned SHA, node24 |

upload-pages-artifact is the one a grep for node20 could not find: it is a
composite, and v3 wrapped upload-artifact@v4 internally. v5 wraps v7.0.0. The
whole transitive chain is now node24 — the other composites (rust-toolchain,
install-action) run only `run:` steps, and claude-code-action's setup-bun is
node24.

soak.yml had drifted furthest: it was the only workflow still on checkout@v4
and setup-node@v4, and the only one spelling pnpm/action-setup as a floating
tag while the other seven pin the SHA. It now matches.

Breaking changes checked, not assumed:

- download-artifact v5 changed path layout for single downloads BY ID; ci.yml
  downloads by `pattern` with `merge-multiple`, so it does not apply.
- v8 stops unzipping non-zipped downloads and defaults `digest-mismatch` to
  `error`. Our artifacts are zipped (`archive` defaults true), and failing on
  a hash mismatch is the loud default.
- `merge-multiple`, `include-hidden-files` and `if-no-files-found` all still
  exist — the coverage gate depends on the last two, and the comment above
  them records the silent-skip bug that cost a debugging round already.
- v6/v7 require runner >= 2.327.1; all jobs use GitHub-hosted runners.

Verified: gate tier 645 tests (including the ci.yml parity and byte-identity
checks, which read the file at runtime and no import graph can see), the GHA
suite's 575 tests including the round-trip over real workflow files, and all
workflow YAML parses.
@xiaolai
xiaolai merged commit 981afc0 into main Aug 8, 2026
15 checks passed
@xiaolai
xiaolai deleted the chore/node24-actions branch August 8, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant