Skip to content

Bump the four GitHub Actions majors under the clean room standard - #218

Merged
Jason-Vaughan merged 1 commit into
mainfrom
chore/actions-major-bumps
Sep 8, 2026
Merged

Bump the four GitHub Actions majors under the clean room standard#218
Jason-Vaughan merged 1 commit into
mainfrom
chore/actions-major-bumps

Conversation

@Jason-Vaughan

@Jason-Vaughan Jason-Vaughan commented Sep 8, 2026

Copy link
Copy Markdown
Owner

What

Bumps the four GitHub Actions majors Dependabot proposed, in one commit:

action bump supersedes
actions/checkout 4 → 7 #206
actions/setup-python 5 → 7 #204
actions/upload-artifact 4 → 7 #205
actions/download-artifact 4 → 8 #207

Reconstructed on main under the clean room standard in CONTRIBUTING.md — those four branches
were not merged, not checked out and not run locally. Under ADR-009 a bot's bytes get the same
treatment as anyone else's. They can be closed when this merges.

Why one PR and not four

The two artifact actions are coupled. From upload v7 / download v8 they share a direct-upload
contract: upload can skip zipping (archive: false) and download decides whether to decompress by
sniffing Content-Type. Neither option is used here — we upload a directory, so it zips, and the
round trip is by name — but merging them separately would leave a producer and a consumer of that
contract straddling it for as long as the second PR stayed open. The pairing rule is recorded in
publish.yml beside the steps, because a future session bumping one of them is exactly who needs it.

The audit

Full record: .prawduct/artifacts/queued-actions-bumps-204-207.md (untracked, per the
public-tree-product-only ruling).

Every target tag was verified as a real upstream release through the API rather than recalled — all
four postdate this session's model cutoff. Every major in every jump was read for breaking changes.

The jumps are smaller than they look. Three of the four crossed a major only to move to Node 24,
which the publishers themselves call "not a breaking change per-se but we're treating it as such".
Every genuine break across the seven majors is gated behind an input this project does not set or a
trigger it does not use:

  • download-artifact v5 changed the path layout for artifacts fetched by ID; we fetch by name,
    which upstream's migration guide lists under "no action needed".
  • setup-python v7 removed the pip-install input, never passed here.
  • checkout v7 now refuses to check out a fork PR under pull_request_target or workflow_run.
    Neither workflow uses either trigger — and the hardening runs with this repo's fork-PR posture.
  • setup-python v7 also carries a commit titled "remove EOL Python versions", the one plausible
    way this breaks a five-version matrix. It does not: reading that PR's file list, it touches only
    that action's own CI matrices and test fixtures, nothing about which interpreters it can install.

download-artifact v8 promotes a digest mismatch from a warning to an error. Taken deliberately
rather than by omission — this is the one path that feeds PyPI.

Runner floor (≥ v2.327.1 for three of the four) is met: both workflows are ubuntu-latest,
GitHub-hosted, no self-hosted runners.

The gap, stated rather than glossed

checkout@v7 and setup-python@v7 are proven — they touch ci.yml, so this PR's own matrix run
exercises them, as did the upstream PRs' (green on Python 3.10–3.14).

The artifact pair is not. It appears only in publish.yml, which fires on release: published,
so nothing here reaches it — the green checks on #205 and #207 ran the unchanged ci.yml and say
nothing about those actions. The next release is the first real exercise of that round trip.
Accepted because the usage is entirely default-shaped and the failure mode is a failed release job
after the tag is cut and before PyPI receives anything: loud, and recoverable.

Test plan

  • make test805 passed, 17 skipped, lint + mypy green (make test depends on lint).
  • This PR's CI matrix is itself the test of checkout@v7 and setup-python@v7 across 3.10–3.14.
  • No test reaches publish.yml; see the gap above.

Notes

Critic review

rev-20260908T213506Z-dbdb1ae6 (cumulative) — 0 blocking, 3 warning, 3 note. Nothing gated.
All six dispositioned; the three warnings are fixed rather than waved through:

Reconstruction of Dependabot's #204, #205, #206 and #207 on main: checkout
4 → 7, setup-python 5 → 7, upload-artifact 4 → 7, download-artifact 4 → 8.
Their branches were not merged, not checked out and not run locally — under
ADR-009 a bot's bytes get the same treatment as anyone else's.

The four land in one commit rather than four merges because two of them are
coupled. From upload v7 / download v8 the artifact actions share a direct
upload contract: upload can skip zipping via `archive: false`, and download
decides whether to decompress by sniffing Content-Type. Neither option is
used here, but bumping one side alone leaves a producer and a consumer of
that contract straddling it for as long as the other change sits unmerged.
The rule is recorded beside the steps, since a later session bumping one of
them is precisely who needs it.

The jumps look worse than they are. Three of the four crossed a major only
to move to Node 24 — a change the publishers themselves describe as "not a
breaking change per-se but we're treating it as such". Every real break
across the seven majors is gated behind an input this project does not set
or a trigger it does not use: download-artifact v5 changed the path layout
for artifacts fetched by ID and we fetch by name; setup-python v7 dropped
`pip-install`, never passed here; checkout v7 refuses to check out a fork PR
under `pull_request_target` or `workflow_run`, and neither workflow uses
either trigger. setup-python v7 also carries a commit called "remove EOL
Python versions", which is the one plausible way this breaks a five-version
matrix — reading its file list, it touches only that action's own CI
matrices and test fixtures, and nothing about which interpreters it installs.

download-artifact v8 promotes a digest mismatch from a warning to an error.
Taken deliberately rather than by omission: this is the one path that feeds
PyPI, and a corrupted dist should stop there.

checkout@v7 and setup-python@v7 are proven, not assumed — they touch ci.yml,
so the upstream PRs' own sandboxed runs exercised them green across Python
3.10 through 3.14. The artifact pair is not: it appears only in publish.yml,
which fires on `release: published`, so the green checks on #205 and #207 ran
the unchanged ci.yml and say nothing about it. The next release is its first
real exercise. Accepted because the usage is entirely default-shaped and the
failure would be a failed release job before PyPI receives anything.

Suite 805 green.
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