Skip to content

✨ feat(ci): automate releases and harden workflows#991

Merged
gaborbernat merged 5 commits intopypa:mainfrom
gaborbernat:781
Mar 23, 2026
Merged

✨ feat(ci): automate releases and harden workflows#991
gaborbernat merged 5 commits intopypa:mainfrom
gaborbernat:781

Conversation

@gaborbernat
Copy link
Copy Markdown
Collaborator

@gaborbernat gaborbernat commented Mar 18, 2026

Releases required eight manual steps including version file updates, changelog edits, commit creation, GPG-signed tag creation, and GitHub release creation. New maintainers needed GPG keys signed by existing maintainers before making releases.

Added a pre-release workflow that automates version bumping, changelog building via towncrier, commit creation, and tag pushing. Maintainers click "Run workflow" and select a version bump type. The CD workflow now triggers on tag pushes and automatically creates GitHub releases, eliminating the manual release creation step.

Hardened all workflows with commit SHA pinning instead of version tags, explicit minimal permissions at workflow and job levels, and credential isolation via persist-credentials: false. Added zizmor security scanner to CI. Configured towncrier for changelog fragments and backfilled fragments for changes since 1.4.0. Updated contributing guide with release process, changelog fragment requirements, and workflow security practices. Added PR template with changelog checklist.

Closes #561

@gaborbernat gaborbernat added the enhancement New feature or request label Mar 18, 2026
@github-advanced-security
Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@gaborbernat gaborbernat force-pushed the 781 branch 2 times, most recently from d1b6b5a to d42a89c Compare March 18, 2026 23:49
@henryiii
Copy link
Copy Markdown
Contributor

I thought we already had trusted publishing going?

I think all the stuff about GPG keys can simply be deleted.

@gaborbernat gaborbernat force-pushed the 781 branch 4 times, most recently from 1efd6c4 to 5232b45 Compare March 19, 2026 00:11
@gaborbernat gaborbernat changed the title ✨🔒 feat(ci): automate releases with trusted publishing and attestations ✨ feat(ci): automate releases and harden workflows Mar 19, 2026
@gaborbernat gaborbernat force-pushed the 781 branch 8 times, most recently from 48ceee6 to bcdc69b Compare March 19, 2026 00:43
@gaborbernat
Copy link
Copy Markdown
Collaborator Author

I thought we already had trusted publishing going?

I think all the stuff about GPG keys can simply be deleted.

Yeah updated title and description.

@gaborbernat gaborbernat force-pushed the 781 branch 2 times, most recently from ee48f0e to 71019f3 Compare March 19, 2026 00:46
Maintainer onboarding has been complicated by the requirement for GPG key management. New maintainers need to generate keys, get them signed by existing maintainers, and have them listed in the installation documentation before they can make releases. This creates friction and delays onboarding.

PyPI removed PGP signature support in May 2023 after analysis showed fewer than forty percent of signatures could be verified and most users never checked them. The replacement is trusted publishing using OpenID Connect tokens combined with build attestations per PEP 740. This modern approach provides stronger security guarantees by cryptographically linking each package to its exact source commit, repository, and workflow run.

Added a pre-release workflow that maintainers trigger through GitHub Actions, selecting a version bump type. The automation handles version updates, prompts for changelog edits, creates release commits and tags, and triggers the continuous deployment pipeline. The CD workflow builds packages, generates attestations, creates GitHub releases, and publishes to PyPI using short-lived OIDC tokens that expire after fifteen minutes. The entire process takes approximately five minutes from button click to published package.

Hardened all GitHub Actions workflows following security best practices. Pinned all actions to commit SHAs to prevent supply chain attacks via tag moving. Set explicit minimal permissions at both workflow and job levels following the principle of least privilege. Added credential isolation to prevent token leakage through artifacts. Enabled automated security scanning with zizmor to catch workflow vulnerabilities in CI.

Updated contributing documentation with comprehensive release process information and workflow security guidelines. The documentation explains the security model, provides detailed local testing instructions, and documents backwards compatibility with the existing manual process.

Closes pypa#561
Aligns the release tox env with the rest of the project by using
a dependency group in pyproject.toml instead of inline tox deps.

Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
@gaborbernat gaborbernat requested a review from layday March 20, 2026 16:01
@gaborbernat gaborbernat enabled auto-merge (squash) March 22, 2026 15:07
Copy link
Copy Markdown
Contributor

@henryiii henryiii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather add zizmor to pre-commit (prek) instead of adding a new job; that makes it easy to run locally too. (This is the only thing I'd like changed)

I rather like making the GitHub Release the core mechanism for triggering a release, and have that make the tag, vs. making the tag the thing that triggers a GitHub Release. But I'm fine with this.

I also don't think we move quickly enough that having an automated changelog is that important; I like hand crafted changelogs and we don't move that fast. But I'm fine with this.

I rather wish this had been broken up a bit; it would be easier to review if it was just hardening releases or changing the way changelogs are created instead of doing it all at once. But I'm fine with this, especially if you are basing this on another project where it works.

@gaborbernat
Copy link
Copy Markdown
Collaborator Author

Yeah I mostly base this off of what has been working well for virtualenv.

Replace standalone zizmor GitHub Actions workflow with a pre-commit
hook for local and CI consistency.
env.BASE is set internally by the workflow, not from external input.
dependabot-cooldown is unrelated to this PR's scope.

Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this to .github/zizmor.yml, to keep the base directory a bit cleaner.

@gaborbernat gaborbernat merged commit 7f46d46 into pypa:main Mar 23, 2026
65 checks passed
@gaborbernat gaborbernat deleted the 781 branch March 23, 2026 21:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Onboard maintainers to the release process

4 participants