Bullshitless Versioning

Posted on March 14, 2017 · 6 min read

I have to admit the post title is deliberately provocative but I'll try to prove that it's not necessarily inaccurate, although I could certainly have titled it Versioning Internal Applications or Simplified Versioning.

Semantic Versioning

Semantic Versioning, a.k.a. SemVer, is a set of rules that define how version numbers should be assigned and incremented.

The versioning scheme is X.Y.Z, where:

  • X is the MAJOR version
  • Y is the MINOR version
  • Z is the PATCH version

And according to SemVer, given a version number MAJOR.MINOR.PATCH, increment the:

  • MAJOR version when you make incompatible API changes,
  • MINOR version when you add functionality in a backwards-compatible manner, and
  • PATCH version when you make backwards-compatible bug fixes.

The case for SemVer

As one can conclude from the SemVer definition and its purpose, it's definitely relevant and useful for public APIs and libraries to ease the dependency management and reduce dependency hell.

The case against SemVer

What about versioning internal applications? You'll probably have several of them and also some being dependencies of others. Does this necessarily mean that you have to version them using SemVer?

Deciding the next version in advance

If you operate selecting the new developments to include in the next release, you're forced to analyze them to decide whether those are major, minor or patch changes. This, of course, means that the version will be held hostage until everything is finished.

Even if you defer that decision until the last minute, there's always a time window when that version is held hostage and any unexpected change of plans forces you to deal with it.

Managing concurrent versions

With the previous setup, having multiple teams working concurrently in the same codebase can be tricky, especially when things go wrong and you have to deal with rollbacks and patches.

Minimal releases

On the other hand, you might consider that grouping several features in the same release is not a good idea. You want the flexibility to be picky, be able to rollback just one feature and so on. Then you can decide to include a single feature in each release, so you develop each feature in its own branch and, when it's ready to deploy, assign the next version number and release it.

This means you have to coordinate a lot to avoid race conditions while picking the next version number.

Contiuous deployment

If you want to do continuous deployment, you can build a GitHub hook / CI job / whatever to automate the assignation of the next version number when anything is merged to the master branch. Needless to say it always needs the input of a human to decide whether the new release is considered a major, a minor or a patch.

Is it really worth it?

Great, you're there but, are you really using the SemVer version number for anything? Not at all.

The end users of our internal applications don't care if the changes are major or not, if you had to deploy many services at once, or if there's been a data migration to accommodate to a new data model.

Within the development team there's also no need for that. Either way you should keep track of the deployments you make, which versions are currently in production and which changes they contain regarding the previous version. SemVer doesn't free you from doing so.

Simplified versioning

All you actually need is to have a reference to a specific artifact representing the state of the code repository at some point in time, nothing else. At the same time you want to easily distinguish between development and production-ready artifacts.

Let's simplify versions to just BRANCH-COMMIT, where:

  • BRANCH is the SCM branch
  • COMMIT is the hash commit where the artifact has been built from.

What do you get with that?

  • No distinction between versions regarding deployment automation
  • No release vs. feature versions, no SNAPSHOTS.
  • Development, test and release life-cycles can be easily automated (CI + CD)
  • Because you don't need to assign an artificial version label to an artifact, any commit from any branch is deployable
  • Enables testing each commit independently
  • No need to categorize the nature of changes to decide the next SemVer
  • No coordination among developers regarding versioning

Of course, you still have to make some kind of Release Notes to describe the contents to the users, but that's pretty much it.

Branching model and development workflow

This simplified versioning eases Continuous Deployment. SemVer doesn't prevent that, but you can skip dealing with automating the semantic part of the versioning.

With a simple branching model consisting of:

  • master representing production
  • all other branches for development

and a couple of CI jobs:

  • one for the master branch which
    1. runs unit tests and, if everything is green
    2. generate the artifact and deploy it to staging
    3. run integration and functional tests and, if everything is green
    4. deploy to production
  • a generic one which
    1. receives notifications from new PRs
    2. runs unit tests and, if everything is green
    3. generate the artifact and deploy it to development
    4. run integration and functional tests and, if everything is green
    5. mark PR as valid

Developers can create a branch from master, make several commits and finally open a PR to master. This will run the unit, integration and functional tests in a dedicated environment and report back to the PR.

Anyone can then perform further testing using the generated artifact. When it's considered stable, they can trigger the deployment in production just by merging the PR to master.

Bullshitless versioning

After defining this versioning scheme and coining the term together with Albert Serrallé, we assumed we couldn't actually be the first ones to come up with this.

We came across this post on the Dave Hall Consulting's blog which advocates for date based version numbering for internal applications, but so far we haven't found anything similar to our proposal.

Maybe it's nonsense and we haven't realized yet, maybe it's something that's not being publicly promoted because it's only used internally (of course, we're talking about versioning internal applications), or maybe we're just the ones having this problems because we were not doing it right in the first place. Either way, it's working pretty well for us so far.

Do you have any thoughts on this? Feel free to leave a comment or contact me.

References


Comments

Would you like to leave a comment? Since this blog is hosted on GitHub Pages there's no straightforward way to do so.

Instead, you can add a comment in this GitHub issue. If you'd like to see it here, refresh this page after posting the comment.