Git conventional commits
--
Here’s a description of conventional commits by Google’s Bard, in the style of a Slipknot song:
[Verse 1]
I'm a conventional committer,
I commit my code with rage.
I follow the rules,
I always do my part.
[Chorus]
Conventional commits,
They're the way to go.
They make your code easier to read,
And they make your life a lot less pain.
[Verse 2]
So if you're a software developer,
And you want to make your life easier,
Then start using conventional commits.
You won't regret it, I swear.
[Chorus]
Conventional commits,
They're the way to go.
They make your code easier to read,
And they make your life a lot less pain.
[Bridge]
Conventional commits are the way of the future.
They're the way to keep your code organized and your sanity intact.
So what are you waiting for?
Start using them today!
[Chorus]
Conventional commits,
They're the way to go.
They make your code easier to read,
And they make your life a lot less pain.
[Outro]
Conventional commits,
They're the way to be.
So use them, and you'll see,
Your life will be a lot more free.
As I am sure you gathered from that, conventional commits are great. They are an agreed standard for the format of commit messages.
This is helpful on large projects with multiple developers interracting, to quickly understand what is happening in a commit before they dive into the code.
Standardising format also leads the way to automation in CI/CD pipelines, as we can always guarantee that descriptors for the commit message will be in the same place, which is what we will be focusing on here.
Commit message formats
The agreed standard documents well the differing types. Though there are some agreed use cases (Eg feat/fix/docs/ci), as long as the standard is maintained across your organisation you can be more creative here!
Gpush
gpush is a small tool I wrote, installable via pip, to standardising commit messages using conventional commits.
Gpush should be used in replacement of
git commit -m “commit message” && git push
And you can simply run gpush after adding your files to be commited:
gpush
gpush will ask for some details to summise your commit, what type of commit, whether or not a breaking change was introduced and finally your commit message.
These values are used to generate a commit message in conventional commit format. Eg the above commit message would be translated to:
feat!: Example commit message
The !
indicates that a breaking change was introduced, which should trigger any automation to bump the major semantic version for the package.
Semantic-release
semantic-release can be used in combination with conventional commits to programatically deploy releases of your application (language agnostic!).
The gpush project mentioned above, uses a fork of semantic-release which is focused on python (python-semantic-release) in the below GitHub action to read conventional commit messages from a pull request, and bump and deploy a new release (including publishing onto pypi).
.github/workflows/semver-deploy.yaml
name: "Semver Bump"
on:
push:
branches:
- "main"
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
auto-semver:
runs-on: "ubuntu-latest"
steps:
- name: "Checkout code"
uses: "actions/checkout@v3"
with:
fetch-depth: 0
- name: "Python Semantic Release"
uses: "python-semantic-release/python-semantic-release@master"
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
repository_username: __token__
repository_password: ${{ secrets.PYPI_TOKEN }}
Breaking the above down, the action will run on a merge into main
branch (or when triggered manually via workflow_dispatch). This is useful in the event of having to retrigger the pipeline if there are authentication issues with your token on pypi or similar.
The python-semantic-release stage uses a number of inputs:
github_token: For authentication to publish the release on GitHub.
repository_username: pypi username (If you are using an api token this should simply be __token__
repository_password: In order to ensure least privilidge and limit blast radius, this token should be scoped on pypi to allow only writes to your project. The API token should be stored as a repository secret in GitHub and not hard-coded into your workflow
_version.py
This file is read by pyproject.toml to be updated by python-semantic-release when your package version is bumped and before deployment in GitHub and Pypi.
"""File to containing the version of the package."""
__version__ = "3.1.2"
pyproject.toml
All that is required then for python-semantic-release to deploy your projet is to create a pyproject.toml file as below to give semantic-release context for your project.
[tool.semantic_release]
version_variable = "_version.py:__version__"
branch = "main"
description = "A short description for your project"
readme = "README.md"
name = "project_name"
keywords = ["some", "example", "tags"]