Automate software versioning, release and changelog with CI/CD pipelines

What is software release?

What is software versioning ?

Common method of versioning

  1. Semantic versioning — this is common method used , where by it consist three groups of numbers Major, Minor and Patch; Semantic version has this structure MAJOR.MINOR.PATCH
    — PATCH
    is counter for bug fixes
    MINOR is counter for functionalities
    MAJOR is a counter for product changes
  2. Date of release — The software version number is the date of the release example UBUNTU 22.04
  3. Sequential numbering — assigned a unique identifier that consists of one or more sequences of numbers or letters used to convey the significance of changes between releases. The level of significance are classified by changes from the previous release.

Why do we need of versioning

How ClickPesa implement software versioning, release and changelog

const gulp = require('gulp');const runSequence = require('gulp4-run-sequence');const jsonModify = require('gulp-json-modify');const gap = require('gulp-append-prepend');gulp.task('autoVersion', async function () { // Run tasks sequentiallyrunSequence('upVersion', 'saveVersion', 'updateChangeLog');});gulp.task('upVersion', async function () {let ver = require('./package.json').version; //version defined in the package.json fileconsole.log('current version: ', ver);let splitString = ver.split('.', 3);let majorVersion = splitString[0].split('"', 1);let minorVersion = splitString[1].split('"', 1);let patchVersion = splitString[2].split('"', 1);let patchNumber = Number(patchVersion[0]);let minorNumber = Number(minorVersion[0]);let majorNumber = Number(majorVersion[0]);if (patchNumber < 9) {patchNumber++;splitString[2] = String(patchNumber);} else {splitString[2] = String(0);if (minorNumber < 9) {minorNumber++;splitString[1] = String(minorNumber);} else {splitString[1] = String(0);majorNumber++;splitString[0] = String(majorNumber);}}process.env.VERSION = splitString.join('.');console.log(' new version : ', process.env.VERSION);});gulp.task('saveVersion', async function () { // saving new version number into package.jsonreturn gulp.src(['./package.json']).pipe(jsonModify({key: 'version',value: process.env.VERSION,}),).pipe(gulp.dest('./'));});gulp.task('updateChangeLog', async function () { // add changes into changelog filelet messages = process.argv[4];console.log(messages);messages = messages.replace('>', '*');console.log(messages);if (messages != '') {gulp.src('./changelog.md').pipe(gap.prependText(messages)).pipe(gap.prependText(`# v${process.env.VERSION}`)).pipe(gulp.dest('./'));} else {console.log('no commit messages');}});

We added step for bump version which will do the following

  1. First retrieve all merged branch commit as save them it bash variable as RELEASE_DETAILS
  2. We use gulp which is javascript package for streaming task runner that lets developers automate many development tasks , so after having RELEASE_DETAILS we passed them into Gulpfile which handle all tasks
    - gulp autoversion --t "${RELEASE_DETAILS}"
  3. On gulpfile.js
master:
- step:
name: bump version
  1. Starting with upVersion() task
    What it does is looking into package.json file and get the version number , depend on your way of versioning it can be Semantic or Sequential or other custom way what needed it you will do your magic of bumping up version number and save the new value in example above new version number is saved on this process.env.VERSION
  2. Then we are going to update Package.json file with new version number you can see on code above on this task saveVersion()
  3. Final task is updateChangeLog() file 2. Remember we passed RELEASE_DETAILSon step 1 which has commits of branch which is merged all details are extracted and saved on variable message you can see on step above where version and commit are added on change log file 3. This is changelog.md file we have with our version 0.0.1 changes
v0.0.1👌 IMPROVE: create PR for each branch from staging to master🐛 FIX: Inject winston logger to the provider👌 IMPROVE: Use one queue to process different jobs🐛 FIX: Add EBUREAU_WALLET_PAYOUT_TRANSACTION_QUEUE initialization📦 NEW: Implement a queue for wallet payouts🤖 TEST: update changelog file and bump version

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store