Automate software versioning, release and changelog with CI/CD pipelines
What is software release?
Is the final version of software released to the end-users after further enhancements and bugs fixes
What is software versioning ?
Software versioning is the process of numbering different releases of a particular software program for both internal use and release designation.
All released changes with version number are recorded in specific order into a file know as changelog
Common method of versioning
-
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
- ** Date of release - **The software version number is the date of the release example UBUNTU 22.04
- 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
It allows programmers and all people to know when changes have been made and track changes enforced in the software. At the same time, it enables potential customers to be acquainted with new releases and recognize the updated versions.
How ClickPesa implement software versioning, release and changelog
As ClickPesa we like to automate our process in order to increase our productivity and smooth things by removing human errors, we decided to let pipeline handle versioning process , let see how we manage to achieve this
For branch or feature which are ready to be deployed in production means PR will be created to Production and merged to master , pipeline will run with master Branch
Actually we are using Bitbucket so pipeline is set as
master:
- step:
name: bump version
We added step for bump version which will do the following
-
First retrieve all merged branch commit as save them it bash variable as
RELEASE_DETAILS
-
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}"
-
On gulpfile.js
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 sequentially runSequence('upVersion', 'saveVersion', 'updateChangeLog'); }); gulp.task('upVersion', async function () { let ver = require('./package.json').version; //version defined in the package.json file console.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.json return gulp .src(['./package.json']) .pipe( jsonModify({ key: 'version', value: process.env.VERSION, }), ) .pipe(gulp.dest('./')); }); gulp.task('updateChangeLog', async function () { // add changes into changelog file let 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'); } });
As we you can see we call runSequence which call other three tasks upVersion, saveVersion and updateChangeLog
As we can see our trigger tasks which is autoVersion
called from a pipeline and inside of it there is runSequence function which call three tasks upVersion, saveVersion and updateChangeLog in sequence
Let's take a look on each task
- start 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
- Then we are going to update Package.json file with new version number you can see on code above on this task
saveVersion
-
Final task is updateChangeLog file
- Remember we passed
RELEASE_DETAILS
on 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 - This is changelog.md file we have with our version 0.0.1 changes
v0.0.1
- Remember we passed
* π IMPROVE: create PR for each branch from staging to master
* π FIX: Inject winston logger to the providers
* π FIX: import statements path
* π IMPROVE: Add wallet transfer transaction job before the payout
* π IMPROVE: Use one queue to process different jobs
* π FIX: Add EBUREAU_WALLET_PAYOUT_TRANSACTION_QUEUE initialization
* π¦ NEW: Implement a queue for wallet payouts
* π IMPROVE: add dependencies for gulp
* π FIX: name of step for bump version
* π€ TEST: update changelog file and bump version
Wow! Remember we modified two files package.json by updating version number and changelog.md by adding changes.
Back on the pipeline process all change files will be committed and pushed as per your setup develop or master branch.
Top comments (0)