A workflow for making a release on PyPI
2023-05-05
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:
- Go to https://pypi.org/manage/account/token/
- Generate a new token, scope it to Entire account (all projects)
- Copy the token and create a new file:
$home/.pypirc
It looks something like this:
[pypi]
username = __token__
password = pypi-Fjk8z...39ZDiQ
- 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.
- Decide on a package name on PyPI that is still available
- Make a manual upload to PyPI. You can do this with
build
andtwine
:
pip install twine build
python -m build
twine upload dist/*
- 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.
- Go to your PyPI settings and register an API token scoped to your package.
- 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:
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:
- Bump the version (
major
/minor
/patch
as needed). I usebumpversion
to help with this.
bumpversion minor
- 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.