Skip to content

ci: split the release into read and write jobs, pin every action, widen the matrix - #91

Merged
TMHSDigital merged 1 commit into
mainfrom
ci/release-and-pins
Sep 24, 2026
Merged

TMHSDigital merged 1 commit into
mainfrom
ci/release-and-pins

Conversation

@TMHSDigital

Copy link
Copy Markdown
Owner

Fixes #52. Part of #51 (see the last section).

Release workflow (#51)

  • One token per job. The workflow's default is permissions: {}, so each job gets only what it asks for:
    • resolve gets no permissions.
    • build has contents: read, and it runs uv sync, the gate, and uv build.
    • publish gets contents: write, id-token: write and attestations: write. It checks out nothing and runs no project code. It downloads the dist artifact, attests it, and attaches it.
  • No inline expansion. resolve reads the tag from env: and checks it against ^v[0-9]+\.[0-9]+\.[0-9]+$ before any other job runs. The later jobs read it only from the environment, and the checkout uses refs/tags/<tag>.
  • One run per tag. The concurrency group is release-${{ inputs.tag || github.ref_name }}. A tag push and a manual dispatch for the same tag now share a group and queue, where before they raced to --clobber the same assets.
  • Provenance. actions/attest-build-provenance signs the wheel and the sdist, so anyone can run gh attestation verify <file> -R TMHSDigital/plumbline to check where they came from.
  • Also: the release checkout sets persist-credentials: false, and the build turns off the uv cache so a release never builds from a cache another workflow wrote.

Pins, Dependabot, matrix (#52)

  • Every uses: in the three workflows now points at a commit SHA, with the version in a comment. Each pin is the newest release within the major version already in use (checkout v5.1.0, setup-uv v7.6.0, and so on). Newer majors exist, and Dependabot proposes them as their own PRs instead of this one bundling them.
  • .github/dependabot.yml covers github-actions and uv, weekly, grouped into one PR per ecosystem, with a 7-day cooldown. For uv it uses lockfile-only, since the floors in pyproject are raised by hand and tested by the lowest-direct job.
  • The matrix is now Ubuntu, Windows and macOS on Python 3.12, 3.13 and 3.14, 9 cells in all. The 3.14 classifier is added. The suite already passed on 3.14.5 locally.
  • README and CONTRIBUTING now describe the new matrix.

What is left of #51

The published v0.1.0 release still has no assets. The tag's __version__ is 0.1.0, so once this lands a dispatch of the new workflow with tag: v0.1.0 would build, attest and attach them. That publishes to a public release, so it waits for the maintainer to confirm. The Unreleased section that #51 asks for already exists in CHANGELOG.

actionlint passes on all three workflows.

🤖 Generated with Claude Code

…en the matrix

The release ran all of its steps, the project's and its dependencies' code
included, with a write token, expanded the dispatch tag straight into shell,
and keyed its concurrency on the ref, so a tag push and a manual run raced.
A resolve job now validates the tag against vX.Y.Z and passes it through the
environment, the build can only read, and a publish job that checks out
nothing attests the wheel and sdist and attaches them. Runs queue per tag.

Every action is pinned to a commit with its version beside it, Dependabot
keeps those pins and uv.lock current after a week's cooldown, and the test
matrix adds macOS and Python 3.14.

Fixes #52. Part of #51.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@TMHSDigital
TMHSDigital merged commit 6745973 into main Sep 24, 2026
23 checks passed
@TMHSDigital
TMHSDigital deleted the ci/release-and-pins branch September 24, 2026 00:35
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.

Pin actions to SHAs, add Dependabot, and widen the test matrix

1 participant