5 min read

Auto Versioning Any Project Using Commitizen & Conventional Commits

Auto Versioning Any Project Using Commitizen & Conventional Commits

General Overview

One thing I come across a lot in my different roles has been versioning, and its always something that can be a pain. Sometimes you have to update multiple files with the version when it changes, docs, etc.

Today we are going to talk about using Conventional Commits along with Commitizen to auto version and create a automated changelog for us.

Conventional Commits is a specification around your commit messages. You can read more about how conventional commits work at the previous mentioned link. The general idea though is based on if you do a feat or fix type of commit it will control how the version is incremented.

Commitizen is a tool we can use to create conventional commits easier as well as auto bump versions and changelog based on the commits. Ensure you have installed Commitizen using one of their methods before continuing.

Auto Versioning Setup

The below steps outline how to get auto versioning setup and working.

Setup GitHub Repo

The first thing you want to do is setup a new GitHub/GitLab/Etc repo to test this in, we need it to be a git repo for the auto versioning to work and tag correctly. It uses the tags from git to know how to auto increment based on the commit history.

After cloning your initial repo, (I'd recommend just setting it with a README.md) we can get started.

Install Commitizen

As mentioned before ensure Commitizen has been installed.

Commitizen Init & Bump

Now we can initialize our repo with commitizen using:

cz init

This will ask us a few questions we have to answer as you can see in the gif below. You can use pyproject.toml if you are using python or existing poetry project, and if you don't like toml format you can select a different format.

The beauty of this though is you can literally use this with any type of project.

cz_init

Next we have to do the git tag 0.0.1 to create the initial 0.0.1 version.

git_tag

Generate Changelog

Now we can run the cz changelog command to generate a new changelog file. Then we can add this to version control via git add . to add our new .cz.toml file and our CHANGELOG.md file.

We also can now run cz c to generate the menu for us to create a commit and we can select this as a fix to show how it will auto update the version from 0.0.1 to 0.0.2.

cz_change_git_add

Commitizen Bump & Push

Now we can do a version bump since we have a new commit, in order to do that and generate the changelog we can do:

cz bump --changelog

This will bump the version if the commits call for it and also update the CHANGELOG.md accordingly.

We can then just do a git push origin XXX where XXX is your branch and push our updates, since it did the version bump for us it will generate the commit and add files.

We also need to do git push --tags to push our tags we created.

cz_bump_push

Updating Versions In Other Files

You are probably saying, ok this is cool and all and can update this one .cz.toml file and create a CHANGELOG.md file, but what if I want my versions updated in other things?

Well that is easy enough with commitizen as well, if you check out their section in the Docs there are options for telling commitizen how to udpate files.

So lets create a my_version.txt file:

echo "version=0.0.2" > my_version.txt

Now we should have a file called my_version.txt with text in it that says version=0.0.2.

So now on a new bump we want commitizen to also update this version number in this file, so the way we can do that is adding the following to our existing .cz.toml file:

[tool.commitizen]
version_files = [
    ".cz.toml",
    "my_version.txt:version"
]

So the total file should look like:

[tool]
[tool.commitizen]
name = "cz_conventional_commits"
version = "0.0.2"
tag_format = "$version"

version_files = [
    ".cz.toml",
    "my_version.txt:version"
]

What we are doing here is telling it to obviously keep the .cz.toml file updated, along with the version var inside of the my_version.txt file.

To test this we can add this file and do a cz bump to watch it update everything:

git add . to add our updated cz.toml file and our my_version.txt file.

Now lets do a cz c and select feat this time for a different version bump.

Finally lets do a cz bump --changelog to bump the version and update the changelog.

bump: version 0.0.2 → 0.1.0
tag to create: 0.1.0
increment detected: MINOR

[main 3ed7d21] bump: version 0.0.2 → 0.1.0
 3 files changed, 8 insertions(+), 2 deletions(-)

Done!

Now if you cat the .cz.toml file you will see it has updated:

[tool]
[tool.commitizen]
name = "cz_conventional_commits"
version = "0.1.0"
tag_format = "$version"

version_files = [
    ".cz.toml",
    "my_version.txt:version"
]

And our version var in our my_version.txt has also updated:

version=0.1.0

What happened here was since we selected a feat commit it updated the MINOR version location so that is why we went from 0.0.2 to 0.1.0.

bump: version 0.0.2 → 0.1.0
tag to create: 0.1.0
increment detected: MINOR

[main 3ed7d21] bump: version 0.0.2 → 0.1.0
 3 files changed, 8 insertions(+), 2 deletions(-)

Done!

Here is an example of everything together on the cli:
cz_bump_txt_file-1

Final Thoughts & CI Options

So now utilizing the cz bump command and Conventional Commits, you can now setup CI to do this process for you.

Typical process would be to validate commit message on PR is a valid conventional commit message, then on merges into your main branch you can generate the cz bump --changelog command and update if there is a new version then push this back to the repo.

Hopefully this small tutorial helped and you can look at Chatbot Auto Version Example by looking at the .github/workflows dir. You can see in the build-train-pr.yml how we validate the commit message.

In the bump_version.yml you can see how the version is bumped and is then used to version our artifact model file.

So the final steps as you use this and update code are basically to update your files, perform a cz c to commit the files and commit message, then run cz bump --changelog to generate the changelog and versions. Then simply push your code up along with tags by doing git push origin HEAD and git push --tags.