git-commit-guard 0.18.0__tar.gz → 0.20.0__tar.gz
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.
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.github/workflows/lint-commits.yml +1 -1
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.github/workflows/lint-workflows.yml +25 -2
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.github/workflows/release.yml +5 -2
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/PKG-INFO +64 -13
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/README.md +63 -12
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/action.yml +6 -0
- git_commit_guard-0.20.0/cliff.toml +56 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/docs/index.html +65 -6
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/src/git_commit_guard/__init__.py +192 -13
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/tests/test_git_commit_guard.py +518 -13
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.editorconfig +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.github/workflows/coverage-baseline.yml +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.github/workflows/coverage-comment.yml +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.github/workflows/lint-md.yml +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.github/workflows/lint-python.yml +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.github/workflows/test.yml +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.gitignore +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.markdownlint.json +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.pre-commit-hooks.yaml +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/.python-version +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/LICENSE +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/docs/commit-guard-icon.svg +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/pyproject.toml +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/ruff.toml +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/tests/__init__.py +0 -0
- {git_commit_guard-0.18.0 → git_commit_guard-0.20.0}/uv.lock +0 -0
|
@@ -22,7 +22,7 @@ jobs:
|
|
|
22
22
|
key: nltk-averaged-perceptron-tagger-punkt
|
|
23
23
|
- name: Lint commits
|
|
24
24
|
# yamllint disable-line rule:line-length
|
|
25
|
-
uses: benner/commit-guard@
|
|
25
|
+
uses: benner/commit-guard@7704c563540b24bb10394e373e508dc664a7f01f # v0.19.0
|
|
26
26
|
with:
|
|
27
27
|
range: origin/${{ github.base_ref }}..HEAD
|
|
28
28
|
disable: signature
|
|
@@ -21,7 +21,30 @@ jobs:
|
|
|
21
21
|
with:
|
|
22
22
|
github_token: ${{ github.token }}
|
|
23
23
|
reporter: github-pr-review
|
|
24
|
-
|
|
24
|
+
yamlfix:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
permissions:
|
|
27
|
+
pull-requests: write
|
|
28
|
+
steps:
|
|
29
|
+
- name: Checkout code
|
|
30
|
+
# yamllint disable-line rule:line-length
|
|
31
|
+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # ratchet:actions/checkout@v4
|
|
32
|
+
with:
|
|
33
|
+
persist-credentials: false
|
|
34
|
+
- name: Set up uv
|
|
35
|
+
# yamllint disable-line rule:line-length
|
|
36
|
+
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # ratchet:astral-sh/setup-uv@v7
|
|
37
|
+
- name: Set up reviewdog
|
|
38
|
+
# yamllint disable-line rule:line-length
|
|
39
|
+
uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # ratchet:reviewdog/action-setup@v1
|
|
40
|
+
- name: Run yamlfix
|
|
41
|
+
env:
|
|
42
|
+
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
|
|
43
|
+
run: |-
|
|
44
|
+
uvx yamlfix .github/workflows/
|
|
45
|
+
git diff .github/workflows/ |
|
|
46
|
+
reviewdog -f=diff -name=yamlfix \
|
|
47
|
+
-reporter=github-pr-review -fail-on-error
|
|
25
48
|
zizmor:
|
|
26
49
|
runs-on: ubuntu-latest
|
|
27
50
|
permissions:
|
|
@@ -41,7 +64,7 @@ jobs:
|
|
|
41
64
|
- name: Run zizmor
|
|
42
65
|
env:
|
|
43
66
|
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
|
|
44
|
-
run:
|
|
67
|
+
run: |-
|
|
45
68
|
uvx zizmor==1.24.1 --format=sarif . |
|
|
46
69
|
reviewdog -f=sarif -name=zizmor \
|
|
47
70
|
-reporter=github-pr-review -fail-on-error
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
name: Release
|
|
3
3
|
on: # yamllint disable-line rule:truthy
|
|
4
4
|
push:
|
|
5
|
-
tags:
|
|
6
|
-
- 'v*'
|
|
5
|
+
tags: [v*]
|
|
7
6
|
permissions:
|
|
8
7
|
contents: write
|
|
9
8
|
id-token: write
|
|
9
|
+
pull-requests: read
|
|
10
10
|
jobs:
|
|
11
11
|
release:
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
|
+
environment: pypi
|
|
13
14
|
steps:
|
|
14
15
|
- name: Checkout code
|
|
15
16
|
# yamllint disable-line rule:line-length
|
|
@@ -34,6 +35,8 @@ jobs:
|
|
|
34
35
|
id: git-cliff
|
|
35
36
|
# yamllint disable-line rule:line-length
|
|
36
37
|
uses: orhun/git-cliff-action@f50e11560dce63f7c33227798f90b924471a88b5 # ratchet:orhun/git-cliff-action@v4.8.0
|
|
38
|
+
env:
|
|
39
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
37
40
|
with:
|
|
38
41
|
args: --current
|
|
39
42
|
- name: Create GitHub Release
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: git-commit-guard
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.20.0
|
|
4
4
|
Summary: Opinionated conventional commit message linter with imperative mood detection
|
|
5
5
|
Project-URL: Homepage, https://github.com/benner/commit-guard
|
|
6
6
|
Project-URL: Repository, https://github.com/benner/commit-guard
|
|
@@ -98,7 +98,8 @@ Available checks:
|
|
|
98
98
|
* `imperative` - First word is an imperative verb (for example `add` not `added`)
|
|
99
99
|
* `body` - Blank line separates subject from body, and body is non-empty
|
|
100
100
|
* `signed-off` - `Signed-off-by:` trailer exists
|
|
101
|
-
* `signature` - Verify GPG or SSH signature
|
|
101
|
+
* `signature` - Verify GPG or SSH signature via the GitHub Commits API or
|
|
102
|
+
public key lookup
|
|
102
103
|
|
|
103
104
|
### Subject length
|
|
104
105
|
|
|
@@ -181,6 +182,25 @@ commit-guard --require-scope
|
|
|
181
182
|
commit-guard --scopes auth,api --require-scope
|
|
182
183
|
```
|
|
183
184
|
|
|
185
|
+
### Required subject pattern
|
|
186
|
+
|
|
187
|
+
Require the commit subject to match a regular expression. Useful for
|
|
188
|
+
enforcing ticket references or any custom naming convention:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
commit-guard --require-subject-pattern "[A-Z]+-[0-9]+"
|
|
192
|
+
commit-guard --require-subject-pattern "#[0-9]+"
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
In `.commit-guard.toml`:
|
|
196
|
+
|
|
197
|
+
```toml
|
|
198
|
+
require-subject-pattern = "[A-Z]+-[0-9]+"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
An invalid regex causes an immediate error at startup (exit 2). This
|
|
202
|
+
check runs independently of `--enable`/`--disable`.
|
|
203
|
+
|
|
184
204
|
### Required custom trailers
|
|
185
205
|
|
|
186
206
|
Require arbitrary trailers to be present in the commit message. Multiple
|
|
@@ -201,12 +221,40 @@ Trailer matching is case-sensitive and requires at least one non-space
|
|
|
201
221
|
character after the colon (e.g. `Closes: #42`). This check runs
|
|
202
222
|
independently of `--enable`/`--disable`.
|
|
203
223
|
|
|
224
|
+
### Signature verification
|
|
225
|
+
|
|
226
|
+
The `signature` check verifies the commit without any local keyring setup:
|
|
227
|
+
|
|
228
|
+
1. If the repo has a GitHub remote, call the Commits API
|
|
229
|
+
(`GET /repos/{owner}/{repo}/commits/{sha}`) to resolve the author's GitHub
|
|
230
|
+
username — this works for corporate emails, noreply addresses, or any email
|
|
231
|
+
not listed publicly on a GitHub profile.
|
|
232
|
+
2. If the Commits API is unavailable (no GitHub remote, commit not yet pushed,
|
|
233
|
+
or API error), parse the username directly from a GitHub noreply address
|
|
234
|
+
(`{id}+{username}@users.noreply.github.com` or
|
|
235
|
+
`{username}@users.noreply.github.com`) — no API call needed.
|
|
236
|
+
3. If neither of the above resolves a username, fall back to searching GitHub
|
|
237
|
+
by the commit author's email.
|
|
238
|
+
4. Fetch the resolved user's public keys from `github.com/{username}.gpg` and
|
|
239
|
+
`github.com/{username}.keys`.
|
|
240
|
+
5. Try GPG verification: import the fetched key into a temporary keyring and
|
|
241
|
+
run `git verify-commit`.
|
|
242
|
+
6. Try SSH verification: write a temporary `allowed_signers` file and run
|
|
243
|
+
`git verify-commit` with the SSH allowed-signers config.
|
|
244
|
+
7. If any key verifies, the check passes. If none do, it fails.
|
|
245
|
+
|
|
246
|
+
If the author cannot be resolved via either method, or the GitHub API is
|
|
247
|
+
unreachable, the check fails with a clear error.
|
|
248
|
+
|
|
249
|
+
For private repositories, set `GITHUB_TOKEN` or `GH_TOKEN` so the Commits API
|
|
250
|
+
can authenticate.
|
|
251
|
+
|
|
204
252
|
### Configuration file
|
|
205
253
|
|
|
206
254
|
Place `.commit-guard.toml` in your project root (or any parent directory) to
|
|
207
255
|
set defaults for `enable`, `disable`, `scopes`, `require-scope`, `types`,
|
|
208
256
|
`max-subject-length`, `min-description-length`, `require-lowercase`,
|
|
209
|
-
`no-trailing-chars`, and `require-trailers`.
|
|
257
|
+
`no-trailing-chars`, `require-subject-pattern`, and `require-trailers`.
|
|
210
258
|
commit-guard searches upward from the working directory and uses the first
|
|
211
259
|
file found.
|
|
212
260
|
|
|
@@ -235,9 +283,11 @@ full precedence and ignore config file values when provided.
|
|
|
235
283
|
|
|
236
284
|
### Environment variables
|
|
237
285
|
|
|
238
|
-
| Variable | Default | Description
|
|
239
|
-
| -------------------------- | ------- |
|
|
240
|
-
| `COMMIT_GUARD_GIT_TIMEOUT` | `10` | Timeout in seconds for git subprocess calls.
|
|
286
|
+
| Variable | Default | Description |
|
|
287
|
+
| -------------------------- | ------- | ------------------------------------------------------------------------- |
|
|
288
|
+
| `COMMIT_GUARD_GIT_TIMEOUT` | `10` | Timeout in seconds for git subprocess calls. |
|
|
289
|
+
| `GITHUB_TOKEN` | — | GitHub token for Commits API access on private repos (signature check). |
|
|
290
|
+
| `GH_TOKEN` | — | Alias for `GITHUB_TOKEN`; used when `GITHUB_TOKEN` is not set. |
|
|
241
291
|
|
|
242
292
|
```bash
|
|
243
293
|
COMMIT_GUARD_GIT_TIMEOUT=30 commit-guard --range origin/main..HEAD
|
|
@@ -246,7 +296,7 @@ COMMIT_GUARD_GIT_TIMEOUT=30 commit-guard --range origin/main..HEAD
|
|
|
246
296
|
In GitHub Actions, set it at the step or job level:
|
|
247
297
|
|
|
248
298
|
```yaml
|
|
249
|
-
- uses: benner/commit-guard@v0.
|
|
299
|
+
- uses: benner/commit-guard@v0.19.0
|
|
250
300
|
env:
|
|
251
301
|
COMMIT_GUARD_GIT_TIMEOUT: 30
|
|
252
302
|
with:
|
|
@@ -330,7 +380,7 @@ steps:
|
|
|
330
380
|
- uses: actions/checkout@v4
|
|
331
381
|
with:
|
|
332
382
|
fetch-depth: 0
|
|
333
|
-
- uses: benner/commit-guard@v0.
|
|
383
|
+
- uses: benner/commit-guard@v0.19.0
|
|
334
384
|
```
|
|
335
385
|
|
|
336
386
|
Check all commits in a pull request:
|
|
@@ -346,7 +396,7 @@ jobs:
|
|
|
346
396
|
- uses: actions/checkout@v4
|
|
347
397
|
with:
|
|
348
398
|
fetch-depth: 0
|
|
349
|
-
- uses: benner/commit-guard@v0.
|
|
399
|
+
- uses: benner/commit-guard@v0.19.0
|
|
350
400
|
with:
|
|
351
401
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
352
402
|
```
|
|
@@ -354,7 +404,7 @@ jobs:
|
|
|
354
404
|
Check a specific commit SHA (mirrors the positional CLI argument):
|
|
355
405
|
|
|
356
406
|
```yaml
|
|
357
|
-
- uses: benner/commit-guard@v0.
|
|
407
|
+
- uses: benner/commit-guard@v0.19.0
|
|
358
408
|
with:
|
|
359
409
|
rev: ${{ github.sha }}
|
|
360
410
|
```
|
|
@@ -372,12 +422,13 @@ jobs:
|
|
|
372
422
|
- uses: actions/checkout@v4
|
|
373
423
|
with:
|
|
374
424
|
fetch-depth: 0
|
|
375
|
-
- uses: benner/commit-guard@v0.
|
|
425
|
+
- uses: benner/commit-guard@v0.19.0
|
|
376
426
|
with:
|
|
377
427
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
378
428
|
disable: signed-off,signature
|
|
379
429
|
scopes: auth,api,db
|
|
380
430
|
require-scope: 'true'
|
|
431
|
+
require-subject-pattern: '[A-Z]+-[0-9]+'
|
|
381
432
|
require-trailer: 'Closes,Reviewed-by'
|
|
382
433
|
max-subject-length: '100'
|
|
383
434
|
min-description-length: '10'
|
|
@@ -391,7 +442,7 @@ jobs:
|
|
|
391
442
|
When `output-file` is set the action exposes the path as an output:
|
|
392
443
|
|
|
393
444
|
```yaml
|
|
394
|
-
- uses: benner/commit-guard@v0.
|
|
445
|
+
- uses: benner/commit-guard@v0.19.0
|
|
395
446
|
id: cg
|
|
396
447
|
with:
|
|
397
448
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
@@ -407,7 +458,7 @@ Add to your `.pre-commit-config.yaml`:
|
|
|
407
458
|
---
|
|
408
459
|
repos:
|
|
409
460
|
- repo: https://github.com/benner/commit-guard
|
|
410
|
-
rev: v0.
|
|
461
|
+
rev: v0.19.0
|
|
411
462
|
hooks:
|
|
412
463
|
- id: commit-guard
|
|
413
464
|
- id: commit-guard-signature
|
|
@@ -77,7 +77,8 @@ Available checks:
|
|
|
77
77
|
* `imperative` - First word is an imperative verb (for example `add` not `added`)
|
|
78
78
|
* `body` - Blank line separates subject from body, and body is non-empty
|
|
79
79
|
* `signed-off` - `Signed-off-by:` trailer exists
|
|
80
|
-
* `signature` - Verify GPG or SSH signature
|
|
80
|
+
* `signature` - Verify GPG or SSH signature via the GitHub Commits API or
|
|
81
|
+
public key lookup
|
|
81
82
|
|
|
82
83
|
### Subject length
|
|
83
84
|
|
|
@@ -160,6 +161,25 @@ commit-guard --require-scope
|
|
|
160
161
|
commit-guard --scopes auth,api --require-scope
|
|
161
162
|
```
|
|
162
163
|
|
|
164
|
+
### Required subject pattern
|
|
165
|
+
|
|
166
|
+
Require the commit subject to match a regular expression. Useful for
|
|
167
|
+
enforcing ticket references or any custom naming convention:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
commit-guard --require-subject-pattern "[A-Z]+-[0-9]+"
|
|
171
|
+
commit-guard --require-subject-pattern "#[0-9]+"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
In `.commit-guard.toml`:
|
|
175
|
+
|
|
176
|
+
```toml
|
|
177
|
+
require-subject-pattern = "[A-Z]+-[0-9]+"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
An invalid regex causes an immediate error at startup (exit 2). This
|
|
181
|
+
check runs independently of `--enable`/`--disable`.
|
|
182
|
+
|
|
163
183
|
### Required custom trailers
|
|
164
184
|
|
|
165
185
|
Require arbitrary trailers to be present in the commit message. Multiple
|
|
@@ -180,12 +200,40 @@ Trailer matching is case-sensitive and requires at least one non-space
|
|
|
180
200
|
character after the colon (e.g. `Closes: #42`). This check runs
|
|
181
201
|
independently of `--enable`/`--disable`.
|
|
182
202
|
|
|
203
|
+
### Signature verification
|
|
204
|
+
|
|
205
|
+
The `signature` check verifies the commit without any local keyring setup:
|
|
206
|
+
|
|
207
|
+
1. If the repo has a GitHub remote, call the Commits API
|
|
208
|
+
(`GET /repos/{owner}/{repo}/commits/{sha}`) to resolve the author's GitHub
|
|
209
|
+
username — this works for corporate emails, noreply addresses, or any email
|
|
210
|
+
not listed publicly on a GitHub profile.
|
|
211
|
+
2. If the Commits API is unavailable (no GitHub remote, commit not yet pushed,
|
|
212
|
+
or API error), parse the username directly from a GitHub noreply address
|
|
213
|
+
(`{id}+{username}@users.noreply.github.com` or
|
|
214
|
+
`{username}@users.noreply.github.com`) — no API call needed.
|
|
215
|
+
3. If neither of the above resolves a username, fall back to searching GitHub
|
|
216
|
+
by the commit author's email.
|
|
217
|
+
4. Fetch the resolved user's public keys from `github.com/{username}.gpg` and
|
|
218
|
+
`github.com/{username}.keys`.
|
|
219
|
+
5. Try GPG verification: import the fetched key into a temporary keyring and
|
|
220
|
+
run `git verify-commit`.
|
|
221
|
+
6. Try SSH verification: write a temporary `allowed_signers` file and run
|
|
222
|
+
`git verify-commit` with the SSH allowed-signers config.
|
|
223
|
+
7. If any key verifies, the check passes. If none do, it fails.
|
|
224
|
+
|
|
225
|
+
If the author cannot be resolved via either method, or the GitHub API is
|
|
226
|
+
unreachable, the check fails with a clear error.
|
|
227
|
+
|
|
228
|
+
For private repositories, set `GITHUB_TOKEN` or `GH_TOKEN` so the Commits API
|
|
229
|
+
can authenticate.
|
|
230
|
+
|
|
183
231
|
### Configuration file
|
|
184
232
|
|
|
185
233
|
Place `.commit-guard.toml` in your project root (or any parent directory) to
|
|
186
234
|
set defaults for `enable`, `disable`, `scopes`, `require-scope`, `types`,
|
|
187
235
|
`max-subject-length`, `min-description-length`, `require-lowercase`,
|
|
188
|
-
`no-trailing-chars`, and `require-trailers`.
|
|
236
|
+
`no-trailing-chars`, `require-subject-pattern`, and `require-trailers`.
|
|
189
237
|
commit-guard searches upward from the working directory and uses the first
|
|
190
238
|
file found.
|
|
191
239
|
|
|
@@ -214,9 +262,11 @@ full precedence and ignore config file values when provided.
|
|
|
214
262
|
|
|
215
263
|
### Environment variables
|
|
216
264
|
|
|
217
|
-
| Variable | Default | Description
|
|
218
|
-
| -------------------------- | ------- |
|
|
219
|
-
| `COMMIT_GUARD_GIT_TIMEOUT` | `10` | Timeout in seconds for git subprocess calls.
|
|
265
|
+
| Variable | Default | Description |
|
|
266
|
+
| -------------------------- | ------- | ------------------------------------------------------------------------- |
|
|
267
|
+
| `COMMIT_GUARD_GIT_TIMEOUT` | `10` | Timeout in seconds for git subprocess calls. |
|
|
268
|
+
| `GITHUB_TOKEN` | — | GitHub token for Commits API access on private repos (signature check). |
|
|
269
|
+
| `GH_TOKEN` | — | Alias for `GITHUB_TOKEN`; used when `GITHUB_TOKEN` is not set. |
|
|
220
270
|
|
|
221
271
|
```bash
|
|
222
272
|
COMMIT_GUARD_GIT_TIMEOUT=30 commit-guard --range origin/main..HEAD
|
|
@@ -225,7 +275,7 @@ COMMIT_GUARD_GIT_TIMEOUT=30 commit-guard --range origin/main..HEAD
|
|
|
225
275
|
In GitHub Actions, set it at the step or job level:
|
|
226
276
|
|
|
227
277
|
```yaml
|
|
228
|
-
- uses: benner/commit-guard@v0.
|
|
278
|
+
- uses: benner/commit-guard@v0.19.0
|
|
229
279
|
env:
|
|
230
280
|
COMMIT_GUARD_GIT_TIMEOUT: 30
|
|
231
281
|
with:
|
|
@@ -309,7 +359,7 @@ steps:
|
|
|
309
359
|
- uses: actions/checkout@v4
|
|
310
360
|
with:
|
|
311
361
|
fetch-depth: 0
|
|
312
|
-
- uses: benner/commit-guard@v0.
|
|
362
|
+
- uses: benner/commit-guard@v0.19.0
|
|
313
363
|
```
|
|
314
364
|
|
|
315
365
|
Check all commits in a pull request:
|
|
@@ -325,7 +375,7 @@ jobs:
|
|
|
325
375
|
- uses: actions/checkout@v4
|
|
326
376
|
with:
|
|
327
377
|
fetch-depth: 0
|
|
328
|
-
- uses: benner/commit-guard@v0.
|
|
378
|
+
- uses: benner/commit-guard@v0.19.0
|
|
329
379
|
with:
|
|
330
380
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
331
381
|
```
|
|
@@ -333,7 +383,7 @@ jobs:
|
|
|
333
383
|
Check a specific commit SHA (mirrors the positional CLI argument):
|
|
334
384
|
|
|
335
385
|
```yaml
|
|
336
|
-
- uses: benner/commit-guard@v0.
|
|
386
|
+
- uses: benner/commit-guard@v0.19.0
|
|
337
387
|
with:
|
|
338
388
|
rev: ${{ github.sha }}
|
|
339
389
|
```
|
|
@@ -351,12 +401,13 @@ jobs:
|
|
|
351
401
|
- uses: actions/checkout@v4
|
|
352
402
|
with:
|
|
353
403
|
fetch-depth: 0
|
|
354
|
-
- uses: benner/commit-guard@v0.
|
|
404
|
+
- uses: benner/commit-guard@v0.19.0
|
|
355
405
|
with:
|
|
356
406
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
357
407
|
disable: signed-off,signature
|
|
358
408
|
scopes: auth,api,db
|
|
359
409
|
require-scope: 'true'
|
|
410
|
+
require-subject-pattern: '[A-Z]+-[0-9]+'
|
|
360
411
|
require-trailer: 'Closes,Reviewed-by'
|
|
361
412
|
max-subject-length: '100'
|
|
362
413
|
min-description-length: '10'
|
|
@@ -370,7 +421,7 @@ jobs:
|
|
|
370
421
|
When `output-file` is set the action exposes the path as an output:
|
|
371
422
|
|
|
372
423
|
```yaml
|
|
373
|
-
- uses: benner/commit-guard@v0.
|
|
424
|
+
- uses: benner/commit-guard@v0.19.0
|
|
374
425
|
id: cg
|
|
375
426
|
with:
|
|
376
427
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
@@ -386,7 +437,7 @@ Add to your `.pre-commit-config.yaml`:
|
|
|
386
437
|
---
|
|
387
438
|
repos:
|
|
388
439
|
- repo: https://github.com/benner/commit-guard
|
|
389
|
-
rev: v0.
|
|
440
|
+
rev: v0.19.0
|
|
390
441
|
hooks:
|
|
391
442
|
- id: commit-guard
|
|
392
443
|
- id: commit-guard-signature
|
|
@@ -49,6 +49,9 @@ inputs:
|
|
|
49
49
|
description: Include merge commits when checking a range
|
|
50
50
|
required: false
|
|
51
51
|
default: 'false'
|
|
52
|
+
require-subject-pattern:
|
|
53
|
+
description: Regex the subject line must match (e.g. '[A-Z]+-[0-9]+')
|
|
54
|
+
required: false
|
|
52
55
|
require-trailer:
|
|
53
56
|
description: Comma-separated list of required trailers (e.g. Closes,Reviewed-by)
|
|
54
57
|
required: false
|
|
@@ -86,6 +89,7 @@ runs:
|
|
|
86
89
|
CG_NO_TRAILING_CHARS: ${{ inputs.no-trailing-chars }}
|
|
87
90
|
CG_ALLOW_EMPTY: ${{ inputs.allow-empty }}
|
|
88
91
|
CG_INCLUDE_MERGES: ${{ inputs.include-merges }}
|
|
92
|
+
CG_REQUIRE_SUBJECT_PATTERN: ${{ inputs.require-subject-pattern }}
|
|
89
93
|
CG_REQUIRE_TRAILER: ${{ inputs.require-trailer }}
|
|
90
94
|
CG_OUTPUT_FILE: ${{ inputs.output-file }}
|
|
91
95
|
run: |
|
|
@@ -105,6 +109,8 @@ runs:
|
|
|
105
109
|
[[ -n "$CG_NO_TRAILING_CHARS" ]] && ARGS+=(--no-trailing-chars "$CG_NO_TRAILING_CHARS")
|
|
106
110
|
[[ "$CG_ALLOW_EMPTY" == "true" ]] && ARGS+=(--allow-empty)
|
|
107
111
|
[[ "$CG_INCLUDE_MERGES" == "true" ]] && ARGS+=(--include-merges)
|
|
112
|
+
[[ -n "$CG_REQUIRE_SUBJECT_PATTERN" ]] && \
|
|
113
|
+
ARGS+=(--require-subject-pattern "$CG_REQUIRE_SUBJECT_PATTERN")
|
|
108
114
|
[[ -n "$CG_REQUIRE_TRAILER" ]] && ARGS+=(--require-trailer "$CG_REQUIRE_TRAILER")
|
|
109
115
|
[[ -n "$CG_OUTPUT_FILE" ]] && ARGS+=(--output-file "$CG_OUTPUT_FILE")
|
|
110
116
|
commit-guard "${ARGS[@]}"
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
[changelog]
|
|
2
|
+
body = """
|
|
3
|
+
{% if version %}\
|
|
4
|
+
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
|
|
5
|
+
{% else %}\
|
|
6
|
+
## [unreleased]
|
|
7
|
+
{% endif %}\
|
|
8
|
+
{% for group, commits in commits | group_by(attribute="group") %}
|
|
9
|
+
### {{ group | striptags | trim | upper_first }}
|
|
10
|
+
{% for commit in commits %}
|
|
11
|
+
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
|
|
12
|
+
{% if commit.breaking %}[**breaking**] {% endif %}\
|
|
13
|
+
{{ commit.message | upper_first }} \
|
|
14
|
+
([`{{ commit.id | truncate(length=7, end="") }}`]\
|
|
15
|
+
(https://github.com/benner/commit-guard/commit/{{ commit.id }}))\
|
|
16
|
+
{% endfor %}
|
|
17
|
+
{% endfor %}
|
|
18
|
+
{%- if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
|
|
19
|
+
|
|
20
|
+
### New Contributors
|
|
21
|
+
{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}
|
|
22
|
+
- @{{ contributor.username }} made their first contribution\
|
|
23
|
+
{% if contributor.pr_number %} in \
|
|
24
|
+
[#{{ contributor.pr_number }}]\
|
|
25
|
+
(https://github.com/benner/commit-guard/pull/{{ contributor.pr_number }})\
|
|
26
|
+
{% endif %}
|
|
27
|
+
{% endfor %}
|
|
28
|
+
{%- endif %}
|
|
29
|
+
"""
|
|
30
|
+
trim = true
|
|
31
|
+
|
|
32
|
+
[remote.github]
|
|
33
|
+
owner = "benner"
|
|
34
|
+
repo = "commit-guard"
|
|
35
|
+
|
|
36
|
+
[git]
|
|
37
|
+
conventional_commits = true
|
|
38
|
+
filter_unconventional = true
|
|
39
|
+
split_commits = false
|
|
40
|
+
protect_breaking_commits = false
|
|
41
|
+
commit_parsers = [
|
|
42
|
+
{ message = "^feat", group = "<!-- 0 -->🚀 Features" },
|
|
43
|
+
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
|
|
44
|
+
{ message = "^perf", group = "<!-- 2 -->⚡ Performance" },
|
|
45
|
+
{ message = "^refactor", group = "<!-- 3 -->🚜 Refactor" },
|
|
46
|
+
{ message = "^style", group = "<!-- 4 -->🎨 Styling" },
|
|
47
|
+
{ message = "^test", group = "<!-- 5 -->🧪 Testing" },
|
|
48
|
+
{ message = "^docs", skip = true },
|
|
49
|
+
{ message = "^ci", skip = true },
|
|
50
|
+
{ message = "^chore", group = "<!-- 6 -->⚙️ Miscellaneous Tasks" },
|
|
51
|
+
{ message = "^revert", group = "<!-- 7 -->◀️ Revert" },
|
|
52
|
+
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
|
|
53
|
+
]
|
|
54
|
+
filter_commits = true
|
|
55
|
+
topo_order = false
|
|
56
|
+
sort_commits = "oldest"
|
|
@@ -377,7 +377,7 @@ $ echo "fix(auth): add token refresh" | commit-guard</code></pre>
|
|
|
377
377
|
</tr>
|
|
378
378
|
<tr>
|
|
379
379
|
<td><code>signature</code></td>
|
|
380
|
-
<td>GPG or SSH signature is valid</td>
|
|
380
|
+
<td>GPG or SSH signature is valid — verified via GitHub Commits API or public key lookup</td>
|
|
381
381
|
</tr>
|
|
382
382
|
</tbody>
|
|
383
383
|
</table>
|
|
@@ -400,7 +400,23 @@ max-subject-length = 100
|
|
|
400
400
|
min-description-length = 10
|
|
401
401
|
require-lowercase = false
|
|
402
402
|
no-trailing-chars = [".", "!"]
|
|
403
|
-
require-trailers = ["Closes", "Reviewed-by"]
|
|
403
|
+
require-trailers = ["Closes", "Reviewed-by"]
|
|
404
|
+
require-subject-pattern = "[A-Z]+-[0-9]+"</code></pre>
|
|
405
|
+
|
|
406
|
+
<h3>Required subject pattern</h3>
|
|
407
|
+
<p>
|
|
408
|
+
Require the commit subject to match a regular expression. Useful for
|
|
409
|
+
enforcing ticket references or any custom naming convention:
|
|
410
|
+
</p>
|
|
411
|
+
<pre><code class="language-bash">commit-guard --require-subject-pattern "[A-Z]+-[0-9]+"</code></pre>
|
|
412
|
+
<p>
|
|
413
|
+
In <code>.commit-guard.toml</code>:
|
|
414
|
+
</p>
|
|
415
|
+
<pre><code class="language-toml">require-subject-pattern = "[A-Z]+-[0-9]+"</code></pre>
|
|
416
|
+
<p>
|
|
417
|
+
An invalid regex causes an immediate error at startup (exit 2). This
|
|
418
|
+
check runs independently of <code>--enable</code>/<code>--disable</code>.
|
|
419
|
+
</p>
|
|
404
420
|
|
|
405
421
|
<h3>Required trailers</h3>
|
|
406
422
|
<p>
|
|
@@ -410,6 +426,39 @@ require-trailers = ["Closes", "Reviewed-by"]</code></pre>
|
|
|
410
426
|
</p>
|
|
411
427
|
<pre><code class="language-bash">commit-guard --require-trailer "Closes,Reviewed-by"</code></pre>
|
|
412
428
|
|
|
429
|
+
<h3>Signature verification</h3>
|
|
430
|
+
<p>
|
|
431
|
+
The <code>signature</code> check verifies commits without requiring a
|
|
432
|
+
pre-configured local keyring:
|
|
433
|
+
</p>
|
|
434
|
+
<ol>
|
|
435
|
+
<li>If the repo has a GitHub remote, call the Commits API
|
|
436
|
+
(<code>GET /repos/{owner}/{repo}/commits/{sha}</code>) to resolve
|
|
437
|
+
the author's GitHub username — works for corporate emails, noreply
|
|
438
|
+
addresses, or any email not listed publicly on a GitHub profile.</li>
|
|
439
|
+
<li>If the Commits API is unavailable (no GitHub remote, commit not
|
|
440
|
+
yet pushed, or API error), parse the username directly from a
|
|
441
|
+
GitHub noreply address
|
|
442
|
+
(<code>{id}+{username}@users.noreply.github.com</code>) — no API
|
|
443
|
+
call needed.</li>
|
|
444
|
+
<li>If neither of the above resolves a username, fall back to
|
|
445
|
+
searching GitHub by the commit author's email.</li>
|
|
446
|
+
<li>Fetch the resolved user's public keys from
|
|
447
|
+
<code>github.com/{username}.gpg</code> and
|
|
448
|
+
<code>github.com/{username}.keys</code>.</li>
|
|
449
|
+
<li>Try GPG verification using a temporary keyring.</li>
|
|
450
|
+
<li>Try SSH verification using a temporary <code>allowed_signers</code> file.</li>
|
|
451
|
+
<li>Pass if any key verifies; fail if none do.</li>
|
|
452
|
+
</ol>
|
|
453
|
+
<p>
|
|
454
|
+
If the author cannot be resolved via either method, or the GitHub API
|
|
455
|
+
is unreachable, the check fails with a clear error. For private
|
|
456
|
+
repositories, set <code>GITHUB_TOKEN</code> or <code>GH_TOKEN</code>
|
|
457
|
+
so the Commits API can authenticate. Disable the
|
|
458
|
+
<code>signature</code> check if GitHub API access is unavailable:
|
|
459
|
+
</p>
|
|
460
|
+
<pre><code class="language-bash">commit-guard --disable signature</code></pre>
|
|
461
|
+
|
|
413
462
|
<h3>Range options</h3>
|
|
414
463
|
<p>
|
|
415
464
|
When using <code>--range</code>, merge commits are excluded by
|
|
@@ -435,6 +484,16 @@ require-trailers = ["Closes", "Reviewed-by"]</code></pre>
|
|
|
435
484
|
<td><code>10</code></td>
|
|
436
485
|
<td>Timeout in seconds for git subprocess calls</td>
|
|
437
486
|
</tr>
|
|
487
|
+
<tr>
|
|
488
|
+
<td><code>GITHUB_TOKEN</code></td>
|
|
489
|
+
<td>—</td>
|
|
490
|
+
<td>GitHub token for Commits API access on private repos (signature check)</td>
|
|
491
|
+
</tr>
|
|
492
|
+
<tr>
|
|
493
|
+
<td><code>GH_TOKEN</code></td>
|
|
494
|
+
<td>—</td>
|
|
495
|
+
<td>Alias for <code>GITHUB_TOKEN</code>; used when <code>GITHUB_TOKEN</code> is not set</td>
|
|
496
|
+
</tr>
|
|
438
497
|
</tbody>
|
|
439
498
|
</table>
|
|
440
499
|
</figure>
|
|
@@ -479,13 +538,13 @@ require-trailers = ["Closes", "Reviewed-by"]</code></pre>
|
|
|
479
538
|
- uses: actions/checkout@v4
|
|
480
539
|
with:
|
|
481
540
|
fetch-depth: 0
|
|
482
|
-
- uses: benner/commit-guard@v0.
|
|
541
|
+
- uses: benner/commit-guard@v0.19.0
|
|
483
542
|
with:
|
|
484
543
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
485
544
|
disable: signed-off,signature</code></pre>
|
|
486
545
|
|
|
487
546
|
<p>Check a specific commit SHA:</p>
|
|
488
|
-
<pre><code class="language-yaml"> - uses: benner/commit-guard@v0.
|
|
547
|
+
<pre><code class="language-yaml"> - uses: benner/commit-guard@v0.19.0
|
|
489
548
|
with:
|
|
490
549
|
rev: ${{ github.sha }}</code></pre>
|
|
491
550
|
|
|
@@ -504,7 +563,7 @@ require-trailers = ["Closes", "Reviewed-by"]</code></pre>
|
|
|
504
563
|
When <code>output-file</code> is set the action exposes the path as
|
|
505
564
|
a step output, making JSONL results available to subsequent steps:
|
|
506
565
|
</p>
|
|
507
|
-
<pre><code class="language-yaml"> - uses: benner/commit-guard@v0.
|
|
566
|
+
<pre><code class="language-yaml"> - uses: benner/commit-guard@v0.19.0
|
|
508
567
|
id: cg
|
|
509
568
|
with:
|
|
510
569
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
@@ -517,7 +576,7 @@ require-trailers = ["Closes", "Reviewed-by"]</code></pre>
|
|
|
517
576
|
<p>Add to <code>.pre-commit-config.yaml</code>:</p>
|
|
518
577
|
<pre><code class="language-yaml">repos:
|
|
519
578
|
- repo: https://github.com/benner/commit-guard
|
|
520
|
-
rev: v0.
|
|
579
|
+
rev: v0.19.0
|
|
521
580
|
hooks:
|
|
522
581
|
- id: commit-guard
|
|
523
582
|
- id: commit-guard-signature</code></pre>
|