Two words that strike fear in the heart of every software developer: "release process". Whether deploying a new version of a billion-person social network or a tiny little open source library, release processes are often manual, complicated, and easy to mess up.

Much has been said on the "new version of a billion-person social network" side. But what about those small, barely a person, open source libraries?

The focus here will be on

  • Open source
  • Python libraries


A new version? What is the number?

As already explored, CalVer works better than SemVer. So you already know something about the version.

With most standard CalVer schemes, the version starts with <Year>.<Month>. For example, something released in April 2023 would be 2023.04....

One option is to choose as the last digit a running number of releases in the month. So, 2023.4.3 would be the third release in April 2023. This means that when assigning the version, you have to look and see what previous releases, if any, happened this month.

More stateless is to choose the day. However, this means it is impossible to release more than once per day. This can be literally irresponsible: what happens if you need to quickly patch up a major goof?

There is another, sneakier, option. It is to take advantage that Python version standard does not mandate only three parts to the version.

For example, 2023.4.27.3 could be the third release in April 27th, 2023. Having to quickly release two versions sounds stressful, and I'm sorry someone had to experience that.

On top of all the stress, they had to have the presence of mind to check how many releases already happened today. This sounds like heaping misery on top of an already stressful situation.

Can we do better? Go completely stateless? Yes, we can.

Autocalver will assign versions to packages using <Year>.<Month>.<Day>.<Seconds from beginning of day>. The last number is only a little bit useful, but does serve as an increasing counter. The timestamp is taken from the commit log, not the build time, so builds are reproducible.


"Three may keep a Secret, if two of them are dead.", Benjamin Franklin, Poor Richard's Almanac, 1735.

Uploading your package to PyPI safely is not trivial. You can generate a package-specific token, then store it as an encrypted secret in GitHub actions, and then unpack it at the right stage, avoid leaking it, and push the package.

Sounds like being half a bad line away from leaking the API key. Luckily, there is a way to avoid it. The PyPI publish GitHub Action uses OpenID Connect to authenticate the runner against PyPI.

You will want to configure GitHub, with the appropriate parameters, as a trusted publisher.


When do you release? Are you checking releases manually? Why?

CI should make sure that, pre-merge, branches pass all automated checks. "Keep the main branch in a releasable state", as the kids used to say.

Wait. If main branch is releasable, why not...release it?

      - trunk

This will configure a GitHub action that releases on every push to trunk. (Trunk is the "main branch" of a tree, though yours might be named differently.)

See the entire action in autocalver's workflows


Configuring your project to use autocalver gives you automatic version numbers. Using PyPI/GitHub trusted publishing model eliminates complicated secret sharing schemes. GitHub upload actions on merge to main branch removes the need to make a decision about when to release.

Putting all of them together results in releases taking literally 0 work. More time for fun!

The "Dynamic" Properties in PyProject

Fri 30 December 2022 by Moshe Zadka

When writing a pyproject.toml file, the project section is optional. However, if it does exist, two of its properties are required:

  • name
  • version

If these two properties are not there, the section will be ignored.

This is a lie. But it is not a big lie: it is almost …

read more

On The Go

Sun 14 August 2022 by Moshe Zadka

Now that travel is more realistic, I have started to optimize how well I can work on the go. I want to be able to carry as few things as possible, and have the best set-up possible.


Power Bank charging

The "center" of the mobile set-up is my Anker Power Bank. It …

read more

Reading the Documentation for Popular Products

Sun 20 February 2022 by Moshe Zadka

Popular products often have a "Getting Started" tutorial in order to guide you in using them for the first timees. Those guides are easy to follow, pleasant to use, and lead you do make bad design choices.

Follow the "Getting Started" guide to get a feel for the product. Then …

read more

Three Problems with a Tool

Fri 24 December 2021 by Moshe Zadka

One of my favorite Podcasts, Podcast.__init__, always makes sure to ask one question towards the end of every episode: when should you not use the tool or technique introduced in this episode? This is a great question. When people have a poor answer I assume that the tool is …

read more

Better Outage Retrospectives

Sun 15 August 2021 by Moshe Zadka

Originally published on Enable Architect.

Modern computer systems supply business-critical services everywhere -- from Amazon providing shopping services to providing enrollment in health insurance plan. We all rely on such systems. But, unfortunately, these systems are complex and can fail in surprising ways.

By now, it is a well-understood …

read more

Empathy vs. sympathy for Site Reliability Engineers (SRE)

Thu 15 July 2021 by Moshe Zadka

This article was originally published on Enable Architect

Many people have had the insight that DevOps is about people. Often, they will summarize it as "DevOps is about empathy". I have found, however, that idealizing empathy is just as bad as thinking that DevOps is about a single technology.

I …

read more

Minimal packing list

Wed 07 July 2021 by Moshe Zadka

With in-person conferences starting to open up, I need to clear the dust off of some skills that have not been used in a while. One of those is how to pack for travel.

This list works for me. It will probably not work for you as-is. Among other things …

read more

Post that PR

Wed 16 June 2021 by Moshe Zadka

Sometimes you will be working on hairy and complicated feature in a shared repository. Maybe it's for work. Maybe it's an open source project.

As a responsible person, you are working on a branch. The usual way of working involves a lot of "intermediate" check-ins. Those serve, if nothing else …

read more

Portable Python Binary Wheels

Mon 05 April 2021 by Moshe Zadka

It is possible to work with Python quite a bit and not be aware of some of the subtler details of package management. Since Python is a popular “glue” language, one of its core strengths is integrating with libraries written in other languages: from database drivers written in C, numerical …

read more