A release just went out this morning and your colleague just came back from holiday. A large bug surfaces on production and a QA asks, “What’s the cause?”. We look at the commits and find the associated ticket. The commit is in the release, but the ticket was never tested, tagged, or put into the release notes. Humans make mistakes far too often. I’ve seen too much code go to production without proper tagging.
How do resolve this issue and ensure it doesn’t happen again?:
Will these solutions prevent all mistakes? No. These solutions simply provide the rest of your team with more accurate and reliable information relevant to the release. I believe the release process should be less ‘doing’ and more ‘checking’. I want to reduce the amount of work it takes to ‘create’ a release and just ship code. I would like to eliminate all sources of human error, so if I go on holiday I can confidently know tickets won’t be missed and left out. These solutions in turn…
In this article, I will dig deep into each of the 3 solutions above and even discuss some bits to get started on the implementation.
The goal isn’t to entirely automate your release process, rather standardize it and make it consistent for all members in your team.
Ideally, I’d like anyone on the team to easily identify issues in a release without having to go to the developer who implemented the feature.
We should be able to ship code without the ‘coder’ there and be confident in their releases.
When working on a piece of code, I often find that I am working on one of the following:
A release is an amalgamation of these. With this soup of commits, it’s incredibly difficult to spot breaking changes or decide what is the next release version.
Implicitly, I think through the following:
However, I cannot accurately answer these questions without the following information on each code change:
So, I first need to standardize my commits to get this information.
I get a tool (Commitizen) that asks for this information like below
It then adds that information to the commit like so:
Feature
feat(index.js): hello world implementation
#TEAM-101
Bugfix
fix(index.js): fix Hello World copy
fix #TEAM-102
Now, I have all the information needed to decide the release. I can take a list of changes and create a version.
If I give this list to someone else, they may give it a different version since they may miss a breaking change in scrolling through the commits.
Instead, we can version automatically using semantic versioning and thus the versioning will be consistent regardless of who runs a release.
Semantic versioning automatically versions a group of changes based on a particular set of rules. I can generate a version automatically with the information provided above by the commits.
How is this done? It goes through the commits and checks for the biggest change and increments the release. If it’s only a group of bugfixes, it is likely to only increment by 0.0.1. If it’s a mixture like above, the version will be incremented by 0.1.0. And if it’s a full-on breaking change or new system an entire version will be incremented (1.0.0).
This may be an oversimplification as versioning can be quite complex. I recommend starting with these basics and asking your development team the following:
In answering these questions, I can then decide when to version a release with semantic versioning.
In a completely automated development environment, every commit has a version. These can be smaller versions like alpha/beta versions or regular versions. However, if you are versioning and not releasing lots of commits this can get out of hand. I’d recommend switching to automated commits when your development lifecycle is automated and close to a full continuous delivery (almost every commit is a release). Once the cadence of development increases, you can further automate other processes.
When I create a new release, I have a semantic version but I should also share all the code changes with the rest of the team. I can automatically generate documentation from the detailed information provided in my code changes (commits) by semantic versioning. Simply running a release using one of the following of these libraries (standard-version / semantic-release) creates the following: https://github.com/evanjmg/changelog-example/blob/master/CHANGELOG.md
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## 1.1.0 (2020-11-08)
### Features
* **index.js:** hello world implementation ([84a478c](https://github.com/evanjmg/changelog-example/commit/84a478cca57635ccfb5d98e822d13c5f6b4b9c75)), closes [#TEAM-101](https://github.com/evanjmg/changelog-example/issues/TEAM-101)
### Bug Fixes
* **index.js:** fix Hello World copy ([d8af554](https://github.com/evanjmg/changelog-example/commit/d8af55417ee5d01db928c4435ca9ebf24d18af64)), closes [#TEAM-102](https://github.com/evanjmg/changelog-example/issues/TEAM-102)
This can be customized to link to JIRA tickets and also include filters etc. One can then run another script to copy this log over to your release ticket or document.
The last step is to share the tagged version and changes everywhere:
These steps can be done in the CI or build system with JIRA hooks.
When I decide to make a release, I will make a release commit and it will update the changelog, add tags to all the tickets.
Then any member on your team can click a version and see an accurate list of changes in the release. No tickets will be missed because they aren’t tagged manually by anyone on the team.
The changelog can also be forwarded onto a release ticket if necessary. Users can see specific details of the release or one can just use the JIRA filter of the release to see the status of all
tickets in the release.
In future articles, I will go over specific implementations of this workflow. If you’re interested in a simple code example of what we discussed, please check out this git repo here: https://github.com/evanjmg/changelog-example
Learn how to implement this workflow in Part 2.