commit-check 2.18.0__py3-none-any.whl → 2.18.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- commit_check/api.py +4 -1
- commit_check/engine.py +39 -20
- commit_check/main.py +6 -1
- commit_check-2.18.2.dist-info/METADATA +256 -0
- {commit_check-2.18.0.dist-info → commit_check-2.18.2.dist-info}/RECORD +9 -9
- commit_check-2.18.0.dist-info/METADATA +0 -940
- {commit_check-2.18.0.dist-info → commit_check-2.18.2.dist-info}/WHEEL +0 -0
- {commit_check-2.18.0.dist-info → commit_check-2.18.2.dist-info}/entry_points.txt +0 -0
- {commit_check-2.18.0.dist-info → commit_check-2.18.2.dist-info}/licenses/LICENSE +0 -0
- {commit_check-2.18.0.dist-info → commit_check-2.18.2.dist-info}/top_level.txt +0 -0
commit_check/api.py
CHANGED
|
@@ -206,7 +206,8 @@ def validate_push(
|
|
|
206
206
|
|
|
207
207
|
:param push_refs: Push ref information in the format produced by git's
|
|
208
208
|
pre-push hook: ``<local ref> <local sha1> <remote ref> <remote sha1>``,
|
|
209
|
-
one entry per line. If *None
|
|
209
|
+
one entry per line. If *None* or empty, or no line names a ref,
|
|
210
|
+
there is nothing to compare and the check reports ``"skip"``.
|
|
210
211
|
:param config: Optional configuration override dict. The push check is
|
|
211
212
|
always enabled when calling this function; a detected force push fails
|
|
212
213
|
the result unless ``no_force_push`` is listed under ``warn``, in which
|
|
@@ -221,6 +222,8 @@ def validate_push(
|
|
|
221
222
|
>>> result = validate_push(f"refs/heads/main abc123 refs/heads/main {zero}")
|
|
222
223
|
>>> result["status"]
|
|
223
224
|
'pass'
|
|
225
|
+
>>> validate_push(None)["status"]
|
|
226
|
+
'skip'
|
|
224
227
|
"""
|
|
225
228
|
cfg = _merge_config(config)
|
|
226
229
|
# Enable force push blocking in the config so the rule is built
|
commit_check/engine.py
CHANGED
|
@@ -93,6 +93,14 @@ class ValidationContext:
|
|
|
93
93
|
files_cache: dict[str, list[tuple[str, int]]] = field(
|
|
94
94
|
default_factory=dict, repr=False, compare=False
|
|
95
95
|
)
|
|
96
|
+
# Set when stdin_text is a piped commit message: checks with a value of
|
|
97
|
+
# their own (branch, author, tags, push refs) then read git instead.
|
|
98
|
+
stdin_is_message: bool = False
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def piped_value(self) -> str | None:
|
|
102
|
+
"""stdin_text as a check's own value, or None when it is the message."""
|
|
103
|
+
return None if self.stdin_is_message else self.stdin_text
|
|
96
104
|
|
|
97
105
|
|
|
98
106
|
@dataclass
|
|
@@ -334,14 +342,14 @@ class BaseValidator(ABC):
|
|
|
334
342
|
Determine if branch validation should be skipped.
|
|
335
343
|
|
|
336
344
|
Skip if the current author is in the ignore_authors list for branches,
|
|
337
|
-
or if no
|
|
345
|
+
or if no branch name was supplied and no commits exist.
|
|
338
346
|
"""
|
|
339
347
|
ignore_authors = context.config.get("branch", {}).get("ignore_authors", [])
|
|
340
348
|
if ignore_authors:
|
|
341
349
|
current_author = self._resolve_current_author(context)
|
|
342
350
|
if current_author and current_author in ignore_authors:
|
|
343
351
|
return True
|
|
344
|
-
return context.
|
|
352
|
+
return context.piped_value is None and not has_commits()
|
|
345
353
|
|
|
346
354
|
def _print_failure(
|
|
347
355
|
self,
|
|
@@ -614,8 +622,9 @@ class AuthorValidator(BaseValidator):
|
|
|
614
622
|
Checks git config first (for pre-commit validation of the configured identity),
|
|
615
623
|
then falls back to the last commit's author info.
|
|
616
624
|
"""
|
|
617
|
-
|
|
618
|
-
|
|
625
|
+
supplied = context.piped_value
|
|
626
|
+
if supplied is not None:
|
|
627
|
+
return supplied.strip()
|
|
619
628
|
|
|
620
629
|
git_config_map = {
|
|
621
630
|
"author_name": "user.name",
|
|
@@ -669,11 +678,8 @@ class BranchValidator(BaseValidator):
|
|
|
669
678
|
def validate(self, context: ValidationContext) -> ValidationResult:
|
|
670
679
|
if self._should_skip_branch_validation(context):
|
|
671
680
|
return ValidationResult.SKIP
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
if context.stdin_text is not None
|
|
675
|
-
else get_branch_name()
|
|
676
|
-
)
|
|
681
|
+
supplied = context.piped_value
|
|
682
|
+
branch_name = supplied.strip() if supplied is not None else get_branch_name()
|
|
677
683
|
self._checked_value = branch_name
|
|
678
684
|
|
|
679
685
|
if not self.rule.regex:
|
|
@@ -730,8 +736,9 @@ class TagValidator(BaseValidator):
|
|
|
730
736
|
return lines
|
|
731
737
|
|
|
732
738
|
def validate(self, context: ValidationContext) -> ValidationResult:
|
|
733
|
-
|
|
734
|
-
|
|
739
|
+
supplied = context.piped_value
|
|
740
|
+
if supplied is not None:
|
|
741
|
+
tags = self._tags_from_stdin(supplied)
|
|
735
742
|
else:
|
|
736
743
|
tags = get_tags_at(context.rev or "HEAD")
|
|
737
744
|
|
|
@@ -814,8 +821,9 @@ class FilesValidator(BaseValidator):
|
|
|
814
821
|
or commits the remote already has — which the caller reports as a
|
|
815
822
|
skip rather than a pass.
|
|
816
823
|
"""
|
|
817
|
-
|
|
818
|
-
|
|
824
|
+
supplied = context.piped_value
|
|
825
|
+
if supplied is not None:
|
|
826
|
+
revs = self._push_revs_from_stdin(supplied)
|
|
819
827
|
if revs is not None:
|
|
820
828
|
return revs or None
|
|
821
829
|
return [context.rev or "HEAD"]
|
|
@@ -1108,6 +1116,10 @@ class ForcePushValidator(BaseValidator):
|
|
|
1108
1116
|
|
|
1109
1117
|
A force push is detected when the remote SHA is not an ancestor of the
|
|
1110
1118
|
local SHA, meaning local history would overwrite the remote.
|
|
1119
|
+
|
|
1120
|
+
With nothing to compare -- no ref lines, only blank or malformed ones, or
|
|
1121
|
+
no upstream to fall back on -- the check reports SKIP rather than PASS:
|
|
1122
|
+
it examined nothing, and a pass would read as a push that was judged safe.
|
|
1111
1123
|
"""
|
|
1112
1124
|
|
|
1113
1125
|
ZERO_SHA = "0000000000000000000000000000000000000000"
|
|
@@ -1117,23 +1129,30 @@ class ForcePushValidator(BaseValidator):
|
|
|
1117
1129
|
# branch name, stdin_text carries a *list* of refs, and no refs means
|
|
1118
1130
|
# there is nothing to check either way. So this one stays a truth test
|
|
1119
1131
|
# while the single-value readers above distinguish "" from None.
|
|
1120
|
-
|
|
1132
|
+
push_refs = context.piped_value
|
|
1133
|
+
if not push_refs:
|
|
1121
1134
|
if context.push_upstream_fallback:
|
|
1122
1135
|
return self._check_current_branch_against_upstream()
|
|
1123
|
-
return ValidationResult.
|
|
1136
|
+
return ValidationResult.SKIP
|
|
1124
1137
|
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1138
|
+
checked_any = False
|
|
1139
|
+
for line in push_refs.splitlines():
|
|
1140
|
+
line = line.strip()
|
|
1141
|
+
# A blank or malformed line names no ref, so it judges nothing.
|
|
1142
|
+
if len(line.split()) < 4:
|
|
1143
|
+
continue
|
|
1144
|
+
checked_any = True
|
|
1145
|
+
if self._check_push_line(line) == ValidationResult.FAIL:
|
|
1128
1146
|
return ValidationResult.FAIL
|
|
1129
1147
|
|
|
1130
|
-
return ValidationResult.PASS
|
|
1148
|
+
return ValidationResult.PASS if checked_any else ValidationResult.SKIP
|
|
1131
1149
|
|
|
1132
1150
|
def _check_current_branch_against_upstream(self) -> ValidationResult:
|
|
1133
1151
|
"""Check whether pushing HEAD to its upstream would require force."""
|
|
1134
1152
|
upstream_ref = get_upstream_branch()
|
|
1135
1153
|
if not upstream_ref:
|
|
1136
|
-
|
|
1154
|
+
# No upstream means no remote history to compare HEAD with.
|
|
1155
|
+
return ValidationResult.SKIP
|
|
1137
1156
|
|
|
1138
1157
|
if self._collect_value:
|
|
1139
1158
|
branch = get_branch_name()
|
commit_check/main.py
CHANGED
|
@@ -711,6 +711,9 @@ def main() -> int:
|
|
|
711
711
|
if not args.message:
|
|
712
712
|
stdin_content = _resolve_stdin_for_non_message(args, stdin_reader)
|
|
713
713
|
|
|
714
|
+
# Next to --message, piped stdin is the message; other checks read git.
|
|
715
|
+
stdin_is_message = args.message and stdin_content is not None
|
|
716
|
+
|
|
714
717
|
# Reset banner state for this run
|
|
715
718
|
print_error_header.has_been_called = False
|
|
716
719
|
|
|
@@ -721,7 +724,9 @@ def main() -> int:
|
|
|
721
724
|
config=config_data,
|
|
722
725
|
no_banner=getattr(args, "no_banner", False),
|
|
723
726
|
compact=getattr(args, "compact", False),
|
|
724
|
-
push_upstream_fallback=args.no_force_push
|
|
727
|
+
push_upstream_fallback=args.no_force_push
|
|
728
|
+
and (stdin_content is None or stdin_is_message),
|
|
729
|
+
stdin_is_message=stdin_is_message,
|
|
725
730
|
)
|
|
726
731
|
|
|
727
732
|
# Run validation – choose output mode based on --format
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: commit-check
|
|
3
|
+
Version: 2.18.2
|
|
4
|
+
Summary: Check commit message formatting, branch naming, commit author, email, and more.
|
|
5
|
+
Author-email: Xianpeng Shen <xianpeng.shen@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: documentation, https://commit-check.com/
|
|
8
|
+
Project-URL: source, https://github.com/commit-check/commit-check
|
|
9
|
+
Project-URL: tracker, https://github.com/commit-check/commit-check/issues
|
|
10
|
+
Keywords: commit conventions,conventional commits,conventional branch,branch naming,commit-check,message,lint message,devops
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Natural Language :: English
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
21
|
+
Classifier: Topic :: Utilities
|
|
22
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: tomli>=1.1.0; python_version < "3.11"
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: nox==2026.8.17; extra == "dev"
|
|
30
|
+
Provides-Extra: test
|
|
31
|
+
Requires-Dist: coverage; extra == "test"
|
|
32
|
+
Requires-Dist: pytest; extra == "test"
|
|
33
|
+
Requires-Dist: pytest-mock; extra == "test"
|
|
34
|
+
Requires-Dist: pytest-codspeed; extra == "test"
|
|
35
|
+
Provides-Extra: ci
|
|
36
|
+
Requires-Dist: twine==7.0.0; extra == "ci"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
<div align="center">
|
|
40
|
+
|
|
41
|
+
<picture>
|
|
42
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/commit-check/.github/main/branding/banner-dark.png">
|
|
43
|
+
<img src="https://raw.githubusercontent.com/commit-check/.github/main/branding/banner-light.png" alt="Commit Check">
|
|
44
|
+
</picture>
|
|
45
|
+
|
|
46
|
+
**Catch bad commits before they merge.**
|
|
47
|
+
|
|
48
|
+
[](https://pypi.org/project/commit-check/)
|
|
49
|
+
[](https://pepy.tech/projects/commit-check)
|
|
50
|
+
[](https://github.com/commit-check/commit-check/actions/workflows/main.yml)
|
|
51
|
+
[](https://codecov.io/gh/commit-check/commit-check)
|
|
52
|
+
[](https://scorecard.dev/viewer/?uri=github.com/commit-check/commit-check)
|
|
53
|
+
|
|
54
|
+
[Docs](https://commit-check.com/getting-started/) ·
|
|
55
|
+
[Rules](https://commit-check.com/rules/) ·
|
|
56
|
+
[GitHub Action](https://github.com/commit-check/commit-check-action) ·
|
|
57
|
+
[GitHub App](https://github.com/apps/commit-check) ·
|
|
58
|
+
[MCP server](https://github.com/commit-check/commit-check-mcp)
|
|
59
|
+
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
**Commit Check** validates commit messages, branch names, authors, sign-offs,
|
|
63
|
+
tags, committed files and AI attribution against one `cchk.toml` — in your
|
|
64
|
+
commit hook, in CI, on every pull request and inside your AI agent. When the
|
|
65
|
+
fix is obvious, it hands you the line.
|
|
66
|
+
|
|
67
|
+

|
|
68
|
+
|
|
69
|
+
## Quick start
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install commit-check # Python 3.10+
|
|
73
|
+
commit-check --message --branch
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
No config needed: out of the box it checks [Conventional Commits](https://www.conventionalcommits.org)
|
|
77
|
+
and [Conventional Branch](https://conventionalbranch.org).
|
|
78
|
+
|
|
79
|
+
### Use with pre-commit
|
|
80
|
+
|
|
81
|
+
Stop bad commits before they exist. In `.pre-commit-config.yaml`:
|
|
82
|
+
|
|
83
|
+
```yaml
|
|
84
|
+
repos:
|
|
85
|
+
- repo: https://github.com/commit-check/commit-check
|
|
86
|
+
rev: v2.18.1
|
|
87
|
+
hooks:
|
|
88
|
+
- id: check-message
|
|
89
|
+
- id: check-branch
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The hooks for the other checks (`check-author-name`, `check-author-email`,
|
|
93
|
+
`check-no-force-push`, `check-tag`, `check-files`) are listed in the
|
|
94
|
+
[pre-commit guide](https://commit-check.com/guides/pre-commit/).
|
|
95
|
+
|
|
96
|
+
### Everywhere else
|
|
97
|
+
|
|
98
|
+
The same `cchk.toml` drives all of them:
|
|
99
|
+
|
|
100
|
+
| Run it in | How |
|
|
101
|
+
|---|---|
|
|
102
|
+
| GitHub Actions | `uses: commit-check/commit-check-action@v2` — see [commit-check-action](https://github.com/commit-check/commit-check-action) |
|
|
103
|
+
| GitHub, no workflow | [Install the GitHub App](https://github.com/apps/commit-check) — one check run per commit |
|
|
104
|
+
| AI agents | `--format json`, the [Python API](#ai-native-usage), or the [MCP server](https://github.com/commit-check/commit-check-mcp) |
|
|
105
|
+
|
|
106
|
+
## What it checks
|
|
107
|
+
|
|
108
|
+
| Check | Flag | Rules |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| Commit message — Conventional Commits, subject length, case and mood, WIP and fixup commits, body, sign-off | `--message` | CC001–CC012 |
|
|
111
|
+
| AI attribution — forbid it, or require an `Assisted-by:` disclosure | `--message` | CC013–CC016 |
|
|
112
|
+
| Author name and email | `--author-name` `--author-email` | CC101–CC102 |
|
|
113
|
+
| Branch name — Conventional Branch, rebased onto a target | `--branch` | CC201–CC202 |
|
|
114
|
+
| Force push | `--no-force-push` | CC301 |
|
|
115
|
+
| Committed files — size, forbidden paths, path length | `--files` | CC302–CC304 |
|
|
116
|
+
| Tag names — SemVer or your own pattern | `--tag` | CC401 |
|
|
117
|
+
|
|
118
|
+
Every rule, with examples: [commit-check.com/rules](https://commit-check.com/rules/)
|
|
119
|
+
|
|
120
|
+
## Configure
|
|
121
|
+
|
|
122
|
+
Put a `cchk.toml` (or `commit-check.toml`) in the repository root or in `.github/`:
|
|
123
|
+
|
|
124
|
+
```toml
|
|
125
|
+
[commit]
|
|
126
|
+
subject_max_length = 72
|
|
127
|
+
require_signed_off_by = true
|
|
128
|
+
ai_attribution = "disclose"
|
|
129
|
+
ignore_authors = ["dependabot[bot]", "renovate[bot]"]
|
|
130
|
+
|
|
131
|
+
[branch]
|
|
132
|
+
conventional_branch = true
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
- **Roll out gently:** `warn = ["CC003"]` reports a rule in full without failing the run.
|
|
136
|
+
- **One policy per organization:** `inherit_from = "github:my-org/.github:cchk.toml"` — see [organization config](https://commit-check.com/guides/organization/).
|
|
137
|
+
- **Override anywhere:** every key has a CLI flag and a `CCHK_*` environment variable.
|
|
138
|
+
- **Editor support:** the schema is on [SchemaStore](https://www.schemastore.org/), so VS Code and JetBrains autocomplete `cchk.toml`.
|
|
139
|
+
|
|
140
|
+
<details>
|
|
141
|
+
<summary><b>Configuration reference</b> — every key, its default, CLI flag and environment variable</summary>
|
|
142
|
+
|
|
143
|
+
Priority: CLI > env > TOML > default. Booleans accept `true/false`, `yes/no`,
|
|
144
|
+
`1/0`; lists are comma-separated on the CLI and in env vars.
|
|
145
|
+
|
|
146
|
+
| Key | Default | CLI flag | Env var | Meaning |
|
|
147
|
+
|-----|---------|----------|---------|---------|
|
|
148
|
+
| `warn` (top level) | `[]` | — | — | Checks or rule IDs to report without failing the run (see "Report a rule without enforcing it") |
|
|
149
|
+
| `commit.conventional_commits` | `true` | `--conventional-commits` | `CCHK_CONVENTIONAL_COMMITS` | Enforce the Conventional Commits format (CC001) |
|
|
150
|
+
| `commit.message_pattern` | `""` | — | `CCHK_MESSAGE_PATTERN` | Custom regex the whole message must match; when set it replaces the Conventional Commits check (still reported as CC001) |
|
|
151
|
+
| `commit.subject_capitalized` | `false` | `--subject-capitalized` | `CCHK_SUBJECT_CAPITALIZED` | Require the subject to start with a capital letter (CC002) |
|
|
152
|
+
| `commit.subject_imperative` | `false` | `--subject-imperative` | `CCHK_SUBJECT_IMPERATIVE` | Require the subject to use the imperative mood (CC003) |
|
|
153
|
+
| `commit.subject_max_length` | `80` | `--subject-max-length` | `CCHK_SUBJECT_MAX_LENGTH` | Maximum subject length (CC004) |
|
|
154
|
+
| `commit.subject_min_length` | `5` | `--subject-min-length` | `CCHK_SUBJECT_MIN_LENGTH` | Minimum subject length (CC005) |
|
|
155
|
+
| `commit.allow_commit_types` | `feat, fix, docs, style, refactor, test, chore, perf, build, ci` | `--allow-commit-types` | `CCHK_ALLOW_COMMIT_TYPES` | Allowed `<type>` values in the subject |
|
|
156
|
+
| `commit.allow_merge_commits` | `true` | `--allow-merge-commits` | `CCHK_ALLOW_MERGE_COMMITS` | Allow merge commits (CC006) |
|
|
157
|
+
| `commit.allow_revert_commits` | `true` | `--allow-revert-commits` | `CCHK_ALLOW_REVERT_COMMITS` | Allow revert commits (CC007) |
|
|
158
|
+
| `commit.allow_empty_commits` | `true` | `--allow-empty-commits` | `CCHK_ALLOW_EMPTY_COMMITS` | Allow empty commit messages (CC008) |
|
|
159
|
+
| `commit.allow_fixup_commits` | `true` | `--allow-fixup-commits` | `CCHK_ALLOW_FIXUP_COMMITS` | Allow `fixup!` commits (CC009) |
|
|
160
|
+
| `commit.allow_wip_commits` | `true` | `--allow-wip-commits` | `CCHK_ALLOW_WIP_COMMITS` | Allow WIP commits (CC010) |
|
|
161
|
+
| `commit.require_body` | `false` | `--require-body` | `CCHK_REQUIRE_BODY` | Require a commit body (CC011) |
|
|
162
|
+
| `commit.require_signed_off_by` | `false` | `--require-signed-off-by` | `CCHK_REQUIRE_SIGNED_OFF_BY` | Require a `Signed-off-by:` trailer (CC012) |
|
|
163
|
+
| `commit.ignore_authors` | `[]` | `--ignore-authors` | `CCHK_IGNORE_AUTHORS` | Authors and co-authors whose commits skip the commit checks |
|
|
164
|
+
| `commit.ai_attribution` | `"ignore"` | `--ai-attribution` | `CCHK_AI_ATTRIBUTION` | `ignore`, `forbid` or `disclose`. `forbid` rejects commits carrying known AI tool signatures (CC013); `disclose` accepts AI assistance disclosed with one of `ai_disclosure_trailers` (CC014) and rejects the tool as a co-author (CC015) or as a sign-off (CC016) |
|
|
165
|
+
| `commit.ai_disclosure_trailers` | `Assisted-by, Generated-by` | `--ai-disclosure-trailers` | `CCHK_AI_DISCLOSURE_TRAILERS` | Trailers that disclose AI assistance under `disclose`; the first is the one a fix is written with. List `Co-authored-by` to accept the tool as a co-author |
|
|
166
|
+
| `commit.ai_disclosure_pattern` | `""` | `--ai-disclosure-pattern` | `CCHK_AI_DISCLOSURE_PATTERN` | Regex the disclosure's value must match under `disclose`, e.g. `^\S+/\S+` for `agent/model`; empty accepts any value, but a trailer with no value at all is always reported |
|
|
167
|
+
| `commit.author_email_pattern` | `"^.+@.+$"` | `--author-email-pattern` | `CCHK_AUTHOR_EMAIL_PATTERN` | Regex the author email must match (CC102, with `--author-email`) |
|
|
168
|
+
| `commit.author_name_pattern` | `""` | `--author-name-pattern` | `CCHK_AUTHOR_NAME_PATTERN` | Regex the author name must match (CC101, with `--author-name`) |
|
|
169
|
+
| `branch.conventional_branch` | `true` | `--conventional-branch` | `CCHK_CONVENTIONAL_BRANCH` | Enforce `<type>/<description>` branch names (CC201) |
|
|
170
|
+
| `branch.allow_branch_types` | `feature, bugfix, hotfix, release, chore, feat, fix, build, ci, docs, perf, refactor, test, style, ai, claude, codex, copilot, cursor, dependabot, renovate` | `--allow-branch-types` | `CCHK_ALLOW_BRANCH_TYPES` | Allowed branch `<type>` prefixes; each entry is a regex matched against the whole type |
|
|
171
|
+
| `branch.allow_branch_names` | `[]` | `--allow-branch-names` | `CCHK_ALLOW_BRANCH_NAMES` | Extra branch names allowed besides `main`, `master`, `HEAD`, `PR-.+`; each entry is a regex matched against the whole branch name, so `create-pull-request/.+` allows a family of them |
|
|
172
|
+
| `branch.require_rebase_target` | `""` | `--require-rebase-target` | `CCHK_REQUIRE_REBASE_TARGET` | Branch the current branch must be rebased onto (CC202); empty disables |
|
|
173
|
+
| `branch.ignore_authors` | `[]` | `--branch-ignore-authors` | `CCHK_BRANCH_IGNORE_AUTHORS` | Authors whose branches skip the branch checks |
|
|
174
|
+
| `push.allow_force_push` | `true` | — (`--no-force-push` runs the check) | `CCHK_ALLOW_FORCE_PUSH` | Reserved; has no effect today. CC301 runs only with `--no-force-push`, which always rejects a non-fast-forward push |
|
|
175
|
+
| `tag.regex` | SemVer with optional `v` | `--tag-regex` | `CCHK_TAG_REGEX` | Pattern tag names must match (CC401); empty disables |
|
|
176
|
+
| `files.max_size` | `""` (off) | `--files-max-size` | `CCHK_FILES_MAX_SIZE` | Largest committed file, in bytes or with `KB`/`MB`/`GB` (CC302) |
|
|
177
|
+
| `files.prohibited_patterns` | `[]` | `--files-prohibited-patterns` | `CCHK_FILES_PROHIBITED_PATTERNS` | fnmatch patterns committed paths must not match (CC303) |
|
|
178
|
+
| `files.max_path_length` | `0` (off) | `--files-max-path-length` | `CCHK_FILES_MAX_PATH_LENGTH` | Longest allowed committed path, in characters (CC304) |
|
|
179
|
+
|
|
180
|
+
Output and appearance are per-run flags, not configuration: `--format json`,
|
|
181
|
+
`--no-banner`, `--compact`, `--dry-run`, `--rev`, `--config`. Color follows
|
|
182
|
+
`NO_COLOR` / `FORCE_COLOR`. Long-form descriptions: [commit-check.com/configuration](https://commit-check.com/configuration/)
|
|
183
|
+
|
|
184
|
+
</details>
|
|
185
|
+
|
|
186
|
+
## AI-native usage
|
|
187
|
+
|
|
188
|
+
`--format json` gives each check a stable rule ID, the value it saw and a
|
|
189
|
+
suggestion — plus the corrected value itself when the correction is
|
|
190
|
+
mechanical, so an agent can apply it without interpreting anything:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
echo "Fix: add streaming support" | commit-check -m --format json
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The failing entry of its `checks` array:
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"rule_id": "CC001",
|
|
201
|
+
"check": "message",
|
|
202
|
+
"status": "fail",
|
|
203
|
+
"value": "Fix: add streaming support",
|
|
204
|
+
"error": "The commit message should follow Conventional Commits. See https://www.conventionalcommits.org",
|
|
205
|
+
"suggest": "Use \"fix: add streaming support\"",
|
|
206
|
+
"fix": "fix: add streaming support",
|
|
207
|
+
"docs_url": "https://commit-check.com/rules/#cc001"
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The same result, without a subprocess:
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
from commit_check.api import validate_message
|
|
215
|
+
|
|
216
|
+
validate_message("feat: add streaming support")["status"] # "pass"
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
`commit_check.api` also has `validate_branch`, `validate_author`,
|
|
220
|
+
`validate_tag`, `validate_push` and `validate_all`, all returning the same
|
|
221
|
+
shape. Unlike the CLI they do not read `cchk.toml`: pass the policy as a
|
|
222
|
+
`config` dict. The [Python API](https://commit-check.com/guides/python-api/)
|
|
223
|
+
page covers each function and how to load a repository's file.
|
|
224
|
+
|
|
225
|
+
Exit codes: `0` passed · `1` a check failed · `2` nothing was checked — bad
|
|
226
|
+
usage, or a config that is missing, is not valid TOML, names an unknown rule or
|
|
227
|
+
holds a regex that does not compile. `--dry-run` reports everything and exits `0`. More output formats: [examples](https://commit-check.com/example/).
|
|
228
|
+
|
|
229
|
+
## Why Commit Check
|
|
230
|
+
|
|
231
|
+
| | Commit Check | commitlint | GitHub Rulesets |
|
|
232
|
+
|---|:-:|:-:|:-:|
|
|
233
|
+
| Conventional Commits | ✅ | ✅ | regex only |
|
|
234
|
+
| Branch, tag, author and file rules | ✅ | ❌ | ✅\* |
|
|
235
|
+
| Feedback before the push | ✅ | ✅ | ❌ |
|
|
236
|
+
| Works with zero config | ✅ | ❌ | ❌ |
|
|
237
|
+
| No Node.js | ✅ | ❌ | ✅ |
|
|
238
|
+
| JSON output, Python API, MCP | ✅ | ❌ | ❌ |
|
|
239
|
+
|
|
240
|
+
\*Push rulesets need a Team or Enterprise plan for private repositories.
|
|
241
|
+
The full comparison, including YACC and custom hooks: [commit-check.com/compare](https://commit-check.com/compare/tools/)
|
|
242
|
+
|
|
243
|
+
## Show that you use it
|
|
244
|
+
|
|
245
|
+
[](https://commit-check.com)
|
|
246
|
+
|
|
247
|
+
```text
|
|
248
|
+
[](https://commit-check.com)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Community
|
|
252
|
+
|
|
253
|
+
Questions and ideas go to [Discussions](https://github.com/commit-check/commit-check/discussions),
|
|
254
|
+
bugs to [Issues](https://github.com/commit-check/commit-check/issues).
|
|
255
|
+
Releases follow [Semantic Versioning](https://semver.org/). Released under the
|
|
256
|
+
[MIT License](https://github.com/commit-check/commit-check/blob/main/LICENSE).
|
|
@@ -2,20 +2,20 @@ commit_check/__init__.py,sha256=--TSQBRscNxJtSNl74Mm6OGxjX0SDh_Gqicuu2AoEYU,4420
|
|
|
2
2
|
commit_check/ai_policy.py,sha256=gYC3ROLgGL1TDyhPkFXkV-NiYbvMt80Qt0MFrJcbJY4,8131
|
|
3
3
|
commit_check/ai_signatures.py,sha256=XTfHh8zD2EbHjuCBBbukQllTJWqO7EoehVc7bADMwQY,9437
|
|
4
4
|
commit_check/ai_signatures_data.py,sha256=33uiiAieL1wB6isgU-dgkz10IrQub7lVCGh8hf7XiN8,11213
|
|
5
|
-
commit_check/api.py,sha256=
|
|
5
|
+
commit_check/api.py,sha256=RlLGWfpEu9iW-7zIWJ7xDHTYHdH7w4a-0AE7yJH6jU0,12818
|
|
6
6
|
commit_check/config.py,sha256=3KAoCU3sREyT0llePdKE6YrM79tmGka3a2j8LqF27WA,9815
|
|
7
7
|
commit_check/config_merger.py,sha256=k3heMtKEMCSca-LtAntfyvNdPaB18iusfPjt_BOe6j8,11758
|
|
8
|
-
commit_check/engine.py,sha256=
|
|
8
|
+
commit_check/engine.py,sha256=vjMcrKpjQR9e_HZoHYkmCUJqcmOw8iOckxpCBqUUvXk,68640
|
|
9
9
|
commit_check/fixes.py,sha256=AsE9ChMXoOCV61pgxbZZNkAzmQS9_ARTWvvox4HkgEg,7088
|
|
10
10
|
commit_check/imperatives.py,sha256=dEd_ssu4G0j6Cann6jqPdB97lw5Adua43K0_Odg_FyA,9518
|
|
11
|
-
commit_check/main.py,sha256=
|
|
11
|
+
commit_check/main.py,sha256=dyvEHptwOdGZA01E3nxbNwNmUvxfgT-vIgfXzvLtqBM,24881
|
|
12
12
|
commit_check/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
commit_check/rule_builder.py,sha256=f42vN3X_hYU47YgJ0xCniwKW9CwlDwt-4Q_WC7_Y-6E,29591
|
|
14
14
|
commit_check/rules_catalog.py,sha256=Sa4jsyxWJ8g6fX2qJTdIMnd6513in5GmSxHYL5nTwws,11557
|
|
15
15
|
commit_check/util.py,sha256=o0PuiiRhSgIVBmBF_20VytiHj74VlKb3nCMJ8KxB2Ds,25749
|
|
16
|
-
commit_check-2.18.
|
|
17
|
-
commit_check-2.18.
|
|
18
|
-
commit_check-2.18.
|
|
19
|
-
commit_check-2.18.
|
|
20
|
-
commit_check-2.18.
|
|
21
|
-
commit_check-2.18.
|
|
16
|
+
commit_check-2.18.2.dist-info/licenses/LICENSE,sha256=VAJ9TE1ov8aUKmeoBRYqciMs0CXag1TeDCoLhwbeQmA,1095
|
|
17
|
+
commit_check-2.18.2.dist-info/METADATA,sha256=9LtV66iFvvvt72VtMZo07FUtJCB78s5hBUfqRt-YsNU,15077
|
|
18
|
+
commit_check-2.18.2.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
19
|
+
commit_check-2.18.2.dist-info/entry_points.txt,sha256=YMrkFGeub-3-IanV1d9qnopXVaRQM7MA9foXKW9iZ88,86
|
|
20
|
+
commit_check-2.18.2.dist-info/top_level.txt,sha256=Wf46u-ooHBMJNHbhfrBNQw3wC5_m8wt-o_Lfbc4QpRg,13
|
|
21
|
+
commit_check-2.18.2.dist-info/RECORD,,
|