Skip to content

👷 ci(release): move releases to shared github-workflows - #156

Draft
gaborbernat wants to merge 1 commit into
mainfrom
fix/release-contract
Draft

gaborbernat wants to merge 1 commit into
mainfrom
fix/release-contract

Conversation

@gaborbernat

@gaborbernat gaborbernat commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

python-discovery cut releases through its own copy of the release logic: a shell version calculator in the prepare workflow, an awk and regex converter from the RST changelog to GitHub notes, and a local tasks/release.py behind a tox environment. 🚀 This PR hands that work to the shared release path in tox-dev/github-workflows 6.0.1 and release-creator 4.1.0, so a fix to how tox-dev projects release lands here with a pin bump instead of a hand edit.

Architecture

This repo keeps thin caller workflows and the project-specific inputs: the changelog path, the PyPI project name and the annotated-tag choice. github-workflows owns the steps: preparing the release commit and tag, building the distributions, rendering notes, checking PyPI digests and creating the GitHub Release. release-creator owns the changelog rules those steps call, from linking fragments to their pull request to crediting authors and converting a tagged RST section to Markdown.

On a tag push, the build and the notes run in parallel, PyPI publishing waits for both, and the GitHub Release comes last, after the PyPI files match the built ones.

flowchart LR
    Tag[Tag push] --> Build[🏗️ Build]
    Tag --> Notes[📝 Render notes]
    Build --> PyPI[🚀 PyPI via OIDC]
    Notes --> PyPI
    PyPI --> GHR[🚀 GitHub Release]
    classDef local fill:#cfe4ff,stroke:#1f6feb,color:#0b1f3a;
    classDef shared fill:#d8f3dc,stroke:#2d6a4f,color:#0b2e1a;
    class Tag,PyPI local;
    class Build,Notes,GHR shared;
Loading

What changes for contributors and maintainers

docs/changelog.rst is rebuilt from the 25 release tags with categorized sections (Added, Fixed, Documentation and others) and stable anchors per release and per category. Fragments name no pull request number: release preparation links each one to its merged PR and credits that PR's commit author and co-authors, then runs release-creator contributors to add a New Contributors subsection. A new docs/contributing.rst page documents this, and a separate news workflow checks fragments on pull requests.

The owner's rule is that people with write access are trusted and the pull request merge is where their work gets validated. So this PR drops checks that only re-validated a writer's action outside a pull request: the tag-format and changelog-section check on tag push, and the prepare workflow's patch path checks before pushing to main. Every job and step now carries a name with one emoji.

Dependencies

pylock.toml comes from nab, configured in [tool.nab]: universal mode, a seven-day P7D upload window, CPython 3.15 on linux_x86_64, covering every dependency group. A weekly workflow relocks it. A new build group adds cython and setuptools next to the hatchling backend because PyYAML 6.0.3 ships no cp315 wheel. release-creator has a temporary cutoff of 2026-10-26T18:24:46Z, marked for deletion after 2026-11-02, which lets the lock resolve 4.1.0 before it is seven days old.

Hook updates move to Dependabot's pre-commit ecosystem with a seven-day cooldown, hook revisions are frozen to commit SHAs, and pre-commit.ci autoupdates quarterly. The package metadata switches to an SPDX license, and the PyPI Changelog link points at docs/changelog.rst.

🛡️ CodeQL

CodeQL moves from default setup to a committed workflow on ubuntu-26.04 that scans actions and python with the security-extended suite and skips tests, which removes the ubuntu-latest migration notice default setup produces. GitHub rejects advanced-setup results while default setup is on, so the 🛡️ Analyze jobs fail until default setup is turned off for this repository.

@gaborbernat gaborbernat added the skip news No user-facing changelog entry needed label Oct 20, 2026
@gaborbernat gaborbernat changed the title 👷 ci(release): adopt shared news checks 👷 ci(release): share the RST release path Oct 20, 2026
@gaborbernat
gaborbernat force-pushed the fix/release-contract branch 10 times, most recently from 420a07d to 52064d2 Compare October 26, 2026 20:59
@gaborbernat gaborbernat changed the title 👷 ci(release): share the RST release path 👷 ci(release): move releases to shared github-workflows Oct 26, 2026
@gaborbernat
gaborbernat force-pushed the fix/release-contract branch 3 times, most recently from ce36924 to 396de75 Compare October 26, 2026 23:43
Release preparation, the distribution build and GitHub note rendering
move to tox-dev/github-workflows 6.0.1, with release-creator 4.1 or later in
the release-* groups (the lock resolves 4.1.0). tasks/release.py goes
away, along with the unused release, release-check and release-validate
groups. docs/changelog.rst is rebuilt from the 25 release tags with
categorized sections and stable anchors, and new entries come from
Towncrier fragments in docs/changelog, checked by the news workflow.
Credits are no longer written by hand: each entry credits the merged pull
request's commit author and co-authors when the changelog is built, and
prepare runs release-creator contributors to add a New Contributors
subsection.

The tag workflow builds through validate-python-release while a read-only
notes job renders the GitHub Release body from the changelog section.
PyPI publishing keeps OIDC in the release environment and drops
skip-existing. A single github-release job then reconciles the PyPI
digests and creates the release with one publish-github-release call; it
has no checkout, so its setup-uv step sets ignore-empty-workdir.
Artifacts pass between jobs by ID. The workflow runs under
release-${{ github.ref }} concurrency without cancelling.

Writers are trusted and validated at pull request merge, so the checks
that only caught a writer's mistake outside a pull request go: the step
that re-checked the tag still named the release commit, and the
pull_request condition repeating the news workflow's only trigger.
github-workflows 6.0.1 drops its own tag, lock and prepare re-checks the
same way. Every job and step now has a name that starts with an emoji.

pylock.toml is generated by Nab from [tool.nab] (universal, seven-day
cutoff, CPython 3.15 on linux_x86_64, project-runtime base group) and
covers every group and extra. A build group carries the hatchling backend
plus cython and setuptools, because PyYAML has no cp315 wheel. A temporary
release-creator cutoff of 2026-10-26T18:24:46Z is to be deleted after
2026-11-02. The weekly updater relocks pylock.toml.

Hook updates move to Dependabot's pre-commit ecosystem with a seven-day
cooldown, and pre-commit.ci autoupdates quarterly. Revisions stay frozen;
the hook-cooldown check, its rerun workflow and the managed closure pins
are gone.

CodeQL moves from default setup to a committed advanced workflow on
ubuntu-26.04, scanning actions and python with security-extended and
skipping tests.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip news No user-facing changelog entry needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant