A Beginner's Guide to Versioning Software

Why Do We Declare Versions for Our Apps?

You have just built a stable version of your app. You are incredibly proud of your work, you have deployed to a cloud platform, and intend to continue to develop it. It has been your intention the entire time to continuously integrate and continuously develop the app.

Eventually, you are going to push more and better code up to your host. Maybe you have open-sourced your project, and other developers have taken an interest in your project and are contributing to the codebase. It is time to start declaring versions for your app, if you have not already.

The general authority on software versioning is Semantic Versioning. For a more in depth guide, please visit their website.

Please note that adding a version number to your app is not an acceptable replacement for a high-quality readme file or API documentation. An update of your version number should take place alongside updates to readmes and other documentation.

What Do the Three Digits in a Version Mean?

Semantic versioning uses a decimal structure of 0.0.1. The first number indicates the MAJOR version release; the second number (between the decimals) indicates the MINOR version release; and the third number indicates PATCHES on the version.

A MAJOR version is incompatible with previous released versions. The major version number should be incremented when a release's API is incompatible with previous released versions of the software. Essentially, any software that is dependent on your API will probably have to update their package dependencies. An exception is if the software is on major version 0. Versions beginning with 0 are not consider stable and may regularly deploy incompatible code.

A MINOR version may have substantial feature changes and improvements, but all improvements are backwards compatible for people accessing your software. Updates with feature deprecation also require a minor version release. Best practice is to include any feature deprecation in a minor version update even before a major version update, as it will give dependent developers and applications time to smoothly transition to your API update.

A PATCH version is a release with only minor feature tweaks, front-end or code styling updates that do not change any routing, bumping your own app's dependencies, so long as those patches do not change the API.

The MINOR version number resets to 0 when a new MAJOR version is released. Likewise, the PATCH version number resets to 0 when a new MINOR or MAJOR version is released.

Major, Minor, or Patch

As a beginning developer that has only a few deployed projects to my name, I largely control what I consider a major, minor, and patch updates. While Semantic Versioning has a few rules, this is largely how I plan to determine what constitutes a major, minor, and patch update:

Full Stack Web-Hosted Applications with Dual Frontend and Backend Builds
  • MAJOR version updates should virtually never occur. Only depreciating major features or major overhauls of my backend API would necessitate the need for a major version update. Since I am not releasing products to market at this time, and everything is hosted on the web, I have the freedom to continuously develop and integrate systems, and, if anything, I am not going to harm users by necessitating the creating of new accounts or purchase new software just to use my app. Migrations to new web-servers might count as a major version change if it requires changes to some URIs.
  • MINOR version updates will occur after well-planned, significant feature expansions that require extra documentation, new or adjusted backend routes, or complete overhauls of a large number of frontend routes. Other than the final remodeling option, minor version updates will always include some kind of backend restructuring, whether it be the creation of new database tables or additional columns to existing tables.
  • PATCH versions, therefore, are everything else. Bumping a dependency, styling updates, and new features that are limited to the frontend would all fall under the category of patch updates. That is, of course, in addition to simple bug fixes meant to bring an app up to date with what is already in its documentation.
CLI Applications
  • MAJOR version updates for CLIs should, likewise, be avoided until absolutely necessary. Users have a tendency to commit commands into muscle memory, so a major update to a CLI application can actually be more disruptive than even a complete overhaul of a frontend website. For my apps, I would only release a new major version if I was requiring users to install (usually others') additional software for continued use of my application.
  • MINOR version updates for CLI applications would include significant, but not disruptive, feature rollouts. If our application fetches from a backend server and we have expanded our backend with new routes or table columns, that would require new API documentation and, therefore, a new minor version release.
  • PATCH versions are anything else: bug fixes, better --help documentation, improved menus, features increasing security, and bumping dependencies.
  • Documenting Versions with Github

    In some cases, it might be useful to developers to have a unique view on your front-end app devoted to version history or a similar display option on a command-line application. But generally, the most appropriate place for documenting versioning will be API documentation or a Readme.

    Hosting sites, such as Heroku, include version counts for each push, but that is almost always not useful, since it increments only major versions and you may only learn something is unstable in the production build (backend-frontend connections, CORS settings, initializers, etc.) once deployed and make the redeployment patch immediately, so using those built-in version counts as gospel is almost never appropriate. And if you have both frontend and backend servers and view the entire app as your entity, they may not even be on the same hosting version.

    For my active apps, I try to provide a unique version number to all deployed apps with unique code, excluding deployments that only last a small amount of time (usually because I didn't test, thoroughly. Someday, I'll learn that lesson). For apps with a frontend and backend working in unison, I match their version numbers to a given time. (Although, if I deploy an update only one end of the web app, I will only update the Github version on that side of the app. However, the next version number, regardless of backend or frontend, will increment the version of the most recently deployed side.)

    If you store your code on Github, the answer is already built in. Since your Readme is available right up front, and it either links to or contains the API documentation, Github is also an excellent place to document your versions.

    Assuming you follow the same deployment-then-version I do, after deployment, I switch over to Github. On your app's Github page, while the master (deployed) branch is the setting, click on the Release tab. If this is your first release of the app, there will be a button 'Create a new release' that you can click. If you've already saved a version, the button will say 'Draft a new release'.

    From there, you can save your version name, title your release with some candy name or something, and provide a description that briefly explains what is new in this version. Once published, developers will have access to a compressed folder containing all code pushed to Github for that moment of your master branch (or another branch of your choosing).