Follow-up to #396, kept separate because it is mechanical and touches every workflow.
actions/checkout@v4 re-resolves on every run, so whoever controls that tag controls step 0 of nearly every job in this repo — including the jobs that hold signing keys. This pins all of them to commits and moves off the stale v4 majors.
announce.yml's lone existing SHA pin moves up with them, so the tree is uniformly pinned rather than half-pinned — the state where a reader can't tell a deliberate omission from a miss.
Why this needed proving first
v5+ of both actions declare runs.using: node24, and Gitea's runner only accepts node24 from a given version onward. Get this wrong and the whole fleet fails at once — including the runs that would tell you it broke. So, before touching 83 sites:
Every runner serving this repo is Gitea Runner v1.0.8, whose vendored act accepts node24 (checked in its source at that exact version).
runs.using is only a validation gate. act execs a barenode from PATH, so the image's node is the real interpreter — and the oldest here is 18.19.1 (ubuntu:24.04's nodejs, in rust-ci-noble).
So checkout v7's node24-targeted ESM bundle was run under that exact node in that exact image. It parsed every input, drove git through @actions/exec, created .git in the workspace, set up and tore down its credential config, and ran its post step — reaching a genuine git error against the synthetic file:// remote used for the test, not a module-load or missing-API failure.
Actions clone straight from github.com here (no Gitea mirror), so these SHAs are meaningful. Both tags are lightweight, pointing directly at the pinned commits — verified via git ls-remote and the GitHub API.
Breaking changes checked, none apply
checkout v6 changed credential persistence, v7 blocks fork-PR checkout for pull_request_target/workflow_run. This repo passes zero checkout inputs and uses neither event.
cache v5/v6 select the same legacy service path as v4, because the runner never sets ACTIONS_CACHE_SERVICE_V2.
bench-gpu.yml needed no carve-out: no gpu-labelled runner is registered, and its last 10 nightly runs sat unassigned.
Deliberately not swept
actions/upload-artifact@v3 (7 sites) stays. It is pinned low on purpose — Gitea's artifact backend identifies as GHES and v4 refuses it. A naive sweep would have broken every artifact upload.
Verification
All 26 workflows re-parse, and the uses: values extracted back out of the parsed YAML are clean SHAs (the trailing # v7.0.1 is a proper comment, not part of the value). Beyond that, this PR's own CI is the test — pull_request runs use the workflow files from this branch, so every job here checks out with the new pin.
Note for elsewhere
unom/infra/scripts/setup-gitea-runner-base.ps1 pins Node 20.18.0 with a comment saying "actions/checkout@v4 needs node20 on PATH". Still functional, but the comment is now stale.
Follow-up to #396, kept separate because it is mechanical and touches every workflow.
`actions/checkout@v4` re-resolves on every run, so whoever controls that tag controls **step 0 of nearly every job in this repo** — including the jobs that hold signing keys. This pins all of them to commits and moves off the stale v4 majors.
- **52** × `actions/checkout@v4` → `@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1`
- **31** × `actions/cache@v4` → `@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0`
`announce.yml`'s lone existing SHA pin moves up with them, so the tree is uniformly pinned rather than half-pinned — the state where a reader can't tell a deliberate omission from a miss.
## Why this needed proving first
v5+ of both actions declare `runs.using: node24`, and Gitea's runner only accepts node24 from a given version onward. Get this wrong and the whole fleet fails at once — including the runs that would tell you it broke. So, before touching 83 sites:
- Every runner serving this repo is **Gitea Runner v1.0.8**, whose vendored `act` accepts `node24` (checked in its source at that exact version).
- **`runs.using` is only a validation gate.** act execs a *bare* `node` from PATH, so the image's node is the real interpreter — and the oldest here is **18.19.1** (`ubuntu:24.04`'s nodejs, in `rust-ci-noble`).
- So checkout v7's node24-targeted **ESM** bundle was run under that exact node in that exact image. It parsed every input, drove `git` through `@actions/exec`, created `.git` in the workspace, set up and tore down its credential config, and ran its post step — reaching a genuine `git` error against the synthetic `file://` remote used for the test, **not** a module-load or missing-API failure.
- Actions clone straight from github.com here (no Gitea mirror), so these SHAs are meaningful. Both tags are lightweight, pointing directly at the pinned commits — verified via `git ls-remote` and the GitHub API.
## Breaking changes checked, none apply
- **checkout v6** changed credential persistence, **v7** blocks fork-PR checkout for `pull_request_target`/`workflow_run`. This repo passes **zero** checkout inputs and uses **neither** event.
- **cache v5/v6** select the same legacy service path as v4, because the runner never sets `ACTIONS_CACHE_SERVICE_V2`.
- `bench-gpu.yml` needed no carve-out: no `gpu`-labelled runner is registered, and its last 10 nightly runs sat unassigned.
## Deliberately not swept
`actions/upload-artifact@v3` (7 sites) stays. It is pinned low **on purpose** — Gitea's artifact backend identifies as GHES and v4 refuses it. A naive sweep would have broken every artifact upload.
## Verification
All 26 workflows re-parse, and the `uses:` values extracted back out of the parsed YAML are clean SHAs (the trailing `# v7.0.1` is a proper comment, not part of the value). Beyond that, **this PR's own CI is the test** — pull_request runs use the workflow files from this branch, so every job here checks out with the new pin.
## Note for elsewhere
`unom/infra/scripts/setup-gitea-runner-base.ps1` pins Node 20.18.0 with a comment saying *"actions/checkout@v4 needs node20 on PATH"*. Still functional, but the comment is now stale.
A tag is a pointer, not a version. `actions/checkout@v4` re-resolves on
every run, so whoever controls that tag controls the first step of nearly
every job in this repo — including the jobs holding signing keys. 52
checkout sites and 31 cache sites now name a commit; announce.yml's lone
existing SHA pin moves up with them so the tree is uniformly pinned rather
than half-pinned, which is the state where a reader cannot tell a
deliberate omission from a miss.
checkout v4 -> v7.0.1, cache v4 -> v6.1.0, both by commit.
The reason this needed proving rather than just doing: v5+ of both declare
`runs.using: node24`, and Gitea's runner only accepts node24 from a certain
version on. Checkout is step 0 of almost everything here, so getting it
wrong fails the whole fleet at once — including the runs that would tell
you it broke.
What was established first:
- every runner serving this repo is Gitea Runner v1.0.8, whose vendored
act accepts node24;
- `runs.using` is only a validation gate — act execs a BARE `node` from
PATH, so the image's node is the real interpreter, and the oldest one
here is 18.19.1 (ubuntu:24.04's nodejs, in rust-ci-noble);
- so checkout v7's node24-targeted ESM bundle was run under that exact
node, in that exact image: it parsed inputs, drove `git` through
@actions/exec, created .git, set up and tore down credential config, and
ran its post step. It reached a genuine git error against the synthetic
file:// remote used for the test — not a module-load or missing-API
failure. It works.
- actions clone straight from github.com here (no Gitea mirror), so these
SHAs are meaningful; both tags are lightweight, pointing directly at the
commits pinned.
No breaking change in v5..v7 applies: this repo passes zero checkout
inputs, and uses neither `pull_request_target` nor `workflow_run` (v7's
fork-PR restriction). cache v5/v6 pick the same legacy service path as v4
because the runner never sets ACTIONS_CACHE_SERVICE_V2.
upload-artifact@v3 is deliberately NOT swept — it is pinned low on purpose,
because Gitea's artifact backend identifies as GHES and v4 refuses it.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Follow-up to #396, kept separate because it is mechanical and touches every workflow.
actions/checkout@v4re-resolves on every run, so whoever controls that tag controls step 0 of nearly every job in this repo — including the jobs that hold signing keys. This pins all of them to commits and moves off the stale v4 majors.actions/checkout@v4→@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1actions/cache@v4→@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0announce.yml's lone existing SHA pin moves up with them, so the tree is uniformly pinned rather than half-pinned — the state where a reader can't tell a deliberate omission from a miss.Why this needed proving first
v5+ of both actions declare
runs.using: node24, and Gitea's runner only accepts node24 from a given version onward. Get this wrong and the whole fleet fails at once — including the runs that would tell you it broke. So, before touching 83 sites:actacceptsnode24(checked in its source at that exact version).runs.usingis only a validation gate. act execs a barenodefrom PATH, so the image's node is the real interpreter — and the oldest here is 18.19.1 (ubuntu:24.04's nodejs, inrust-ci-noble).gitthrough@actions/exec, created.gitin the workspace, set up and tore down its credential config, and ran its post step — reaching a genuinegiterror against the syntheticfile://remote used for the test, not a module-load or missing-API failure.git ls-remoteand the GitHub API.Breaking changes checked, none apply
pull_request_target/workflow_run. This repo passes zero checkout inputs and uses neither event.ACTIONS_CACHE_SERVICE_V2.bench-gpu.ymlneeded no carve-out: nogpu-labelled runner is registered, and its last 10 nightly runs sat unassigned.Deliberately not swept
actions/upload-artifact@v3(7 sites) stays. It is pinned low on purpose — Gitea's artifact backend identifies as GHES and v4 refuses it. A naive sweep would have broken every artifact upload.Verification
All 26 workflows re-parse, and the
uses:values extracted back out of the parsed YAML are clean SHAs (the trailing# v7.0.1is a proper comment, not part of the value). Beyond that, this PR's own CI is the test — pull_request runs use the workflow files from this branch, so every job here checks out with the new pin.Note for elsewhere
unom/infra/scripts/setup-gitea-runner-base.ps1pins Node 20.18.0 with a comment saying "actions/checkout@v4 needs node20 on PATH". Still functional, but the comment is now stale.