Automatic versioning
The purpose of conventional commits is to be able to bump your project version and changelog automatically. Cocogitto allow you to do this with the cog bump
command.
The bump
subcommand will execute the following steps:
- Calculate the next version based on the commit types since the latest tag.
- Execute a set configuration defined pre-bump hooks.
- Append the changes for this version to
CHANGELOG.md
. - Create a version commit containing changes made during the previous steps.
- Create a git tag on the version commit.
- Execute a set of configuration defined post-bump hook.
Auto bump
cog bump
will calculate the next version based on your commit history since the latest semver tag. Once a tag number as been calculated it will create a tagged commit containing the changelog for this new tag.
Auto bump commit types
By default, only the following commit types will trigger the following auto bumps.
fix: a commit of the type fix patches a bug in your codebase (this correlates with PATCH in Semantic Versioning).
feat: a commit of the type feat introduces a new feature to the codebase (this correlates with MINOR in Semantic Versioning).
BREAKING CHANGE: a commit that has a footer BREAKING CHANGE:, or appends a ! after the type/scope, introduces a breaking API change (correlating with MAJOR in Semantic Versioning). A BREAKING CHANGE can be part of commits of any type.
If you want to change this or include other types you can update that in [commit_types] in cog.toml.
Example
Assuming we are working on the following git repository:
* 8e08b78 - (HEAD -> master) feat: another cool feature <Paul Delafosse>
* 490b846 - docs: add some documentation <Paul Delafosse>
* 8bc0d28 - fix: fix a ugly bug <Paul Delafosse>
* a0c9050 - feat: add awesome feature <Paul Delafosse>
* 6d014b4 - chore: initial commit <Paul Delafosse>
Let us now create a version:
❯ cog bump --auto
Warning: using 'cog bump' with the default configuration.
You may want to create a 'cog.toml' file in your project root to configure bumps.
Failed to get current version, falling back to 0.0.0
Skipping irrelevant commits:
- docs: 1
Found feature commit 8e08b7
Found bug fix commit 8bc0d2
Found feature commit a0c905
Bumped version: ... -> 0.1.0
If we look again at our git log:
* 76c0ffd - (HEAD -> master, tag: 0.1.0) chore(version): 0.1.0 (2 minutes ago) <Paul Delafosse>
...
Also, a CHANGELOG.md
file have been created using the default
template:
# Changelog
All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines.
---
## 0.1.0 - 2021-11-11
#### Bug Fixes
- fix a ugly bug - (8bc0d28) - Paul Delafosse
#### Documentation
- add some documentation - (490b846) - Paul Delafosse
#### Features
- another cool feature - (8e08b78) - Paul Delafosse
- add awesome feature - (a0c9050) - Paul Delafosse
---
Changelog generated by [cocogitto](https://github.com/cocogitto/cocogitto).
Also see template config if you need to change the default changelog template.
TIP
Sometimes getting a version number automatically is not what you want. Cocogitto let you specify the target version with the following flags:
--auto
: choose the next version for you (based on feature commit, bug fixes commit and BREAKING_CHANGE commit).--major
: increment the MAJOR version.--minor
: increment the MINOR version.--patch
: increment the PATCH version.--version <version>
: set version manually ( ex:cog bump --version 3.2.1
).--pre <metadata>
: set the pre-release metatada.--build <metadata>
: set the build metatada.
Example:
cog bump --major --pre "beta.1" --build "foo.bar"
# 1.2.3 -> 2.0.0-beta.1+foo.bar
Note: cog bump --auto
treats 0.y.z
versions specially, i.e. it will never do an auto bump to the 1.0.0
version, even if there are breaking changes. That way, you can keep adding features in the development stage and decide yourself, when your API is stable.
Dry run
If you just need to get the next version number without performing the automatic bump use the --dry-run
flag:
cog bump --dry-run --auto
TIP
The dry-run
flag can be helpful when writing shell scritps using cocogitto. Since only the version number will output to stdout so you can do the following:
VERSION=$(cog bump --dry-run --auto) # -> VERSION=1.0.0
Bump hooks
Pre bump hooks
Creating git tag automatically is great, but sometimes you need to edit some file with the new version number, or perform some additional checks before doing so.
A typical example is editing your project manifest in your package manager configuration file. You can run pre bump commands with the latest
and version
aliases to reference respectively the latest known version and the target version.
In case you are first setting out your project and you don't have a version yet, you can define a default value for the aliases. This can be simply done by adding a default value to the alias like: {{version|0.0.0}}
. The same can be done for any of the version aliases.
Example:
When adding the following hooks to cog.toml
, the hook commands will be run before creating the version commit:
# cog.toml
pre_bump_hooks = [
"cargo build --release",
"echo 'bumping from {{latest|0.0.0}} to {{version|0.0.1}}'",
"cargo bump {{version|0.0.1}}",
]
And result in the following bump:
❯ cog bump --auto
Skipping irrelevant commits:
Found feature commit 9055d9
Compiling my_awesome_repo v0.1.0 (/home/okno/_Workshop/MyRepos/my_awesome_repo)
Finished release [optimized] target(s) in 0.86s
bump from 0.1.0 to 0.2.0
Bumped version: 0.1.0 -> 0.2.0
TIP
If any of the pre-bump command fails cocogitto will abort the bump. Any changes made to the repository during the pre-bump phase will be stashed under cog_bump_{{version}}
.
Example:
cog.toml:
pre_bump_hooks = [
"cargo build --release",
"echo 'bump from {{latest}} to {{version}}'",
"exit 1" # Fail on purpose here
]
run:
❯ cog bump --auto
Skipping irrelevant commits:
Found bug fix commit a0de11
Compiling my_awesome_repo v0.2.0 (/home/okno/_Workshop/MyRepos/my_awesome_repo)
Finished release [optimized] target(s) in 0.22s
bump from 0.2.0 to 0.2.1
Error: prehook run `exit 1` failed
All changes made during hook runs have been stashed on `cog_bump_0.2.1`
you can run `git stash apply stash@0` to restore these changes.
Post bump hooks
Post-bump hooks works exactly like pre-bump hooks. They are run after the version has been created and are typically used to push changes to the remote, publish packages and apply branching model strategies.
# cog.toml
post_bump_hooks = [
"git push",
"git push origin {{version}}",
"cargo publish"
]
DANGER
There is no rollback procedure for post-bump hook, on failure cog will abort and leave the repository in an undefined state. We are working on allowing user to define their rollback procedures, but it is not there yet.
Version DSL
It is common to bump your development branch version package manifest after creating a new release. A typical example in the java world would be to bump your maven snapshot on your development branch after a release.
# cog.toml
post_bump_hooks = [
"git push",
"git push origin {{version|1.0.0}}",
"git checkout develop",
"git rebase master",
"mvn versions:set -DnewVersion={{version|1.0.0+minor-SNAPSHOT}}",
"cog commit chore \"bump snapshot to {{version|1.0.0+1minor-SNAPSHOT}}\"",
"git push",
]
As you can see we are bumping the manifest using a small DSL. It only has a few keywords:
- start with the one of
version
,version_tag
,latest
,latest_tag
orpackage
keyword. - followed by an optional default value (example above:
|1.0.0
) in SemVer format in case the value for the keyword is not available - the default cannot be used with the package keyword. - followed by the
+
operator. major
,minor
andpatch
to specify the kind of increment you want. Then an optional amount, default being one (version+1minor
andversion+minor
being the same).- followed by any number of
+{amount}{kind}
(exemple:version+2major+1patch
) - ended by any alphanumeric character (SemVer additional labels for pre-release and build metadata), here
-SNAPSHOT
.
Bump profiles
For some branching model or release cadence you might want to bump your versions with different hooks.
To do so you can define alternate profile hooks in cog.toml
:
[bump_profiles.hotfix]
pre_bump_hooks = [
# Ensure we are performing a bump from the latest release branch
"""
[[ "$(git rev-parse --abbrev-ref HEAD)" == "release/{{latest}}" ]] && echo "On branch release/{{latest}}" || exit 1
""",
]
post_bump_hooks = []
Once your custom hook profile is set you can call it with the --hook-profile
flag:
❯ cog bump -H hotfix --auto
Skipping irrelevant commits:
Found feature commit 5b21b3
Found bug fix commit a0de11
[[ $(git rev-parse --abbrev-ref HEAD) == release/0.2.0 ]] && echo On branch release/0.2.0 || exit 1
On branch release/0.2.0
Bumped version: 0.2.0 -> 0.3.0
Note that for the sake of readability in this documentation, the above example use a oneliner to check the current branch, but you would probably want to can a shell script instead:
pre_bump_hooks = [
"""
sh -c "./check_branch.sh"
""",
]
Branch whitelist
It is a common practice to bump always from the same set of branches. For instance, you might want to allow bumping only on branch main
and branches prefixed with release/
.
To do so add the following to your cog.toml
:
branch_whitelist = [
"main",
"release/**"
]