Skip to content

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:

  1. Calculate the next version based on the commit types since the latest tag.
  2. Execute a set configuration defined pre-bump hooks.
  3. Append the changes for this version to CHANGELOG.md.
  4. Create a version commit containing changes made during the previous steps.
  5. Create a git tag on the version commit.
  6. 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:

git
* 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:

bash
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:

git
* 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:

markdown
# 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:

bash
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:

shell
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:

shell
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:

toml
# 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:

bash
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:

toml
pre_bump_hooks = [
  "cargo build --release",
  "echo 'bump from {{latest}} to {{version}}'",
  "exit 1" # Fail on purpose here
]

run:

bash
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.

toml
# 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.

toml
# 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 or package 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 and patch to specify the kind of increment you want. Then an optional amount, default being one (version+1minor and version+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:

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:

bash
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:

toml
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:

toml
branch_whitelist = [
  "main",
  "release/**"
]