Single click code-versioning (Complimenting cloud-native Architecture)

DHRUV BANSAL
Deutsche Telekom Digital Labs
7 min readNov 9, 2020

In a typical software development lifecycle, code goes through various stages between the developer’s machine and production. Typical stages would be Development, Testing, User-Acceptance Testing, Pre-Production, and Production. With all these stages into play, there are various means by which a team can maintain code and its versions.

Problem statement

With the growing complexity of businesses and an increase in the pace of change in customer needs, more and more companies are adopting microservices architecture to deliver highly scalable products in highly agile manners. A common pattern in a microservices architecture is to maintain different code repositories for different independently deployable microservices. More code repositories generally mean, at any given point of time, a product is a combination of different versions of those different code bases i.e. few of the microservices might need more frequent changes than others. Maintaining and merging multiple code repositories for different versions manually could be very time-consuming and error-prone.

Pieces of solution

This blog will present a few options for maintaining code and how we have built ‘one-click’ solution to automate code versioning following semantic versioning and code merging using Git and Jenkins pipeline.

There are three main pieces of this ‘one-click’ code-versioning solution :

1. Git workflows

2. Semantic versioning

3. JGit-Flow plugin

I will present all the pieces at a high level and will weave them together to reach to a final solution.

1. Code Workflow with Git

Below, I am going to discuss the two most popular and recommended workflows for git users :

a. Git Flow

Git Flow was created by Vincent Driessen in 2010 and it is based on two main branches.

· master — this branch contains the production code. All development code is merged into master at some point in some time.

· develop — this branch contains the pre-production code. When the features are finished they are merged into develop.

The Lifecycle of these branches is infinite (in other terms they are permanent branches).

Various stages of code such as the Testing phase, UAT phase, Pre-production, etc. are aided by other supporting branches and tags:

· feature-* — this branch is used to develop new features for the upcoming releases. It branches off from develop and must merge into develop. Developers typically use features branches for development.

· hotfix-* — this branch is necessary to act immediately upon an undesired status of master. It branches off from master and must merge both into master and develop. This is essentially meant for bug fixing on the master branch.

· release-* — this branch supports the preparation of a new production release. It allows many minor bugs to be fixed and helps in the preparation of meta-data for a release. It branches off from develop and must merge into master and develop.

The official blog — https://nvie.com/posts/a-successful-git-branching-model/

b. Github Flow

Github Flow is a more mature and lightweight workflow. This workflow complements continuous delivery practices.

Essentially there is only one main branch that is master.

· At any given point of time,masteris, in theory, stable and deployable and ready for production.

· For any code change, whether development or bug fix, create a branch off from master.

· Open a pull request when development is complete in that branch and code is ready for merging.

· Once the code is reviewed and the feature is signed off, the code is merged back to master by the reviewer (or group of reviewers).

· Finally, when the code is in master, code is ready to deploy on production or pre-production.

Given the above two workflows, depending upon the dev team’s maturity team’s select one of these.

Other code workflows

There are two other workflows that are basically derived from the above two basic workflows :

c. GitLab flow

d. Oneflow

Both workflows provide more flexibility based on individual product requirements by introducing the concept of environment branches and other things. Read through the given official document to understand each workflow advantages and disadvantages and select what suits you best.

Now moving ahead from git workflows, the second part of the solution is semantic versioning.

2. Semantic versioning

Semantic versioning (Semver) aims to bring some rationality to the management of rapidly moving software release targets. Versioning our code helps us to track every transition in the software development phase. Moreover, it helps to track what’s been added/removed and at what point.

Semantic Versioning is a 3-component number in the format of X.Y.Z, where :

· X stands for a major version.

· Y stands for a minor version.

· Z stands for a patch.

Given a version number MAJOR.MINOR.PATCH, increment the:

1. MAJOR version when you make incompatible API changes

2. MINOR version when you add functionality in a backward-compatible manner

3. PATCH version when you make bug fixes in a backward-compatible manner

Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

Official blog

https://semver.org/

Moving onto the third piece of solution JGit-Flow plugin.

3. JGit-Flow plugin

JGit-flow plugin is a Maven plugin that supports git-flow workflow in maven projects. This plugin abstracts git-flow workflow stages via maven goals and also incorporates semantic versioning concepts.

JGit-flow plugin features

It provides commands and abstracts out all git-flow functionalities

· starting a release — creates a release branch and updates pom(s) with release versions.

· finishing a release — runs a maven build (deploy or install), merges the release branch into both master and develop, updates pom(s) with development versions.

· starting a hotfix — creates a hotfix branch and updates pom(s) with hotfix versions.

· finishing a hotfix — runs a maven build (deploy or install), merges the hotfix branch into both master and develop, updates pom(s) with previous versions.

· starting a feature — creates a feature branch

· finishing a feature — merges the feature branch into develop.

Example of JGit-flow maven goal

Suppose the code in the develop the branch is 1.0.0-SNAPSHOT and now you want to create a release branch out of the develop branch to promote the code for Testing or UAT, the following command will do both — create a release branch with the desired semantic version and change the code version in the develop branch. For example, if you want your release code version to be 1.0.0-RC and develop code version to be 1.1.0-SNAPSHOT, the following JGit-flow plugin will do version changes and will create a new git release branch.

mvn jgitflow:release-start -DallowSnapshots -DreleaseVersion1.0.0-RC -DdevelopmentVersion=1.1.0-SNAPSHOT

Similarly, you can end the release, and thereafter the code will be merged in master and a tag will be created.

Enough of context-setting :). Let’s tie all these pieces together to reach a target state where all these concepts are weaved into a one-click solution for code versioning via Jenkins Pipeline. We use this single pipeline to version our code for all the microservices (currently we have 8 microservices, which essentially means 8 different GIT repositories for our product).

JGit Jenkins Pipeline

JGit Jenkins pipeline is an abstraction over gitflow-workflow and helps to orchestrate code branching and release management.

How JGit pipeline works :

1. First step is to add configure JGit-plugin in your maven project.

2. The Pipeline takes all the code repository references as input.

3. This pipeline offers two modes right now -

· start-release

· end-release

Start-Release

Start-Release will execute the following steps for all the code repositories :

o It will compare the code of configured develop and master branch, and smartly figure out if there are any code changes to be released.

o If there are code changes to be released, the pipeline will execute ‘jgitflow:release-start’ command to create release-[version] branch from develop branch taking into account semantic versioning for both the branches.

o If no code changes are found then nothing happens for that code repository.

End-Release

End-Release will execute the following steps for all the code repositories :

o It will figure out for what all code repositories’ release branch exists by the configured release branch pattern.

o If release branch is found then ‘jgitflow:release-end’ command is triggered to finish the release branch and code is merged in master and the tag is created on the merged code. It will also merge the release in develop branch

o If no release branch is found then that code repository will be skipped for release end operation.

Summary

With the help of this solution, we are able to automate the code merge and semantic versioning of around 10 microservices in a single click. Automating this task has helped us save a lot of time and manual effort and made our delivery and release process faster and less error-prone.

Git hub repo

This repository has code for the pipeline and all supporting documentation on how to configure the pipeline in Jenkins and the internal working of the pipeline.

Contributors

Kudos to Vatsalya Singh who contributed and helped in releasing 1.0 version of this pipeline.

--

--

DHRUV BANSAL
Deutsche Telekom Digital Labs

Loves to architect, build & scale disruptive technology consumer products