Integrate Commitizen in python projects — Git commits syntax check, bump version, and more.

Silvio Pavanetto
Jobtome Engineering
4 min readNov 15, 2022
Photo by Pedro Araújo on Unsplash

In this article I would like to talk about a very good tool to manage some elements of python (not only) projects to improve the productivity and the quality of your git repos.

Some context

I have been working in my current company — Jobtome — as a software engineer for about one year now (we are hiring by the way).
Recently, we decided to take a step forward in the process of choosing best practices and tools to use for better working in team.

In my team most of the projects are written in python.
In addition, there are usually multiple team members working on the same project and we extensively adopt a continuous integration (CI) approach.
Therefore, it is essential to adopt common standards and procedures (especially those related to git).

Old stack

Until recently we used to use a mix of different tools, such as bump2version and standard-version to bump the versions, update the Changelog and create tags.

The problem is that standard-version requires Node.js to be installed (and in a python project, it’s a little out of place 🫠).

Also, in this way, we did not have a common syntax to respect for writing commit messages and this is not good 👎🏻

For these reasons, we have decided to switch to Commitizen¹, among the various open source proposals, because with a single tool (installable directly in python with pip) we have all the features mentioned above + the syntax enforcing on commits.

How to integrate Commitizen in your repo

First of all, add it to your requirements-dev.txt together with the other fundamental pieces for having well formatted project files and install them:

Git commits syntax enforcing

After some trial and error, failing to set up the git hook automatically, I decided to switch to the good old manual way ✍️.

So I put the content of the desired .git/hooks/commit-msg file inside the Makefile in a variable like this:

Then you can use a very easy Makefile command like this setup-dev-env that does the following:

The final result will be a commit-msg file written in .git/hooks that looks like this:

Another important requirement for Commitizen to work properly is to add the following content to your .pre-commit-config.yaml

You can check that everything is working fine by trying to do a commit with a message that is not using the conventional commits² syntax, like git commit -m “test commit msg” and you will receive a shell output that will look like this:

Bump versions

Another useful feature is to automatically bump versions among different files of the project.

Every detail about this feature is explained in the official Commitizen documentation, but I just want to highlight that is super simple to configure every option of the bump with the pyproject.toml configuration file.

Here is an example of how I configured Commitizen in one of my projects:

Once this is configured, you can simply use cz bump for updating all the files mentioned in version_files config variable above, making a commit with message = bump_message.

Also, with update_changelog_on_bump = true you will find that the Changelog has been automatically updated with all commits since the latest version.

An example of Changelog:

In addition, you can use bump and specify different types of increment or version numbers.

When should I use major, minor, or patch?

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

MAJOR version when you make incompatible API changes
MINOR version when you add functionality in a backwards-compatible manner
PATCH version when you make backward-compatible bug fixes

Source: Semantic Versioning 2.0.0

Tag

Only one last step related to the repo tags is missing, but once you have configured the bump part, you’re almost done.

In our case, I configured another Makefile command that has to be used after the cz bump, to push the new versions and create a new tag:

If everything is configured correctly, the git push will produce 2 different CI/CD pipelines: 1 for the commit itself and the other (with more steps, e.g. the push of the new image to the registry) for the new tag.

Gitlab example of 2 CI pipelines triggered by new tag

References

--

--

Silvio Pavanetto
Jobtome Engineering

Software engineer in love with good code, basketball and problem solving. https://silviopavanetto.com