Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/compare/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ for the current state. GitHub's own rulesets are on
| [commitcheck](https://github.com/marketplace/commitcheck) | A hosted App that applies one regular expression, set in its web admin | Commit message, pull request title or description, by regex | GitHub App | Free for public repositories; $25 a month for private ones |
| [DCO app](https://github.com/apps/dco) and [DCO-2](https://github.com/cncf/dco2) | The sign-off check the Linux kernel and the CNCF use, with a remediation flow for missing sign-offs | `Signed-off-by` trailers | GitHub App | Free, open source |
| [PRLint](https://github.com/ewolfe/prlint), [PR Title Checker](https://github.com/marketplace/actions/pr-title-checker) | Regular expressions over pull request fields | Title, body, labels, branch | App / Action | Free, open source |
| **Commit Check** | One rule engine, [documented rule by rule](../rules.md), run as a hook, a CLI, an Action, a hosted App or an MCP tool | Commit message, branch name, author name and email, sign-off, AI attribution, force pushes, file size and paths, tag names; the squash message of a pull request | All of the above | Free, open source; the App's private organization repositories move to a paid plan later |
| **Commit Check** | One rule engine, [documented rule by rule](../rules.md), run as a hook, a CLI, an Action, a hosted App or an MCP tool | Commit message, branch name, author name and email, sign-off, AI attribution, force pushes, file size and paths, tag names; the pull request title (Action) and the squash message of a pull request (App) | All of the above | Free, open source; the App's private organization repositories move to a paid plan later |

## What is different about Commit Check

Expand Down
23 changes: 14 additions & 9 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ flag overrides both for a single run.
| `--message` | Conventional Commits ([CC001](rules.md#cc001)), subject lengths of 5–80 characters ([CC004](rules.md#cc004), [CC005](rules.md#cc005)), and an allow-list of ten commit types |
| `--branch` | Conventional Branch ([CC201](rules.md#cc201)) and an allow-list of twenty-one branch types |
| `--author-name` / `--author-email` | The built-in name and email patterns ([CC101](rules.md#cc101), [CC102](rules.md#cc102)) |
| `--tag` | SemVer tag names, with an optional leading `v` ([CC401](rules.md#cc401)) |

Off until you turn them on: subject capitalization, imperative mood,
required body and signoff, and rebase requirements.
Expand Down Expand Up @@ -89,8 +90,9 @@ It is a warning, not an error: the exit code and the JSON on stdout do not
change. The top-level `warn` list and the GitHub App's
[`[jira]`](guides/github-app.md#jira-ticket-references) and
[`[pull_request]`](#pull-requests-every-commit-or-the-squash-message) sections
are read elsewhere and are not reported. The Python API and the MCP server
load the file themselves and do not report it either.
are read elsewhere and are not reported. The Python API reads no file at all
(it takes a `config` dict), and the MCP server loads the file itself without
reporting unknown settings.

## Inheriting a shared config

Expand All @@ -115,12 +117,15 @@ The value can be a GitHub shorthand, a local path or an HTTPS URL:
| Local file | `../../shared/org-cchk.toml` |
| HTTPS URL | `https://example.com/shared/cchk.toml` |

!!! note "Inheritance fails quietly"
!!! note "Inheritance fails open"

If the target is unreachable or the format is not recognized, Commit Check
ignores the inheritance and uses the local configuration alone. Plain HTTP
URLs are rejected outright. A repository that silently stops inheriting
still passes its own checks, so pin the branch when the policy matters.
ignores the inheritance and uses the local configuration alone, printing a
one-line `⊘ inherit_from ... could not be loaded` notice on stderr; the exit
code does not change. Plain HTTP URLs are rejected the same way. Only one
level is followed: an `inherit_from` inside the parent is ignored, with a
notice. A repository that stops inheriting still passes its own checks, so
pin the branch when the policy matters.

## Pull requests: every commit, or the squash message

Expand Down Expand Up @@ -269,7 +274,7 @@ Used from a hook definition, with no config file anywhere in the repository:
```yaml title=".pre-commit-config.yaml"
repos:
- repo: https://github.com/commit-check/commit-check
rev: v2.19.1
rev: v2.19.2
hooks:
- id: check-message
args:
Expand Down Expand Up @@ -309,8 +314,8 @@ The full mapping between the three forms:
| `require_body = false` | `CCHK_REQUIRE_BODY=false` | `--require-body=false` |
| `require_signed_off_by = false` | `CCHK_REQUIRE_SIGNED_OFF_BY=false` | `--require-signed-off-by=false` |
| `ignore_authors = ["bot"]` | `CCHK_IGNORE_AUTHORS=bot,user` | `--ignore-authors=bot,user` |
| `author_email_pattern=^.+@example\.com$` | `CCHK_AUTHOR_EMAIL_PATTERN=^.+@example\.com$` | `--author-email-pattern=^.+@example\.com$` |
| `author_name_pattern=^.+ .+$` | `CCHK_AUTHOR_NAME_PATTERN=^.+ .+$` | `--author-name-pattern=^.+ .+$` |
| `author_email_pattern = '^.+@example\.com$'` | `CCHK_AUTHOR_EMAIL_PATTERN=^.+@example\.com$` | `--author-email-pattern=^.+@example\.com$` |
| `author_name_pattern = '^.+ .+$'` | `CCHK_AUTHOR_NAME_PATTERN=^.+ .+$` | `--author-name-pattern=^.+ .+$` |
| `conventional_branch = true` | `CCHK_CONVENTIONAL_BRANCH=true` | `--conventional-branch=true` |
| `allow_branch_types = ["feature"]` | `CCHK_ALLOW_BRANCH_TYPES=feature,bugfix` | `--allow-branch-types=feature,bugfix` |
| `allow_branch_names = ["staging", "production"]` | `CCHK_ALLOW_BRANCH_NAMES=staging,production` | `--allow-branch-names=staging,production` |
Expand Down
15 changes: 9 additions & 6 deletions docs/example.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ revision.

=== "From the repository"

Validates `HEAD`'s message. This is what the `commit-msg` hook runs.
Validates `HEAD`'s message.

```console
$ commit-check -m
```

=== "From a file"

This is what the `check-message` pre-commit hook runs, with the message
file git hands it.

```console
$ commit-check -m commit_message.txt
```
Expand Down Expand Up @@ -54,7 +57,7 @@ revision.
```console
$ echo "updated the parser" | commit-check -m
CC001 message check failed ==> updated the parser
The commit message should follow Conventional Commits.
The commit message should follow Conventional Commits. See https://www.conventionalcommits.org
Suggest: Use <type>(<scope>): <description>, where <type> is one of: feat, fix, ...
Docs: https://commit-check.com/rules/#cc001
```
Expand Down Expand Up @@ -109,8 +112,8 @@ $ commit-check --branch
```

Runs [CC201](rules.md#cc201), and [CC202](rules.md#cc202) if
`require_rebase_target` is set. `master`, `main`, `HEAD` and `PR-*` are always
accepted; everything else needs a `<type>/<description>` shape:
`require_rebase_target` is set. `main`, `master`, `develop`, `HEAD` and `PR-*` are
always accepted; everything else needs a `<type>/<description>` shape:

```text
fix/empty-config-crash
Expand Down Expand Up @@ -159,7 +162,7 @@ pushed:
```yaml title=".pre-commit-config.yaml"
repos:
- repo: https://github.com/commit-check/commit-check
rev: v2.19.1
rev: v2.19.2
hooks:
- id: check-no-force-push
stages: [pre-push]
Expand Down Expand Up @@ -198,7 +201,7 @@ and how CLI, environment and file settings override each other.

```console
$ commit-check -m --compact
[FAIL] CC003 subject_imperative: docs: revamped the profile
[FAIL] CC003 subject-imperative: docs: revamped the profile
```

=== "No banner"
Expand Down
4 changes: 2 additions & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Four things are happening in that output, and each is deliberate:
## 3. Fix it

```console
$ git commit --amend -m "fix(parser): handle empty input"
$ git commit --amend --allow-empty -m "fix(parser): handle empty input"
$ commit-check --message
```

Expand All @@ -93,7 +93,7 @@ $ commit-check --branch
```text
CC201 branch check failed ==> my-changes
The branch should follow Conventional Branch. See https://conventionalbranch.org
Suggest: Use <type>/<description> with allowed types
Suggest: Use <type>/<description> with an allowed type, or add the branch to allow_branch_names in config
Docs: https://commit-check.com/rules/#cc201
```

Expand Down
40 changes: 32 additions & 8 deletions docs/guides/github-actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,36 @@ jobs:
author-email: true
```

1. Commit Check needs the full history to inspect every commit in the pull
request. Without this it only sees the most recent one.
1. Recommended, not required: the Action then reads the pull request's
commits from the clone. With a shallow clone it lists them through the
GitHub API instead (up to 250), and if it cannot, it warns and checks the
head commit alone.

The Action reads the same `cchk.toml` as the CLI, so a repository that already
has one needs no Action-specific configuration.

## Inputs

| Input | Default | What it does |
|---|---|---|
| `message` | `true` | Check every commit message of the pull request |
| `branch` | `true` | Check the branch name |
| `author-name` | `false` | Check each commit's author name |
| `author-email` | `false` | Check each commit's author email |
| `pr-title` | `false` | Check the pull request title against Conventional Commits, the one that matters for squash merges. Pull request events only |
| `pr-comments` | `false` | Post the report as a pull request comment, edited in place on later runs |
| `job-summary` | `true` | Write the report to the job summary |
| `dry-run` | `false` | Report failures as warnings and always exit `0` |

`pull_request` does not fire when a title is edited. With `pr-title: true`,
add `types: [opened, synchronize, reopened, edited]` to re-check a renamed pull
request.

The Action also sets a `result` output: the check results as JSON, read with
`fromJSON(steps.<id>.outputs.result)`. Its `status` is `pass`, `warn`, `skip`
or `fail`, and each scope carries the same per-check fields as
`commit-check --format json`.

## Making it a required check { #making-it-a-required-check }

Until it is required, a failing Commit Check does not stop anyone from
Expand All @@ -55,11 +79,10 @@ needs fixing directly on the PR:
message: true
branch: true
pr-comments: ${{ github.event_name == 'pull_request' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

This needs extra permissions on the job:
The Action posts with the workflow's own token, so no `GITHUB_TOKEN` needs to
be passed in. It does need extra permissions on the job:

```yaml
permissions:
Expand All @@ -85,9 +108,10 @@ Turn it off once the history is clean.

A `pull_request` workflow triggered by a fork receives a **read-only**
`GITHUB_TOKEN`, and `permissions: pull-requests: write` does not override that.
`pr-comments` will therefore fail to post on fork pull requests unless the
repository has *Send write tokens to workflows from pull requests* enabled under
**Settings → Actions → General**.
On such a run the Action skips the comment with a warning and says so in the
job summary; the check, the annotations and the summary still work. For
feedback on fork pull requests themselves, use the [GitHub App](github-app.md),
which is not bound by the workflow's token.

!!! warning "Do not reach for `pull_request_target` casually"

Expand Down
18 changes: 11 additions & 7 deletions docs/guides/github-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ with the defaults, advisory only (see [Without a config file](#without-a-config-
## What you get

On every push to a branch and on every pull request, each commit gets a check
run named **Commit Check** on the Checks tab, in the commit's status and in the
run named **Commit Check** (a push of more than 50 commits has its newest 50
checked, and the older ones get one neutral "not checked" result) on the Checks tab, in the commit's status and in the
merge box. (Tag pushes and branch deletions carry nothing to check; commits by
bots are skipped, and squash mode checks a pull request as one message — both
[below](#bots-re-runs-and-commits-checked-twice).) The result reads the same
way everywhere:

- a one-line verdict — `All 4 checks passed`, or `2 of 4 checks failed`;
- a one-line verdict — `All 4 checks passed`, or `Commit message and branch failed (2 of 4 checks)`;
- for a failure, a table of what failed, the value that failed and the rule
ID, linked to the [rule reference](../rules.md);
- **How to fix**: the rule's own explanation and suggestion;
Expand Down Expand Up @@ -94,8 +95,9 @@ push or pull request, in the same four places: `cchk.toml`, `commit-check.toml`,
`.github/commit-check.toml`. Every option on the
[configuration page](../configuration.md) that belongs to a rule the App runs
applies, precedence included; the `[push]`, `[files]` and `[tag]` sections are
read but have nothing to act on here. Nothing is App-specific to set, apart
from the two sections below.
read but have nothing to act on here. Nothing is App-specific to set apart
from `[pull_request]` (above) and `[jira]` (below); the CLI and the Action ignore
them.

[`inherit_from`](organization.md) works, and a `github:` target is fetched with
the App's own credentials, so a shared config in a private `.github` repository
Expand All @@ -113,7 +115,7 @@ rules.

A repository with no config file **and** no shared one has not chosen its
rules, so its result is **advisory**: failures are reported in full, but the check is neutral — titled,
say, `2 of 4 checks would fail (not enforced)` — and never blocks a merge. Below the
say, `Commit message and branch would fail (2 of 4 checks, not enforced)` — and never blocks a merge. Below the
fixes the report says why, and gives the smallest file that turns enforcement
on:

Expand Down Expand Up @@ -205,8 +207,10 @@ reports the same rule IDs — it just costs you CI minutes instead.

## Privacy

The App fetches the commits under test and the configuration file, nothing
else, and stores nothing: no database, no copy of any message, author or
The App fetches the commits under test, the configuration file (the
repository's own or its account's shared one) and the repository metadata the
checks need, such as the squash-merge settings and the comparison with a rebase
target, and stores nothing: no database, no copy of any message, author or
config. The [privacy page](../privacy.md) lists the permissions it asks for and
what each one is used for.

Expand Down
6 changes: 3 additions & 3 deletions docs/guides/organization.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ allow_branch_types = ["feature", "bugfix", "hotfix", "release", "chore"]
Where the [GitHub App](github-app.md) is installed on the organization, that
file is already in force: a repository with no `cchk.toml` of its own is
checked against the organization's, including repositories created tomorrow,
and the check run's last line says so. The App reads the file with its own
and the check run's report says so in its last lines. The App reads the file with its own
credentials, so the `.github` repository can be private. A personal account's
`.github` repository does the same for that account's repositories. A repository that
commits its own config uses that instead — to build on the shared one rather
Expand Down Expand Up @@ -102,8 +102,8 @@ stderr and ignored.
!!! warning "Inheritance fails open"

If the parent config is unreachable — a network blip, a renamed file, a
private repository — Commit Check silently falls back to the local config
rather than failing the build. This keeps CI green during an outage, but it
private repository — Commit Check falls back to the local config, with a
one-line notice on stderr, rather than failing the build. This keeps CI green during an outage, but it
also means a typo in `inherit_from` is easy to miss. Verify the merged
result when you first set it up:

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/policies.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ $ git rebase --signoff main

The DCO is a statement about who wrote the code, so it only means something if
the identity is real. [CC101](../rules.md#cc101) and
[CC102](../rules.md#cc102) check the committer name and email, and are enabled
[CC102](../rules.md#cc102) check the author name and email, and are enabled
by default when their check runs:

```console
Expand Down
6 changes: 3 additions & 3 deletions docs/guides/pre-commit.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Add Commit Check to `.pre-commit-config.yaml`:
```yaml title=".pre-commit-config.yaml"
repos:
- repo: https://github.com/commit-check/commit-check
rev: v2.19.1
rev: v2.19.2
hooks:
- id: check-message
- id: check-branch
Expand Down Expand Up @@ -68,7 +68,7 @@ Options can be passed as hook arguments, which keeps everything in one file:
```yaml title=".pre-commit-config.yaml"
repos:
- repo: https://github.com/commit-check/commit-check
rev: v2.19.1
rev: v2.19.2
hooks:
- id: check-message
args:
Expand All @@ -90,7 +90,7 @@ colon, and lets the commit through:
```yaml title=".pre-commit-config.yaml"
repos:
- repo: https://github.com/commit-check/commit-check
rev: v2.19.1
rev: v2.19.2
hooks:
- id: check-message
args: [--fix]
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -409,12 +409,12 @@ conventional_branch = <span class="cc-t-pass">true</span></div>
<li><span><b>A fix you can paste</b>, whenever the correction is unambiguous.</span></li>
</ol>
</div>
<!-- Real output of commit-check 2.18.0; the ASCII-art banner it prints first is left out. -->
<!-- Real output of commit-check 2.19.2; the ASCII-art banner it prints first is left out. -->
<div class="cc-diag">
<p class="cc-t-dim">$ echo "Fix: add streaming support" | commit-check -m</p>
<p><span class="cc-mark">1</span><span><span class="cc-t-fail cc-b">CC001</span> message check failed ==&gt;</span></p>
<p><span class="cc-mark">2</span><span class="cc-t-white">Fix: add streaming support</span></p>
<p><span class="cc-mark">3</span><span class="cc-t-dim">The commit message should follow Conventional Commits.</span></p>
<p><span class="cc-mark">3</span><span class="cc-t-dim">The commit message should follow Conventional Commits. See https://www.conventionalcommits.org</span></p>
<p><span class="cc-mark">4</span><span><span class="cc-t-blue">Suggest:</span> Use "<span class="cc-t-pass cc-b">fix: add streaming support</span>"</span></p>
<p class="cc-diag__docs cc-t-dim">Docs: https://commit-check.com/rules/#cc001</p>
</div>
Expand Down
5 changes: 2 additions & 3 deletions docs/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,8 @@ $ commit-check --message --branch
`commit-check.toml`, in the repository root or `.github/`. Any other name needs
`--config`.

**TOML fails to parse.** Usually unquoted strings, `True` instead of `true`, or
a trailing comma in an array. Editors validate the file against the published
schema — see
**TOML fails to parse.** Usually unquoted strings, or `True` instead of `true`.
Editors validate the file against the published schema — see
[where the config file lives](configuration.md#where-the-config-file-lives).

**A rule does not behave as expected.** Check the option name and its default in
Expand Down
Loading