In this article I present my highly-opinionated three laws of software versioning. My laws are an academic rung or two below Sir Isaac’s three laws of motion, but I at least have better hair.
The Version Is The Identification
There are lots of articles on the web about software versioning. Mostly about semantic versioning and the general approach of how to name or number a customer-facing release.
That’s good stuff to know, but in my opinion the numbering scheme is rarely the weakness of the software versioning process in a team. Usually the real weakness is a manual and brittle software development process. Resulting in software builds that can’t be reliably identified. Particularly those many interim builds between customer releases.
The entire aim of software versioning is identification. You need to be able to ask a software build “what version are you?”. The answer should allow you to precisely identify the particular code commits used to create the build, and also the particular versions of the build tool-chain. If you don’t have that, you have nothing at all.
Uncannier’s Three Laws Of Software Versioning
Newton’s three laws were inspired by an Apple to the head. My three laws are inspired by pain I have suffered as a software engineer. Pain of my own doing when I was wet behind the ears. More latterly, pain caused by the naivety of others.
1 – The Version Shall Not Be In The Source Code
If you have to make a code commit to change the version, then you’re doing it wrong. If it’s in the source code, you will sometimes forget to change it. Or elect not to change it. You certainly won’t change it for every build. You just won’t. Different builds will report the same version. Even though they behave differently. This means your code is untraceable. If a defect is reported, you won’t know what commit of the code it relates to. Your quality is then non-existent.
2 – The Version Shall Be Automatically Generated At Build Time
In between customer-facing releases, a developer or development team will typically make many builds that will have internal customers. QA, sales and marketing demos, and so forth.
Every build that will ever be used by someone other than the developer, must have a unique version number. Every build. The best way to achieve that is by generating the version automatically at build time.
When you automate, you can automate a lot. Consider to have extended version information that captures the commit hash and/or the build time to help guarantee uniqueness and traceability.
3 – All Internal & External Release Builds Shall Come From a CI Server, Never A Developer’s Machine
The most reliable way to automate version generation at build time is to make it the responsibility of a Continuous Integration server. By doing this, it becomes trivial to include the branch name, build number, commit hash and build time in extended version information. Coupled with the CI server’s build logs, every build can be easily traced back to the matching code commits and the version of the build tool-chain.
Never allow developers to disseminate builds that come from their personal machine. Such builds lack the above-mentioned traceability. You can’t even be sure what versions of the build tools were used to generate the build, since no build logs were created or archived. Even the offending developer can’t tell you anything reliable just a matter of hours or days later. You are wasting everybody’s time when giving mutant local builds to QA for example. Give them a CI build from your feature branch.
You would think that software versioning should be an innocuous and dull topic. I can’t really argue the “dull” part, but I have seen software versioning, or the lack it, being genuinely harmful to the productivity of teams.
Don’t undersell the importance of rigorous software versioning. It’s a chain of custody, a record trail, that will allow you to do proper forensics on your code when defects get reported. Without it, your process will have a low signal-to-noise ratio. You should set it up early in your project.