Semantic Versioning Should Not Be Scheduled

Created by josh
November 29, 2020 4:28:36 PM PST (Revised November 30, 2020 12:06:17 PM PST )

In my experience developing software for the past ten plus years, two very popular versioning standards have dominated the release cycles of popular applications over the years. For most of these cases, semantic versioning and calendar versioning have worked their way into release cycles of applications that may not have started out with a standardized method.


What is semantic versioning?

Semantic versioning is simply a convention of enumerating a release based on major, minor and patch versions. These numbers are separated by decimals, respectively. Each level outlined corresponds to compatibility impact from one version to the next.

A major version upgrade is considered a breaking, incompatible change between releases. In some cases, a software upgrade process can migrate your application from one major version to the next, but otherwise, it may be such a different system, that you have to start over and figure a process to import your old application into the new version. Regardless, a major version change is a planned, controlled version that anticipates some form of a major upgrade. In larger organizations, a succeeding major version goes through a rigorous process of project planning, scope management and a series of well organized sprints. Without a doubt, a major version will endure vigorous testing and cover many QA strategies before making its way to production.

A minor version update is usually a slew of new features or planned fixes for the current major version. Upgrading to a succeeding minor version should not render the application incompatible with a previous version (in case it has to be rolled back). Minor versions tend to be the building blocks of continuous development, including execution on bug reports, user stories and feature requests. These updates are not supposed to be disruptive to the application at its current major version, but only provide more features or quietly fix outstanding bugs. Known bugs may be resolved in this sprint - in which case, they should have passed various levels of testing before being included in the release. An example might be the option to add "dark mode" to an application's design. Introducing this new feature should not automatically set the application to dark mode - instead, the application should simply provide the option to toggle dark mode.

The patch version should be reserved for unplanned hotfixes or small tweaks. For example, if the application has recently been through the ringer for a minor version upgrade (carefully developed, adequately tested) but somehow breaks in production for some unforeseen reason, it may be urgent enough to quickly "bandage" the issue and release it back to production as soon as possible. If it is determined not to be either urgent or high priority, it may just be thrown onto the list as part of the next minor version. Whether a release requires unplanned turnaround or if there was any change to the codebase whatsoever, the version number needs to be incremented. Sometimes these types of fixes aren't related to something recent - in fact - it may have been triggered by some dormant part of the application that somehow surfaced in some unusual workflow.


Back to the point - why scheduled releases and semantic versioning do not mix?

Let me be clear on my point here - there are a bunch of factors and situations that determine whether or not you should target release dates. Planning on releasing a new major version? Yes - schedule it, prioritize it, set a goal on pre-production, release candidates and a production release. Key word there - "goal". If, say, you end up in the weeds of launching a major release - and it lags during pre-production testing, that will impact when a production release will be available. So having flexibility on the release date will become more and more important. On the other hand, patch releases are typically reserved for unscheduled, high-priority hotfixes. How does it make sense to create an ongoing/routine schedule for unplanned hotfixes? The simple answer - it does not. Especially on the tail of a significant minor release that contains a slew of new features/bug fixes; or any major release, which contains a whole new world of potential unforeseen issues.


So who schedules their releases routinely using Semantic Versioning? A couple examples:

1) Drupal. Every level of release (major, minor and patch versions) are timed within development windows. "Patch releases (9.0.1, 9.0.2, etc.) will have a monthly release window, which will address bugs to be fixed." - Drupal Core Release Cycle. What does this mean? Other than high-priority security hotfixes, which are announced in press releases, deviate from the scheduled window of time. So basically, Drupal has two standards for patch versioning - windows of time to include a slew of very minor fixes and patches vs. urgent patches.

2) PHP. While PHP appears to release patch versions irregularly about every month, many of the patches could have been broken up into more frequent releases. They do provide a calendar for major and minor versions on a sliding scale of active, security, and end-of-life support. This is the current calendar, as of writing this. Anyone remember PHP 6? If you don't, that's because it failed to ever make it to production and they ran the clock out until PHP 7 became the new priority. It didn't have to be that way. They could have spent their time, as planned, focusing on unicode features and eventually accommodate PHP 7 features as minor versions of PHP 6 until development was ready to carry into RC/production.

Let's look at the PHP release timeline a bit differently - was anyone involved upgrading to PHP minor version 5.3 from any earlier version of PHP 5? Talk about incompatible change - PHP 5.3 could have become a whole new major version, PHP 6. In fact, they published a page about it, leading with "Although most existing PHP 5 code should work without changes, please take note of some backward incompatible changes".


So let's look at it again...

1) Major version: Incompatible application changes

2) Minor version: Backwards-compatible changes

3) Patch version: Backwards-compatible bug fixes (I expand this to include small tweaks and hotfixes, but to each their own)

Don't believe me - take a look at the official source for semantic versioning!