Automating Python Releases: GitHub Actions, Poetry, and Trusted Publishers

Overview of Automated Publishing

Publishing a

package manually is a recipe for inconsistency. Between managing version tags in
Git
, building distribution wheels, and uploading to the
PyPI
, there are too many manual touchpoints where human error can creep in. Automation turns this fragile process into a repeatable pipeline. By using
GitHub Actions
, you can trigger a release workflow simply by pushing a version tag. This ensures that the code on
GitHub
exactly matches the version users install via pip, providing a single source of truth for your software distribution.

Prerequisites and Tools

To follow this workflow, you need a basic understanding of

project structure and
Git
command-line operations. We use
Poetry
for dependency management and building because it handles versioning and project metadata more elegantly than legacy tools. You will also need a
PyPI
account and a repository hosted on
GitHub
. Familiarity with
YAML
syntax is helpful, as that is the language used to define
GitHub Actions
workflows.

Automating Python Releases: GitHub Actions, Poetry, and Trusted Publishers
GitHub Actions for Python Packages: How to Automate Releases to PyPi

Key Libraries & Tools

  • Poetry
    : A comprehensive tool for
    Python
    packaging and dependency management.
  • PyPI
    : The official third-party software repository for
    Python
    .
  • GitHub Actions
    : A CI/CD platform that allows you to automate your build, test, and deployment pipeline.
  • Trusted Publishers: A
    PyPI
    security feature that uses short-lived
    OIDC
    tokens instead of permanent API keys.

Configuring Trusted Publishers

Security is paramount when connecting

to
PyPI
. While API keys work, the Trusted Publisher mechanism is superior. It establishes a handshake between
GitHub Actions
and
PyPI
using a short-lived identity token. To set this up, navigate to the publishing settings on your
PyPI
project and add a new
GitHub
publisher. You must provide your repository owner name, the repository name, and the specific workflow filename (e.g., release.yml). This prevents long-lived credentials from being stolen or leaked.

Building the Workflow

The heart of the automation is the .github/workflows/release.yml file. This workflow should trigger only when a specific tag pattern is pushed. Using regular expressions ensures that only valid version tags following

trigger a release.

on:
  push:
    tags:
      - 'v[0-9]+.[0-9]+.[0-9]+'

The workflow is divided into logical jobs: fetching details, checking if the version already exists on

, building the package, and finally publishing.

jobs:
  setup-and-build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install Poetry
        run: pipx install poetry
      - name: Build
        run: poetry build

We utilize poetry build to generate the source distribution and the wheel file. These artifacts are then passed to the pypa/gh-action-pypi-publish action for the final upload.

Syntax Notes and Best Practices

Pay close attention to GitHub Output. When passing data between jobs, you cannot use standard environment variables because each job runs on a fresh virtual machine. Instead, use echo "key=value" >> $GITHUB_OUTPUT to persist data like version numbers for subsequent jobs. Additionally, always follow

for versioning to maintain compatibility with
Poetry
and
pip
.

Tips & Gotchas

does not allow you to overwrite a version once it has been published. If you upload 1.0.0 and realize there is a bug, you cannot simply delete and re-upload 1.0.0. You must bump the version to 1.0.1. Implementing a check job in your workflow that queries the
PyPI
API before building can save significant CI/CD resources by failing early if a version conflict is detected.

Automating Python Releases: GitHub Actions, Poetry, and Trusted Publishers

Fancy watching it?

Watch the full video and context

4 min read