Overview of Automated Publishing Publishing a Python package manually is a recipe for inconsistency. Between managing version tags in Git, building distribution wheels, and uploading to the Python Package Index (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 Python 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. 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 GitHub 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 PEP 440 trigger a release. ```yaml 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 PyPI, building the package, and finally publishing. ```yaml 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 PEP 440 for versioning to maintain compatibility with Poetry and pip. Tips & Gotchas PyPI 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.
Poetry
Software
- Nov 1, 2024
- Oct 4, 2022