Skip to main content
  1. Posts/

A workflow for making a release on PyPI

·414 words·2 mins

Releasing a package on PyPI is not as difficult as it used to be. The tooling has evolved significantly since I uploaded my first package many years ago. Most of the steps can now be automated using github actions. In this blog I describe my typical workflow for releasing a package on PyPI.

Authentication on PyPI #

After 2023-06-01, all uploads from user accounts with 2FA enabled must use an API token in place of their password.

So, first things first, we must set up authentication:

  1. Go to https://pypi.org/manage/account/token/
  2. Generate a new token, scope it to Entire account (all projects)
  3. Copy the token and create a new file: $home/.pypirc

It looks something like this:

1
2
3
[pypi]
  username = __token__
  password = pypi-Fjk8z...39ZDiQ
  1. Enjoy publishing to PyPI without every typing your password again

First release #

Although I have automated releases of my packages, the first release has to be manual.

  1. Decide on a package name on PyPI that is still available
  2. Make a manual upload to PyPI. You can do this with build and twine:
1
2
3
pip install twine build
python -m build
twine upload dist/*
  1. Celebrate first release on pypi 🥳

(I recommend using testpypi if this is the first time.)

Automating the next releases #

The following releases can be completely automated using github actions.

  1. Go to your PyPI settings and register an API token scoped to your package.
  2. Add the token to this repo’s secrets named PYPI_TOKEN: https://github.com/USER/PROJECT/settings/secrets/actions.

Afterwards, this github action will take care of the rest:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
name: Publish on PyPI

on:
  release:
    types: [published]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-python@v2
      with:
        python-version: 3.10

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install setuptools wheel twine
        python setup.py sdist bdist_wheel        

    - name: Publish package
      uses: pypa/gh-action-pypi-publish@master
      with:
        user: __token__
        password: ${{ secrets.PYPI_TOKEN }}

Place this action in .github/workflows/publish.yaml of your project.

New releases #

The workflow then becomes as follows:

  1. Bump the version (major/minor/patch as needed). I use bumpversion to help with this.
1
bumpversion minor
  1. Make a new release on github. The upload to PyPI is triggered when a release is published. Make sure the tag matches the version.

If you use the standard github workflow (create branch->PR->merge->delete branch), it’s really easy to make changelogs this way too.