Skip to content

👷 ci(release): release through tox-dev/github-workflows 6.0.1 - #275

Merged
gaborbernat merged 1 commit into
pytest-dev:mainfrom
gaborbernat:fix/release-contract
Oct 27, 2026
Merged

gaborbernat merged 1 commit into
pytest-dev:mainfrom
gaborbernat:fix/release-contract

Conversation

@gaborbernat

@gaborbernat gaborbernat commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Releasing pytest-print used to depend on bash written into this repo's workflows: it bumped the version from a dropdown, pasted fragment files into CHANGELOG.md and built the GitHub Release text with awk. This PR hands that work to tox-dev/github-workflows 6.0.1 and release-creator 4.1.0. 🚀 A maintainer dispatches 🏷️ Prepare release; with the default auto bump the version follows the pending Towncrier fragments, and the changelog credits the commit authors and co-authors and lists first-time contributors.

Contributors see the change in two places. The new CONTRIBUTING.md, linked from the README, lists the ten fragment categories, says which ones select a minor or major version, and asks for no hand-written credits. The 19 existing changelog sections are rewritten into those categories with stable anchors and author credits; entries that only covered CI, tooling or refactors are gone, so 1.2.1 and 1.2.2 keep only their headings.

Architecture

The shared prepare workflow splits the work in two. A read-only job builds the changelog and uploads a release patch; a second job in the release-auth environment, which deploys only from main, applies that patch, creates a GitHub App token and pushes the commit and tag. The App key never reaches the job that runs Towncrier and the hooks.

The tag starts release.yaml, which runs one release at a time per tag. The shared build makes the wheel and sdist against the locked build backend while a read-only job renders the GitHub Release body from the tagged changelog section. PyPI publishing uses trusted publishing with attestations. The last job compares every built file with PyPI and checks its attestation, then publishes the GitHub Release.

flowchart LR
    Dispatch[Prepare release dispatch] --> Assemble[Assemble changelog, read-only]
    Assemble --> Push[Push commit and tag, release-auth]
    Push --> Build[Build wheel and sdist]
    Push --> Notes[Render release notes]
    Build --> PyPI[Publish to PyPI]
    Notes --> GHR[Verify PyPI files, publish GitHub Release]
    PyPI --> GHR
    classDef ro fill:#cfe4ff,stroke:#1f6feb,color:#0b1f3a;
    classDef write fill:#ffe3a3,stroke:#d29200,color:#3a2c00;
    class Dispatch,Assemble,Build,Notes ro;
    class Push,PyPI,GHR write;
Loading

Checks that only caught a mistake by someone with write access are gone: prepare no longer requires refs/heads/main, and the tag run no longer checks the tag's shape or the distribution file names. The fork guard on github.repository stays. The news check moves to its own 📝 Changelog workflow, which requires a fragment on human PRs, so 🚦 Required checks pass now gates only the test matrix. Each workflow, job and step gets an emoji name.

Dependencies

pylock.toml, generated by Nab 0.0.22 for CPython 3.15 on linux_x86_64, pins the release tools, including release-creator 4.1.0. The build group locks the hatchling backend plus Cython and setuptools, since PyYAML is locked as an sdist only. release-creator 4.1.0 is newer than the seven-day upload cutoff, so [tool.nab] carries an exception for it. A weekly 🔒 Upgrade release tools workflow opens the relock PR. The tox environments still install their dependency groups without the lock.

Hook updates move to Dependabot's pre-commit ecosystem, weekly on Tuesday with a seven-day cooldown, and pre-commit.ci autoupdates quarterly. Hooks are pinned to frozen commit SHAs, and mdformat comes from its upstream repo with pinned plugins. The PyPI page now renders the README through hatch-fancy-pypi-readme, so its CHANGELOG.md and CONTRIBUTING.md links point at GitHub. The metadata switches to an SPDX license and adds Framework :: Pytest.

🛡️ CodeQL

CodeQL moves from default setup to a committed workflow on ubuntu-26.04 scanning Python and the workflows with the security-extended suite and skipping tests/, which removes the ubuntu-latest migration notice default setup produces.

@gaborbernat gaborbernat added skip news PR does not need a changelog entry and removed skip news PR does not need a changelog entry labels Oct 20, 2026
@gaborbernat gaborbernat changed the title 🔧 build(release): lock all project groups build(release): adopt shared release workflow Oct 21, 2026
@gaborbernat gaborbernat changed the title build(release): adopt shared release workflow 👷 ci(release): adopt shared release workflow Oct 21, 2026
@gaborbernat
gaborbernat force-pushed the fix/release-contract branch 9 times, most recently from adbe948 to 7dfa79f Compare October 26, 2026 20:58
@gaborbernat gaborbernat changed the title 👷 ci(release): adopt shared release workflow 👷 ci(release): release through tox-dev/github-workflows 6.0.1 Oct 26, 2026
@gaborbernat
gaborbernat force-pushed the fix/release-contract branch 4 times, most recently from 59b086d to 0c8be6c Compare October 27, 2026 01:57
Prepare releases from Towncrier fragments through github-workflows 6.0.1
and publish the tag with the shared Python release workflow. The
changelog gets user-facing categories, stable anchors and author credits
for the 19 tagged sections, and a CONTRIBUTING guide explains fragments
and how credits come from commit authors and co-authors.

Nab writes pylock.toml for every group from a [tool.nab] table on
CPython 3.15 linux_x86_64, with a temporary upload cutoff exception for
release-creator 4.1.0. A build group locks the hatchling backend with
Cython and setuptools, because PyYAML has no CPython 3.15 wheel. The
unused release, release-check and release-validate groups are gone.

The tag workflow runs under a per-tag concurrency group. A read-only
notes job renders the changelog section in parallel with the build.
PyPI uploads no longer skip existing files. One job then verifies the
PyPI digests and creates the GitHub Release. Checks that only a writer
could defeat are dropped: the tag re-check before the GitHub Release,
the main-branch condition on prepare, and the pull_request condition
that repeated news.yaml's only trigger.

Every workflow, job and step carries an emoji name. The required checks
become "🚦 Required checks pass" and "📝 News fragment".

Dependabot's pre-commit ecosystem and pre-commit.ci's quarterly
autoupdate handle hook updates, so there is no hook cooldown check.

CodeQL moves from default setup to a committed advanced workflow on
ubuntu-26.04 with the same languages and query suite.
@gaborbernat
gaborbernat marked this pull request as ready for review October 27, 2026 05:39
@gaborbernat
gaborbernat merged commit a4933d1 into pytest-dev:main Oct 27, 2026
15 checks passed
@gaborbernat
gaborbernat deleted the fix/release-contract branch October 27, 2026 05:40
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