Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 

Repository files navigation

commitlint-action

GitHub Action wrapping DivergentCodes/commitlint: Conventional Commits linting for PR titles and commit messages with no third-party actions — the only nested uses: is GitHub's own actions/setup-go, and the linter is a zero-dependency Go binary installed from source.

Usage

Pin to a full commit SHA (with a version comment) — the strongest supply-chain posture, since a moved or compromised tag can't silently swap the action:

name: pr-lint
on:
  pull_request:
    types: [opened, edited, synchronize, reopened]
permissions:
  contents: read
jobs:
  commitlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@<full-sha>  # required for commits-mode
      - uses: DivergentCodes/commitlint-action@<full-sha>  # v1.0.1
        with:
          pr-title-mode: block   # squash-merge title is load-bearing
          commits-mode: warn     # advisory; intermediate commits vanish at squash

actions/checkout is required whenever commits-mode is not off, because the action reads the PR's commits from git. With commits-mode: off the title comes from the event payload and no checkout is needed.

Tag pinning (@v1) also works and is fine for internal repos, but SHA pinning is recommended for anything security-sensitive.

The edited trigger matters: it re-runs the check when a PR title is fixed, so a failed title clears without pushing a commit.

Why these defaults

When PRs are squash-merged, the PR title becomes the commit message on main — so the title is load-bearing (it drives semantic-release versioning) and is linted in block mode. The individual commits inside the PR are discarded at squash, so they're linted in warn mode: contributors get feedback without being blocked on work-in-progress commit messages. If you merge with rebase or merge commits instead, set commits-mode: block.

Inputs

Input Default Meaning
version latest commitlint version to go install; pin a tag (e.g. v1.1.2) in production
pr-title-mode block block fails the check, warn reports only, off skips
commits-mode warn same modes, applied to each PR commit
types conventional set comma-separated allowed types
scopes any comma-separated allowed scopes
require-scope false require a (scope)
max-subject-length 72 subject length limit
github-token github.token fetches the commitlint module while its repo is private; unused once public

Permissions

permissions: contents: read is sufficient — enough for actions/checkout to fetch the commits. The action makes no API calls and never writes anything. With commits-mode: off it reads only the event payload.

The linter is installed with a plain go install, which resolves through the Go module proxy with checksum-database verification. No token is involved.

If that fetch fails — which it will if the linter is being pulled from a private fork or mirror — the action retries with github-token, rewriting only github.com/DivergentCodes/ URLs so the token is never offered to another host or org. That retry sets GOPRIVATE, which bypasses the proxy and checksum database; it is scoped to the fallback precisely so the ordinary path keeps its verification.

Using this in another repository

Both this action and DivergentCodes/commitlint are public, so no token or extra configuration is needed — paste the workflow from Usage and it works.

The github-token input remains for the case where the linter is fetched from a private fork or mirror; it is unused otherwise.

Runner requirements

Runs on ubuntu-latest (and other GitHub-hosted runners) out of the box: it uses actions/setup-go to install the linter and reads commits with git. On self-hosted runners, ensure Go and git are available.

Troubleshooting

  • "subject must be type(scope)?: description" on a PR title → edit the title to a conventional form (e.g. feat: ..., fix(api): ...); the edited trigger re-runs the check automatically.
  • PR commits failing unexpectedly → they're linted in warn mode by default (non-blocking). If they block, commits-mode is set to block.
  • Type rejected → it's not in the allowed set; pass types: to extend it.

Releases

Releases are automatic on merge to main, with autogenerated changelogs in the release notes (no committed changelog file). The version comes from the merged commit's conventional type:

Merged commit Bump Example
feat!: / BREAKING CHANGE major v1.2.3v2.0.0
feat: minor v1.2.3v1.3.0
fix: / perf: patch v1.2.3v1.2.4
docs: / ci: / chore: none no release

The major-version alias (v1) moves to each new release automatically, so @v1 always resolves to the newest compatible version. Pushing a v* tag by hand still works for re-cuts.

Reference a release by SHA (preferred) or tag.

License

MIT

About

A GitHub Action that runs commitlint for conventional commit linting

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors