Too many times this year I've found myself struggling to improve my [blog pipeline](/series/blogging-with-quartz/) because I couldn't keep track of when code stopped and started doing what it was supposed to do. This was entirely my own fault, I was not observing best-practices:
All of this worked well enough for private use monoliths, one-offs and skunkworks projects but these Drone pipelines presented a new challenge.
Drone pipelines tend to be structured as a series of docker images operating on a mount that gets injected into all of them so they can share their work. This is fine, docker images are an easy fire-and-forget solution for deploying tools.
As things grew more complex, my sloppy coding practices put me in a lot of unnecessary tight spots.
- Some parts of the pipeline were idempotent, others weren't.
- Some parts of the pipeline were affected by each other's work. For example, one step scans files for attachments and copies them into Hugo-appropriate directories, and the next transforms links from Obsidian to Hugo layouts.
- I frequently wanted to implement multiple features/fixes simultaneously but when this took longer than planned, rolling back to a known-good version was impossible because my docker images are only tagged with `latest`.
All of this added up to things breaking for far longer than they needed to, more often than they needed to. Eventually, enough was enough. I drew a line in the sand and decided that I wasn't going to live like this anymore.
After some digging I found resources that helped me build a Makefile to take care of things. That first Makefile added a **lot** but I'm only going to cover the tooling for semantic versioning and git tagging; the rest of that Makefile was go cross-compilation and docker image stuff that I'm replacing with bazel.
To handle automatically incrementing semver values, I landed on `bump`. Because it's written in Go, I was able to fork it and patch a few minor issues and make sure that it keeps working for the foreseeable future.
[bump](https://github.com/guilhem/bump) is a golang utility that'll read a git repository's tags and apply a [semantic versioning](https://semver.org/) compliant version increment. `bump patch` bumps `v0.0.1` to `v0.0.2`. `bump major` goes from `v2.24.5` to `v3.0.0`. You get the idea.
All together, this suite works perfectly for handling tagging. I don't have a super rigorous policy on what constitutes a major, minor, or patch version but being able to `make bump-patch` to tag a specific known-good commit made a world of difference. My drone pipelines became drastically more reliable thanks to version pinning.
Bazel isn't directly involved in manipulating tags yet. To do that, I'll need to add bazel build files to the `bump` repo. I'll cover that in the next post, where I cover how to use bazel's stamping funtionality.