Skip to content

With release tools

release-please, semantic-release, git-cliff and cz bump read your commit messages to decide the next version and write the changelog. A commit they cannot parse is not an error to them: it is left out of the changelog, or it does not count toward a release. Commit Check is the gate in front of them, so what they read always parses.

Check the message the tool will read

Which message that is depends on how pull requests are merged.

  • Merge commits or rebase. Every commit on the branch lands on main, and the release tool reads each one. Check each one: the pre-commit hook while it is written, and the Action with its default message: true on the pull request.
  • Squash merge. The branch's commits are thrown away, and the pull request title becomes the commit on main. release-please, for one, "highly recommend[s]" squash merges. Check the title: pr-title: true on the Action, or check = "squash" on the App, which checks the full message a squash merge would land. With GitHub's default squash message, a pull request of a single commit lands that commit's message rather than the title. The App follows that setting; with the Action, set the squash commit message to "Pull request title" in the repository settings so the title you check is the one that lands.
.github/workflows/commit-check.yml
name: Commit Check

on:
  pull_request:
    types: [opened, edited, synchronize, reopened]

jobs:
  commit-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: commit-check/commit-check-action@v2
        with:
          message: false  # the branch's commits do not reach main
          pr-title: true

The default commit types are the Conventional Commits ones the tools release on (feat, fix, perf) plus the ones they parse but do not release on, such as docs and chore; whether those show in the changelog is the tool's setting. A breaking change written as feat!: or feat(api)!: passes Commit Check, and so does a BREAKING CHANGE: footer. semantic-release's default Angular preset does not read the !, though: give the commit a BREAKING CHANGE: footer, or switch it to the conventionalcommits preset.

Let the tool's own pull request through

release-please and changesets open their release pull request from a branch whose name you cannot choose:

Tool Branch Default title
release-please release-please--branches--main, plus --components--<name> in a monorepo chore(main): release 1.2.3
changesets/action changeset-release/main Version Packages

The default branch rule, CC201, rejects both names. Allow the ones you use:

cchk.toml
[branch]
allow_branch_names = ["release-please--branches--.+", "changeset-release/.+"]

Each entry is a regular expression that has to match the whole branch name, so these allow the tools' branches and nothing that merely contains them.

release-please's title passes CC001 as it is. changesets' Version Packages does not, so with pr-title: true give it a Conventional Commits title and commit message:

- uses: changesets/action@v1
  with:
    commit: "chore: version packages"
    title: "chore: version packages"

Per tool

Tool What it reads Notes
release-please Conventional Commits on the release branch since the last release Branch name above. Its README recommends squash merges, so check the title.
semantic-release Commits since the last release, with the Angular preset by default The Angular types are Commit Check's defaults.
git-cliff Commits, parsed as Conventional Commits when conventional_commits = true in cliff.toml With filter_unconventional = true, a commit that does not parse is dropped from the changelog without a word.
Commitizen cz bump Conventional Commits since the last tag Commitizen has its own cz check. Commit Check adds branch names, authors, sign-off and the App, from one config.
changesets Changeset files, not commit messages Only its branch name and PR title matter here, both above.