Versioning and Continuous Delivery
Continuous delivery is the latest automation that can really save you a lot of time when developing, testing and pushing to production your code. Instead of manually building your application and uploading to a server (plus many more actions in between), you can simply automate the whole process.
The above automation is simple and before achieving it, you should be able to do the following first:
- Identify your build process
- Create a script or pipeline that can run the process above
- Automatically trigger the previous script to be executed on specific events
For more information in the continuous delivery process, you can search for products like BitBucket pipelines or Buddy to understand how they can automate the entire deployment using simple actions and events.
When your project has only one stable and live version at any given time in production, then things are quite easy. You can setup your pipelines once and make them run every time, simply by mapping your triggers when merging on specific branches, for example:
- master → Production
- master → Staging (recommended, test before Production)
- develop → QA
Some of the above can be automated and some can be manual in order to give you more control and extra testing, but this is not required. You can automate your entire deployment process according to your business needs.
Sometimes it’s important for your project to allow multiple versions in production because different clients use different versions.
An example of multiple versioning is an API. When you allow your clients to connect to your API, you want to support their application even when you release updates that are backwards incompatible, at least for a while, until you notify them that the old version is deprecated and is going to be discontinued.
With multiple versions, structure and branching is the first concern that developers might want to deal with. To put it simply, how are you supposed to structure your repository in a way that it can support your multiple versioning? There is a design that I am suggesting and I am using the last years for both work or personal projects, and you can read more in Git Workflow / Branching.
Since branching is solved, automation of something that is not stable can be tricky. I mean, based on the above (and known) Git Flow, the team is supposed to create different branches on every version. How can you automate the deployment?
First let’s examine how your version branches are going to look like.
Based on the semantic versioning, there are 3 types of changes:
- PATCH version when you make backwards-compatible bug fixes
- MINOR version when you add functionality in a backwards-compatible manner
- MAJOR version when you make incompatible API changes
To explain better, here are some examples:
- 1.0.0 → 1.0.1: Fixed some bugs without any impact in any output
- 2.3.5 → 2.4.0: Added a new feature, old features are not affected at all
- 3.5.6 → 4.0.0: Deleted or changed an existing feature and some existing API calls will probably fail
Seeing the above example, we can easily understand that clients can use the same API for PATCH and MINOR changes to your version but when it comes to MAJOR version changes, you have to notify them about the changes otherwise their system might behave strange, or even crash.
Based on the above assumption, it’s safe enough to say that you can separate your deployment based on the MAJOR version, so a possible structure could be something like this:
- /path-to-your-api/v1/ (branch v1)
- /path-to-your-api/v2/ (branch v2)
- /path-to-your-api/v3/ (branch v3)
- /path-to-your-api/v4/ (branch v4)
Regarding your repository, you can simply create different release tags for every PATCH and MINOR changes on every release branch to identify different release versions:
- branch [v1]: tags v1.0.0, v1.0.1, v1.1.0, v1.4.5, …
- branch [v2]: tags v2.0.0, v2.0.4, v2.1.0, v2.3.1, …
- and so on…
Automation of Deployment
Since we have concluded the structure of the repository in combination with the deployment structure, the real question is:
How do we automate it?
Let’s make it simple and ask the real question(s):
- Do we really want to fully automate this process? If yes, which part exactly?
- How often do we create new backwards incompatible versions?
So far we have seen that branch v1 will be deployed to folder /path-to-your-api/v1/ and so on. So, I guess that someone has to manually make this automation (like any other automation in the beginning). What if you did the same for v2, v3 etc.? Simply document the process and do it again (or copy paste the pipeline, change some parameters and voila!).
Well, if you really need to automate the above processes, meaning that you create new MAJOR versions often (every month for example), perhaps you should re-consider your versioning workflow and re-design it.
Continuous Deployment of multiple versions is no different from normal continuous versions, you just have to setup your new version every now and then (sometimes it will be months or even years) and you are all set.
I have applied this approach through the last years in all the different companies I have worked and in several, different in needs, projects. We just create a new pipeline for each version (so far there are only a few) and we are done. From this point on, we just push to the right branch and it’s deployed automatically.
Thanks for reading! Feel free to comment and discuss about the above approach. If you like the article please “hit” the green heart to recommend it!