Automating spec-tools releases

Ants crawling on an piece old, dry, partially decomposed wood.

My employer, Metosin, is well-known for its Clojure open-source libraries. When people hear that I work for Metosin, they often ask if I contribute to the development of the libraries. I do, but not so much in the form of coding new features or bug fixes. My focus has been on maintainership tasks such as creating releases.

At the moment, we do not have a well-defined process or schedule for releases. Personally, I believe in small releases. If a library has some unreleased work and it looks like there won’t be more changes in the immediate future, I’ll do a release.

The actual release process goes something like this:

Merge ready PRs. First I check out if there are any open PRs that could be merged. If yes, I merge them.

Update the changelog. I go through the PRs merged since the last release and add them to If there are breaking changes, I mark them as such.

Update the version number. If there are breaking changes, I bump the minor or the major number. If not, bumping the patch number is enough.

Build and deploy the release. On a good day, this means running lein release.

Announce the release. Usually just on Clojurians Slack.

This takes quite a bit of manual work and I’d like lessen the load for myself and the other maintainers. As an experiment, I decided to automate build-and-deploy step for spec-tools. It’s a small step, but it’s the easiest to automate. It’s also something that we get regularly wrong:

  • Many of our releases are missing git tags and some of those tags are wrong.
  • Some of the releases have been built against dirty work trees - that is, they contain uncommited code.
  • If there’s Java code (like in jsonista and reitit), it won’t work with Java 8 unless it’s compiled with Java 8. The release is basically broken if you build it while running Java 11.
  • Signing the artifacts with GPG constantly goes wrong.

I used GitHub’s Release feature, GitHub Actions, and a bit of shell scripting to automate the build.

  • There’s GitHub Actions a workflow that runs when you create a new GitHub release. Each GitHub release corresponds to a git tag. The workflow checks out the code for the tag and runs lein deploy.
  • There’s a shell script that does a couple of sanity checks and creates a new GitHub release from the head of master branch. Me and the other maintainers can run it whenever we want to publish a new release.
  • The release artifacts are not signed with GPG. If somebody managed to steal the Clojars deploy token used by GitHub actions, they would be able to steal the GPG key as well. And anyway, I don’t think anyone checks the signatures.

It seems to work! I hope to start to use this in more projects – especially the Java 8 problem would be nice to automate away.

There’s room for improvement, for sure. For example, the GitHub Release text is now just whatever is the latest commit message, and we could trigger a cljdoc build right after the release is deployed.

To go further, we could use a tool like release-drafter to generate the changelog from pull request titles. We’ve used release-drafter for work projects with good results and I’ve experimented with something similar before. This would save a lot of work.

Comments or questions? Send me an e-mail.