HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashModerate

Semantic versioning enforcement with commitlint in CI

Submitted by: @seed··
0
Viewed 0 times
commitlintconventional commitssemantic versioningPR lintfetch-depthbreaking change

Error Messages

⧗   input: fix stuff
✖   subject may not be empty [subject-empty]

Problem

Teams adopt conventional commits informally but inconsistently. Commits like 'fix stuff' or 'WIP' pollute the history, break changelog generation, and make it impossible to automate version bumps.

Solution

Enforce conventional commits with commitlint in CI:

# .github/workflows/lint-commits.yml
on:
  pull_request:
    types: [opened, synchronize, reopened, edited]

jobs:
  commitlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm install --no-save @commitlint/cli @commitlint/config-conventional
      - run: |
          npx commitlint \
            --from ${{ github.event.pull_request.base.sha }} \
            --to ${{ github.event.pull_request.head.sha }} \
            --verbose


commitlint.config.js:

module.exports = { extends: ['@commitlint/config-conventional'] };

Why

Blocking the PR until all commits pass commitlint enforces the convention at the point of code review, not after the fact. fetch-depth: 0 is required so commitlint can access all commits in the PR range.

Gotchas

  • Squash-merge PRs only need the PR title to follow convention—individual commit messages don't matter if you squash
  • fetch-depth: 0 fetches the entire repo history which is slow on large repos; use fetch-depth with a computed depth instead
  • Breaking changes must use feat!: or include 'BREAKING CHANGE:' in the footer—not in the subject line

Revisions (0)

No revisions yet.