From fdc4f2d6b693436b47ff3d66d7f4cd36bbb8f32f Mon Sep 17 00:00:00 2001 From: Jason-Vaughan <95194903+Jason-Vaughan@users.noreply.github.com> Date: Tue, 8 Sep 2026 14:34:35 -0700 Subject: [PATCH] Bump the four GitHub Actions majors under the clean room standard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .github/workflows/ci.yml | 4 ++-- .github/workflows/publish.yml | 18 ++++++++++++++---- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac79301..032c333 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,10 +29,10 @@ jobs: matrix: python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e4b4810..9f23291 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,9 +13,9 @@ jobs: name: Build distributions runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v7 with: python-version: "3.12" @@ -36,7 +36,13 @@ jobs: python -m build python -m twine check dist/* - - uses: actions/upload-artifact@v4 + # Upload and download must move as a pair. From upload v7 / download v8 the two + # 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 — this is a directory, so it zips, and the round trip is by name — + # but bumping one side alone puts a producer and a consumer of that contract on + # either side of it. Bump both, or neither. + - uses: actions/upload-artifact@v7 with: name: dist path: dist/ @@ -51,7 +57,11 @@ jobs: permissions: id-token: write steps: - - uses: actions/download-artifact@v4 + # download v8 defaults `digest-mismatch` to `error`: a download whose hash does not + # match the server's now fails the job instead of logging a warning. That is the + # behaviour we want on the one path that uploads to PyPI — a corrupted dist should + # never reach the publish step — so the default is taken deliberately, not by omission. + - uses: actions/download-artifact@v8 with: name: dist path: dist/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cdc063..3ec17a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Internal +- **The four GitHub Actions majors, taken together** + ([#204](https://github.com/Jason-Vaughan/TangleBrain/pull/204), + [#205](https://github.com/Jason-Vaughan/TangleBrain/pull/205), + [#206](https://github.com/Jason-Vaughan/TangleBrain/pull/206), + [#207](https://github.com/Jason-Vaughan/TangleBrain/pull/207)). `actions/checkout` 4 → 7, + `actions/setup-python` 5 → 7, `actions/upload-artifact` 4 → 7, `actions/download-artifact` 4 → 8. + Re-implemented on `main` rather than merged, per the clean room policy in `CONTRIBUTING.md` — the + same standard Dependabot's bytes get as anyone else's. + + **The jumps are smaller than they look.** Three of the four actions crossed a major purely to + move to Node 24, a change their own release notes call "not a breaking change per-se but we're + treating it as such". Of the genuine breaks across all seven majors, every one 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 removed + `pip-install`, which was never passed; `checkout` v7 now refuses to check out a fork PR under + `pull_request_target` or `workflow_run`, and neither workflow uses either trigger. + + **Both artifact actions moved in one commit on purpose.** From upload v7 / download v8 they share + a direct-upload contract — upload can skip zipping, download decides whether to decompress from + `Content-Type`. Neither option is used here, but bumping one alone would straddle that contract + for as long as the second change stayed unmerged. `download-artifact` v8 also promotes a digest + mismatch from a warning to an error, which is the behaviour worth having on the one path that + reaches PyPI. + + **What is verified, and what waits for a release.** `checkout@v7` and `setup-python@v7` ran green + across the whole Python 3.10–3.14 matrix on the upstream PRs, which touched `ci.yml`. The artifact + pair lives only in `publish.yml`, which triggers on `release: published` — so nothing exercises it + until the next release, and the checks on #205 and #207 ran the unchanged `ci.yml` and say nothing + about it. Recorded rather than glossed: the first real test of that round trip is the next + release, and it fails loudly and recoverably if it fails at all. + - **Dependabot now watches Python dependencies and workflow actions weekly** ([#137](https://github.com/Jason-Vaughan/TangleBrain/issues/137)). Reported by [@be-student](https://github.com/be-student), with thanks — they also opened