Conventional Commits & Dynamic Changelog

Conventional commits is simply a way of describing our commit messages using a convention that allows them to be easily read by a machine 🤖
This allows us to use the power of automation in any way we see fit.

What and why?

One of said ways can be to implement a dynamic CHANGELOG file.
A Changelog is generally a file where we keep all the changes made in an app or project such as bug fixes, new features, etc.
The use of a record file like this is for anyone who wants to be up to speed on which features are truly implemented in a project. Another great use for this is when the client asks “Where did this change?” or “When did we add that amazing feature?” we can pinpoint the where and when of the changes.

If you’d like some tips on how to develop an easy to read changelog you can check this small post: How to write a changelog

The issue with changelogs is that it takes the developers from their tasks to go write the changes they committed in a file and can be distracting. So we do what developers do best: we automate. 😎

How?

This section assumes you know what Git is and the basics on how it works.

If you read the first section you may have noticed that the way we write our commit messages can allow a machine to interpret it. This is possible by following a set of rules during our commit process.
Let’s assume we have a few changes in our code to commit and we stage them:

-- CODE language-code line-numbers --
$ git add .

When we’re ready to commit we’ll call the commit command with a message parameter where the magic will happen:

-- CODE language-code line-numbers --
$ git commit -m "feat(homepage): Add alternative footer to the homepage<br><br>

Implement the alternative version of the footer<br>
Add alternate icons in the mobile version of the footer<br><br>
Fixes issue #3"

For the sake of clarity let’s break this message down to its structure:

-- CODE language-code line-numbers --
<type>[optional scope]: <description><br>
[optional body]<br>
[optional footer]<br>

By structuring our messages this way machines can grab every single element — <type>, <description>, etc - and use it for the good of humanity-- I mean for the good of your project!

In the next section, we will list what we can use in our commit messages.

Usage

type: feat [ X.1.X - Minor] | fix [ X.X.1 - Patch]
chore | docs | refactor | improvement [X.X.X - N/A]
(There are other optional types but we’ll stick with these to keep things simple)

It’s important to notice the feat and fix types bump up the version of the project correlating to a MINOR and PATCH (accordingly) in semantic versioning.
The other types have no semantic versioning effect unless BREAKING CHANGE is specified

scope: (homepage):
Short description of a section of the codebase enclosed in parenthesis followed by a colon and a space

description: Add alternative footer to the homepage
Short description of the code changes

body: Implement the alternative version of the footer(…)
A longer description of the commit, providing additional context about the changes.
Must be placed one empty line after the description

BREAKING CHANGE: BREAKING CHANGE [1.X.X - Major]
Must be indicated at the very beginning of the footer or body section of a commit and consist of the uppercase text BREAKING CHANGE, followed by a colon and a space.
It bumps up the version of the project correlating to a MAJOR in semantic versioning

footer: Fixes issue #3
The footer should only contain additional issue references about the changes

What if I want to use custom names?

Since this convention relies heavily on well-established keywords to increment the semantic versions of our app, using our own personal convention and still get the use of Conventional Commits is not an option at the moment.

Dynamic Changelog

To dynamically update our changelog we’re going to be using a package called standard-version

First we install it:

-- CODE language-code line-numbers --
$ npm i --save-dev standard-version

Next we add a custom command in our package.json so it’s easier to use:

-- CODE language-code line-numbers --
"scripts": {<br>
   &nbsp;"release": "standard-version"<br>
}

Now we can use npm run release in place of npm version to update our app’s version and tags based on our CHANGELOG records

Extra tool (optional)

If you don’t feel like memorizing the convention, commitizen has got you covered! It’s a command line utility that prompts you to fill out the required fields for each commit - which is pretty neat 👌

Image for post

First we install commitizen globally.

-- CODE language-code line-numbers --
$ npm install -g commitizen

Then we install the necessary adapter:

-- CODE language-code line-numbers --
$ npm install -g cz-conventional-changelog

Now we create a .czrc file in our home directory

-- CODE language-code line-numbers --
nano ~/.czrc

And add a path property referring to the, globally installed, commitizen adapter:

-- CODE language-code line-numbers --
{ "path": "cz-conventional-changelog" }

We can now run git cz instead of git commit to be greeted by the prompt! 👏

Video demo

You check a video demo of the whole process working using the commitizen CLI below:

Alex Ferreira
Front-End Developer