Release Management with PyPI and GitHub
Wed 25 January 2023 by George DornI'm a core maintainer of Django-Tastypie, the oldest REST framework for Django. It predates Django-Rest-Framework and comes from the very earliest days of Class-Based Views, from when they were still very controversial. It's still in use by a lot of developers and companies, though these days the primary development efforts are in keeping it up-to-date with Django releases and bugfixing. It's still in Beta for some legacy reasons, but it's exceptionally mature.
This post is about a task I do roughly once a year, and forget how to do correctly every time: cut a new release. Because release management is not part of my day job and because I only do it once or twice a year, I always get something wrong.
The Right Process (for tastypie)
1. Bump the version number in tastypie.VERSION
TastyPie's version is written in one and only one place in the code: tastypie.VERSION. Every other mention of the version in code imports from that, to keep things from getting out of sync.
2. Update the Release Notes
The release notes are included in the docs. Every new release gets a new notes file, which must also be linked from the release_notes/index.rst page.
Tracking everything that has changed since the last release is a difficult but necessary step. In a perfect world, you'd be tracking changes as they are made, but this is hard enough for a single-developer project much less a community-maintained project. Instead, GitHub provides some tools for this on the Releases page. By default, this page shows the last release and, crucially, a link to show all commits made to master since this release. I try to keep this to the broad strokes, keeping the nitty-gritty details confined to our Backwards-Incompatible Changes file.
3. Release to PyPI
Make sure everything is ready to go before this step. It's not possible to change a release once published to PyPI.
Every time I do this, the toolchain has changed. Most recently, the preferred tool has changed to Twine which was relatively painless (if arcane):
$ pip install twine
$ python setup.py sdist
$ twine upload dist/*
You can provide authentication for twine in a configuration file, but given the recent NPM credential debacle it is probably a good idea to avoid putting your PyPI password in any cleartext file.
4. Create a Github Release / Tag
"Releasing" a Python library on GitHub is a bit of an anachronism; most users will be deploying from PyPI. But it is a simple process (just create a new Draft Release from the Releases page, pointing at either master or a release tag.) and worth it for the rollup diffs and commit log alone. But also, bafflingly, some linux distros still build TastyPie as a package, and they rely on github tags/releases to know when to build a new package.
Go to the releases page to draft a new release, picking the same commit that was published to PyPI to create a tag and name the release similarly.