At Batteries911, the BE team has the responsibility of maintaining an API that is consumed by 3 (soon 4) different clients: two iOS applications and a SPA. This means that, whenever we introduce a change, we need to be absolutely sure that the change is either non-disruptive or, if it is, that it was communicated properly and coordinated with all the FE teams.
For a long time, we just relied on Slack for this job: whenever we changed something in the API, we’d send a message in a Slack channel aptly named dev-integration, so that everyone knew about the change (or so we thought).
We were pretty satisfied with our approach, but then things started to break because people were not aware of some change we applied or some endpoint we removed. Going back to fix the issue when the release had already reached the QA phase was time and money-consuming. Moreover, we were losing visibility of how the API was changing over time, which meant it was often hard to track down issues.
Much to the joy of the iOS and Web teams, the decision was made to adopt Semantic Versioning for our API and to start keeping a changelog.
There were definitely challenges involved in this, though: how were we supposed to ensure that the changelog was accurate? Who would take on the responsibility of writing changelog entries at the end of each release? We already had so much on our minds that the additional burden of keeping a detailed list of every single change seemed like an impossible feat.
Also, no one was happy with the fact that we had just lost our rolling release approach to releasing and would start to version our software like some old, boring enterprise.
In other words, there was definitely some initial resistance.
And yet, we came to love our changelog and our version numbers, and the structure and guidance they provide. Today, we keep our changelog entries diligently, and we tag our major, minor and patch versions with care.
So how did we do it?
Let me start with an important point: not all software needs versioning, or a changelog. If you’re building an MVP, versioning is probably not for you. If you work on a traditional full-stack website, then it’s very likely you don’t need versioning either.
The bottom line is that versioning is an overhead on top of your development process, so it should only be adopted where it provides tangible benefits. With that said, there are many many cases where it provides benefits, so think twice before you dismiss it as useless. Here are some examples:
Even if you don’t belong to any of these categories, you might still want to practice your versioning skills, which is perfectly fine. Just be mindful of the additional work you’ll have to do, and make sure that you’re not bogging down your team with unnecessary chores.
The versioning process that we came up with is dead-simple. The trick was to make sure that it was impossible not to follow the process, so that people were forced to adopt it and it became part of their workflow. For instance, here’s what we did at Batteries911 for the initial setup:
With this setup in place, it was pretty much impossible to miss a step of the process: it would be caught either by the checklist or by the PR’s reviewer. Of course, this approach requires discipline: all changes must be made in a PR and all PRs must be reviewed thoroughly. If you can ensure this happens, you’ll have peace of mind.
At this point, you might be wondering why I speak of versioning and the practice of keeping a changelog seem as if they were so intertwined. After all, you can record changes even without version numbers, and you can have version numbers without recording changes, right?
Well, since Semantic Versioning requires you to advance version numbers not based on some arbitrary choice, but on the kind of changes that you are introducing with the new version, a changelog is an invaluable tool when picking the new version number.
For us, a new release usually starts without a defined version number. We just call it “unreleased”, because don’t know what kind of changes we’re going to make — we do have an idea because we know what goals we want to achieve, of course, but we might not always know how to do it yet. Then, as we start writing code, we also start accumulating entries in the release’s changelog.
Source: xkcd.com
When the time comes to release the new version, the team lead looks at the changelog and can immediately see what number to increment: if the release only contains bugfixes, we need to increment the patch number; if the release contains new features, we need to increment the minor version; if the release contains backwards-incompatible changes, we need to increment the major version (hint: if this happens too often, something’s off).
This approach works perfectly for us, because it allows us to keep track of everything that happens without sacrificing the smallest hint of flexibility.
We are currently experimenting with novel ways and processes that will keep us in check: for instance, we are working on a GitHub bot that will analyze PRs to check for changelog entries and whether those entries seem to make sense. This can be achieved with some API introspection and is proving a very fun challenge to work on.
For the time being, we are quite happy with a process that satisfies everyone: the BE team has more visibility into what they are doing and their work is more structured, the FE teams are always in the loop about what’s going on with the API, and management can easily get insight into the product’s development and velocity.