git-commit-guard 0.22.1__tar.gz → 0.22.3__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.22.1 → git_commit_guard-0.22.3}/.github/workflows/coverage-baseline.yml +2 -2
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/.github/workflows/coverage-comment.yml +2 -2
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/.github/workflows/lint-commits.yml +1 -1
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/.github/workflows/lint-md.yml +1 -1
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/.github/workflows/lint-workflows.yml +2 -2
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/.github/workflows/release.yml +1 -1
- git_commit_guard-0.22.3/.github/workflows/security-audit.yml +24 -0
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/.github/workflows/test.yml +2 -2
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/PKG-INFO +13 -13
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/README.md +11 -11
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/docs/index.html +8 -8
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/pyproject.toml +2 -2
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/src/git_commit_guard/__init__.py +11 -11
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/tests/test_git_commit_guard.py +63 -48
- git_commit_guard-0.22.3/uv.lock +320 -0
- git_commit_guard-0.22.1/uv.lock +0 -320
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/.editorconfig +0 -0
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/.github/workflows/lint-python.yml +0 -0
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/.gitignore +0 -0
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/.markdownlint.json +0 -0
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/.pre-commit-hooks.yaml +0 -0
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/.python-version +0 -0
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/LICENSE +0 -0
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/action.yml +0 -0
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/cliff.toml +0 -0
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/docs/commit-guard-icon.svg +0 -0
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/ruff.toml +0 -0
- {git_commit_guard-0.22.1 → git_commit_guard-0.22.3}/tests/__init__.py +0 -0
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
persist-credentials: false
|
|
17
17
|
- name: Install uv
|
|
18
18
|
# yamllint disable-line rule:line-length
|
|
19
|
-
uses: astral-sh/setup-uv@
|
|
19
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # ratchet:astral-sh/setup-uv@v8.2.0
|
|
20
20
|
- name: Cache NLTK data
|
|
21
21
|
# yamllint disable-line rule:line-length
|
|
22
22
|
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
run: uv run --dev pytest tests/ --cov=git_commit_guard --cov-report=xml
|
|
28
28
|
- name: Upload coverage baseline
|
|
29
29
|
# yamllint disable-line rule:line-length
|
|
30
|
-
uses: actions/upload-artifact@
|
|
30
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # ratchet:actions/upload-artifact@v7
|
|
31
31
|
with:
|
|
32
32
|
name: main-coverage
|
|
33
33
|
path: coverage.xml
|
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
steps:
|
|
17
17
|
- name: Download artifact
|
|
18
18
|
# yamllint disable-line rule:line-length
|
|
19
|
-
uses: actions/download-artifact@
|
|
19
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # ratchet:actions/download-artifact@v8
|
|
20
20
|
with:
|
|
21
21
|
run-id: ${{ github.event.workflow_run.id }}
|
|
22
22
|
name: pr
|
|
@@ -57,7 +57,7 @@ jobs:
|
|
|
57
57
|
- name: Download baseline coverage
|
|
58
58
|
if: steps.baseline.outputs.run-id != ''
|
|
59
59
|
# yamllint disable-line rule:line-length
|
|
60
|
-
uses: actions/download-artifact@
|
|
60
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # ratchet:actions/download-artifact@v8
|
|
61
61
|
with:
|
|
62
62
|
run-id: ${{ steps.baseline.outputs.run-id }}
|
|
63
63
|
name: main-coverage
|
|
@@ -22,6 +22,6 @@ 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@e156ca25789cc1824f745d74209f9c2654135dca # v0.22.2
|
|
26
26
|
with:
|
|
27
27
|
range: origin/${{ github.base_ref }}..HEAD
|
|
@@ -37,7 +37,7 @@ jobs:
|
|
|
37
37
|
persist-credentials: false
|
|
38
38
|
- name: Set up uv
|
|
39
39
|
# yamllint disable-line rule:line-length
|
|
40
|
-
uses: astral-sh/setup-uv@
|
|
40
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
41
41
|
with:
|
|
42
42
|
enable-cache: false
|
|
43
43
|
- name: Set up reviewdog
|
|
@@ -34,7 +34,7 @@ jobs:
|
|
|
34
34
|
persist-credentials: false
|
|
35
35
|
- name: Set up uv
|
|
36
36
|
# yamllint disable-line rule:line-length
|
|
37
|
-
uses: astral-sh/setup-uv@
|
|
37
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # ratchet:astral-sh/setup-uv@v8.2.0
|
|
38
38
|
- name: Set up reviewdog
|
|
39
39
|
# yamllint disable-line rule:line-length
|
|
40
40
|
uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # ratchet:reviewdog/action-setup@v1
|
|
@@ -59,7 +59,7 @@ jobs:
|
|
|
59
59
|
persist-credentials: false
|
|
60
60
|
- name: Set up uv
|
|
61
61
|
# yamllint disable-line rule:line-length
|
|
62
|
-
uses: astral-sh/setup-uv@
|
|
62
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # ratchet:astral-sh/setup-uv@v8.2.0
|
|
63
63
|
- name: Set up reviewdog
|
|
64
64
|
# yamllint disable-line rule:line-length
|
|
65
65
|
uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # ratchet:reviewdog/action-setup@v1
|
|
@@ -20,7 +20,7 @@ jobs:
|
|
|
20
20
|
fetch-depth: 0
|
|
21
21
|
- name: Set up uv
|
|
22
22
|
# yamllint disable-line rule:line-length
|
|
23
|
-
uses: astral-sh/setup-uv@
|
|
23
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
24
24
|
with:
|
|
25
25
|
enable-cache: false
|
|
26
26
|
- name: Build package
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Security Audit
|
|
3
|
+
on: # yamllint disable-line rule:truthy
|
|
4
|
+
pull_request:
|
|
5
|
+
schedule:
|
|
6
|
+
- cron: 13 3 * * 2
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
jobs:
|
|
10
|
+
audit:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- name: Checkout code
|
|
14
|
+
# yamllint disable-line rule:line-length
|
|
15
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
16
|
+
with:
|
|
17
|
+
persist-credentials: false
|
|
18
|
+
- name: Install uv
|
|
19
|
+
# yamllint disable-line rule:line-length
|
|
20
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
21
|
+
- name: Audit dependencies
|
|
22
|
+
run: >-
|
|
23
|
+
uv audit --frozen --preview-features audit-command
|
|
24
|
+
--ignore-until-fixed GHSA-p4gq-832x-fm9v
|
|
@@ -15,7 +15,7 @@ jobs:
|
|
|
15
15
|
persist-credentials: false
|
|
16
16
|
- name: Install uv
|
|
17
17
|
# yamllint disable-line rule:line-length
|
|
18
|
-
uses: astral-sh/setup-uv@
|
|
18
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
19
19
|
- name: Cache NLTK data
|
|
20
20
|
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
|
21
21
|
with:
|
|
@@ -35,7 +35,7 @@ jobs:
|
|
|
35
35
|
cp coverage.xml ./pr/
|
|
36
36
|
- name: Upload PR artifact
|
|
37
37
|
# yamllint disable-line rule:line-length
|
|
38
|
-
uses: actions/upload-artifact@
|
|
38
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # ratchet:actions/upload-artifact@v7
|
|
39
39
|
with:
|
|
40
40
|
name: pr
|
|
41
41
|
path: pr/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: git-commit-guard
|
|
3
|
-
Version: 0.22.
|
|
3
|
+
Version: 0.22.3
|
|
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
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
16
16
|
Classifier: Topic :: Software Development :: Quality Assurance
|
|
17
17
|
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
18
18
|
Requires-Python: >=3.12
|
|
19
|
-
Requires-Dist: nltk>=3.9.
|
|
19
|
+
Requires-Dist: nltk>=3.9.4
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
|
|
22
22
|
# commit-guard
|
|
@@ -36,7 +36,7 @@ Opinionated conventional commit message linter with imperative mood detection.
|
|
|
36
36
|
verb, verified via nltk POS tagging — not a hand-coded regex of "bad"
|
|
37
37
|
words.
|
|
38
38
|
* **Signature verification without a local keyring.** Resolves the commit
|
|
39
|
-
|
|
39
|
+
committer via the GitHub API and verifies GPG/SSH against their published
|
|
40
40
|
`.gpg`/`.keys` — no per-runner key management.
|
|
41
41
|
* **Strict by default.** Subject format, body, trailers, `Signed-off-by`,
|
|
42
42
|
and signature all enforced out of the box; opt out with `--disable`.
|
|
@@ -242,7 +242,7 @@ independently of `--enable`/`--disable`.
|
|
|
242
242
|
The `signature` check verifies the commit without any local keyring setup:
|
|
243
243
|
|
|
244
244
|
1. If the repo has a GitHub remote, call the Commits API
|
|
245
|
-
(`GET /repos/{owner}/{repo}/commits/{sha}`) to resolve the
|
|
245
|
+
(`GET /repos/{owner}/{repo}/commits/{sha}`) to resolve the committer's GitHub
|
|
246
246
|
username — this works for corporate emails, noreply addresses, or any email
|
|
247
247
|
not listed publicly on a GitHub profile.
|
|
248
248
|
2. If the Commits API is unavailable (no GitHub remote, commit not yet pushed,
|
|
@@ -250,7 +250,7 @@ The `signature` check verifies the commit without any local keyring setup:
|
|
|
250
250
|
(`{id}+{username}@users.noreply.github.com` or
|
|
251
251
|
`{username}@users.noreply.github.com`) — no API call needed.
|
|
252
252
|
3. If neither of the above resolves a username, fall back to searching GitHub
|
|
253
|
-
by the commit
|
|
253
|
+
by the commit committer's email.
|
|
254
254
|
4. Fetch the resolved user's public keys from `github.com/{username}.gpg`
|
|
255
255
|
(GPG) and the `/users/{username}/ssh_signing_keys` API (SSH keys tagged
|
|
256
256
|
with the **Signing key** role). Auth-only SSH keys are deliberately not
|
|
@@ -261,7 +261,7 @@ The `signature` check verifies the commit without any local keyring setup:
|
|
|
261
261
|
`git verify-commit` with the SSH allowed-signers config.
|
|
262
262
|
7. If any key verifies, the check passes. If none do, it fails.
|
|
263
263
|
|
|
264
|
-
If the
|
|
264
|
+
If the committer cannot be resolved via either method, or the GitHub API is
|
|
265
265
|
unreachable, the check fails with a clear error.
|
|
266
266
|
|
|
267
267
|
For private repositories, set `GITHUB_TOKEN` or `GH_TOKEN` so the Commits API
|
|
@@ -316,7 +316,7 @@ COMMIT_GUARD_GIT_TIMEOUT=30 commit-guard --range origin/main..HEAD
|
|
|
316
316
|
In GitHub Actions, set it at the step or job level:
|
|
317
317
|
|
|
318
318
|
```yaml
|
|
319
|
-
- uses: benner/commit-guard@v0.22.
|
|
319
|
+
- uses: benner/commit-guard@v0.22.3
|
|
320
320
|
env:
|
|
321
321
|
COMMIT_GUARD_GIT_TIMEOUT: 30
|
|
322
322
|
with:
|
|
@@ -400,7 +400,7 @@ steps:
|
|
|
400
400
|
- uses: actions/checkout@v4
|
|
401
401
|
with:
|
|
402
402
|
fetch-depth: 0
|
|
403
|
-
- uses: benner/commit-guard@v0.22.
|
|
403
|
+
- uses: benner/commit-guard@v0.22.3
|
|
404
404
|
```
|
|
405
405
|
|
|
406
406
|
Check all commits in a pull request:
|
|
@@ -416,7 +416,7 @@ jobs:
|
|
|
416
416
|
- uses: actions/checkout@v4
|
|
417
417
|
with:
|
|
418
418
|
fetch-depth: 0
|
|
419
|
-
- uses: benner/commit-guard@v0.22.
|
|
419
|
+
- uses: benner/commit-guard@v0.22.3
|
|
420
420
|
with:
|
|
421
421
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
422
422
|
```
|
|
@@ -424,7 +424,7 @@ jobs:
|
|
|
424
424
|
Check a specific commit SHA (mirrors the positional CLI argument):
|
|
425
425
|
|
|
426
426
|
```yaml
|
|
427
|
-
- uses: benner/commit-guard@v0.22.
|
|
427
|
+
- uses: benner/commit-guard@v0.22.3
|
|
428
428
|
with:
|
|
429
429
|
rev: ${{ github.sha }}
|
|
430
430
|
```
|
|
@@ -442,7 +442,7 @@ jobs:
|
|
|
442
442
|
- uses: actions/checkout@v4
|
|
443
443
|
with:
|
|
444
444
|
fetch-depth: 0
|
|
445
|
-
- uses: benner/commit-guard@v0.22.
|
|
445
|
+
- uses: benner/commit-guard@v0.22.3
|
|
446
446
|
with:
|
|
447
447
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
448
448
|
disable: signed-off,signature
|
|
@@ -462,7 +462,7 @@ jobs:
|
|
|
462
462
|
When `output-file` is set the action exposes the path as an output:
|
|
463
463
|
|
|
464
464
|
```yaml
|
|
465
|
-
- uses: benner/commit-guard@v0.22.
|
|
465
|
+
- uses: benner/commit-guard@v0.22.3
|
|
466
466
|
id: cg
|
|
467
467
|
with:
|
|
468
468
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
@@ -478,7 +478,7 @@ Add to your `.pre-commit-config.yaml`:
|
|
|
478
478
|
---
|
|
479
479
|
repos:
|
|
480
480
|
- repo: https://github.com/benner/commit-guard
|
|
481
|
-
rev: v0.22.
|
|
481
|
+
rev: v0.22.3
|
|
482
482
|
hooks:
|
|
483
483
|
- id: commit-guard
|
|
484
484
|
- id: commit-guard-signature
|
|
@@ -15,7 +15,7 @@ Opinionated conventional commit message linter with imperative mood detection.
|
|
|
15
15
|
verb, verified via nltk POS tagging — not a hand-coded regex of "bad"
|
|
16
16
|
words.
|
|
17
17
|
* **Signature verification without a local keyring.** Resolves the commit
|
|
18
|
-
|
|
18
|
+
committer via the GitHub API and verifies GPG/SSH against their published
|
|
19
19
|
`.gpg`/`.keys` — no per-runner key management.
|
|
20
20
|
* **Strict by default.** Subject format, body, trailers, `Signed-off-by`,
|
|
21
21
|
and signature all enforced out of the box; opt out with `--disable`.
|
|
@@ -221,7 +221,7 @@ independently of `--enable`/`--disable`.
|
|
|
221
221
|
The `signature` check verifies the commit without any local keyring setup:
|
|
222
222
|
|
|
223
223
|
1. If the repo has a GitHub remote, call the Commits API
|
|
224
|
-
(`GET /repos/{owner}/{repo}/commits/{sha}`) to resolve the
|
|
224
|
+
(`GET /repos/{owner}/{repo}/commits/{sha}`) to resolve the committer's GitHub
|
|
225
225
|
username — this works for corporate emails, noreply addresses, or any email
|
|
226
226
|
not listed publicly on a GitHub profile.
|
|
227
227
|
2. If the Commits API is unavailable (no GitHub remote, commit not yet pushed,
|
|
@@ -229,7 +229,7 @@ The `signature` check verifies the commit without any local keyring setup:
|
|
|
229
229
|
(`{id}+{username}@users.noreply.github.com` or
|
|
230
230
|
`{username}@users.noreply.github.com`) — no API call needed.
|
|
231
231
|
3. If neither of the above resolves a username, fall back to searching GitHub
|
|
232
|
-
by the commit
|
|
232
|
+
by the commit committer's email.
|
|
233
233
|
4. Fetch the resolved user's public keys from `github.com/{username}.gpg`
|
|
234
234
|
(GPG) and the `/users/{username}/ssh_signing_keys` API (SSH keys tagged
|
|
235
235
|
with the **Signing key** role). Auth-only SSH keys are deliberately not
|
|
@@ -240,7 +240,7 @@ The `signature` check verifies the commit without any local keyring setup:
|
|
|
240
240
|
`git verify-commit` with the SSH allowed-signers config.
|
|
241
241
|
7. If any key verifies, the check passes. If none do, it fails.
|
|
242
242
|
|
|
243
|
-
If the
|
|
243
|
+
If the committer cannot be resolved via either method, or the GitHub API is
|
|
244
244
|
unreachable, the check fails with a clear error.
|
|
245
245
|
|
|
246
246
|
For private repositories, set `GITHUB_TOKEN` or `GH_TOKEN` so the Commits API
|
|
@@ -295,7 +295,7 @@ COMMIT_GUARD_GIT_TIMEOUT=30 commit-guard --range origin/main..HEAD
|
|
|
295
295
|
In GitHub Actions, set it at the step or job level:
|
|
296
296
|
|
|
297
297
|
```yaml
|
|
298
|
-
- uses: benner/commit-guard@v0.22.
|
|
298
|
+
- uses: benner/commit-guard@v0.22.3
|
|
299
299
|
env:
|
|
300
300
|
COMMIT_GUARD_GIT_TIMEOUT: 30
|
|
301
301
|
with:
|
|
@@ -379,7 +379,7 @@ steps:
|
|
|
379
379
|
- uses: actions/checkout@v4
|
|
380
380
|
with:
|
|
381
381
|
fetch-depth: 0
|
|
382
|
-
- uses: benner/commit-guard@v0.22.
|
|
382
|
+
- uses: benner/commit-guard@v0.22.3
|
|
383
383
|
```
|
|
384
384
|
|
|
385
385
|
Check all commits in a pull request:
|
|
@@ -395,7 +395,7 @@ jobs:
|
|
|
395
395
|
- uses: actions/checkout@v4
|
|
396
396
|
with:
|
|
397
397
|
fetch-depth: 0
|
|
398
|
-
- uses: benner/commit-guard@v0.22.
|
|
398
|
+
- uses: benner/commit-guard@v0.22.3
|
|
399
399
|
with:
|
|
400
400
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
401
401
|
```
|
|
@@ -403,7 +403,7 @@ jobs:
|
|
|
403
403
|
Check a specific commit SHA (mirrors the positional CLI argument):
|
|
404
404
|
|
|
405
405
|
```yaml
|
|
406
|
-
- uses: benner/commit-guard@v0.22.
|
|
406
|
+
- uses: benner/commit-guard@v0.22.3
|
|
407
407
|
with:
|
|
408
408
|
rev: ${{ github.sha }}
|
|
409
409
|
```
|
|
@@ -421,7 +421,7 @@ jobs:
|
|
|
421
421
|
- uses: actions/checkout@v4
|
|
422
422
|
with:
|
|
423
423
|
fetch-depth: 0
|
|
424
|
-
- uses: benner/commit-guard@v0.22.
|
|
424
|
+
- uses: benner/commit-guard@v0.22.3
|
|
425
425
|
with:
|
|
426
426
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
427
427
|
disable: signed-off,signature
|
|
@@ -441,7 +441,7 @@ jobs:
|
|
|
441
441
|
When `output-file` is set the action exposes the path as an output:
|
|
442
442
|
|
|
443
443
|
```yaml
|
|
444
|
-
- uses: benner/commit-guard@v0.22.
|
|
444
|
+
- uses: benner/commit-guard@v0.22.3
|
|
445
445
|
id: cg
|
|
446
446
|
with:
|
|
447
447
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
@@ -457,7 +457,7 @@ Add to your `.pre-commit-config.yaml`:
|
|
|
457
457
|
---
|
|
458
458
|
repos:
|
|
459
459
|
- repo: https://github.com/benner/commit-guard
|
|
460
|
-
rev: v0.22.
|
|
460
|
+
rev: v0.22.3
|
|
461
461
|
hooks:
|
|
462
462
|
- id: commit-guard
|
|
463
463
|
- id: commit-guard-signature
|
|
@@ -315,7 +315,7 @@
|
|
|
315
315
|
</li>
|
|
316
316
|
<li>
|
|
317
317
|
<strong>Signature verification without a local keyring.</strong>
|
|
318
|
-
Resolves the commit
|
|
318
|
+
Resolves the commit committer via the GitHub API and verifies GPG/SSH
|
|
319
319
|
against their published <code>.gpg</code>/<code>.keys</code> — no
|
|
320
320
|
per-runner key management.
|
|
321
321
|
</li>
|
|
@@ -456,7 +456,7 @@ require-subject-pattern = "[A-Z]+-[0-9]+"</code></pre>
|
|
|
456
456
|
<ol>
|
|
457
457
|
<li>If the repo has a GitHub remote, call the Commits API
|
|
458
458
|
(<code>GET /repos/{owner}/{repo}/commits/{sha}</code>) to resolve
|
|
459
|
-
the
|
|
459
|
+
the committer's GitHub username — works for corporate emails, noreply
|
|
460
460
|
addresses, or any email not listed publicly on a GitHub profile.</li>
|
|
461
461
|
<li>If the Commits API is unavailable (no GitHub remote, commit not
|
|
462
462
|
yet pushed, or API error), parse the username directly from a
|
|
@@ -464,7 +464,7 @@ require-subject-pattern = "[A-Z]+-[0-9]+"</code></pre>
|
|
|
464
464
|
(<code>{id}+{username}@users.noreply.github.com</code>) — no API
|
|
465
465
|
call needed.</li>
|
|
466
466
|
<li>If neither of the above resolves a username, fall back to
|
|
467
|
-
searching GitHub by the commit
|
|
467
|
+
searching GitHub by the commit committer's email.</li>
|
|
468
468
|
<li>Fetch the resolved user's public keys from
|
|
469
469
|
<code>github.com/{username}.gpg</code> (GPG) and
|
|
470
470
|
<code>/users/{username}/ssh_signing_keys</code> (SSH keys tagged
|
|
@@ -476,7 +476,7 @@ require-subject-pattern = "[A-Z]+-[0-9]+"</code></pre>
|
|
|
476
476
|
<li>Pass if any key verifies; fail if none do.</li>
|
|
477
477
|
</ol>
|
|
478
478
|
<p>
|
|
479
|
-
If the
|
|
479
|
+
If the committer cannot be resolved via either method, or the GitHub API
|
|
480
480
|
is unreachable, the check fails with a clear error. For private
|
|
481
481
|
repositories, set <code>GITHUB_TOKEN</code> or <code>GH_TOKEN</code>
|
|
482
482
|
so the Commits API can authenticate. The official GitHub Action wires
|
|
@@ -566,13 +566,13 @@ require-subject-pattern = "[A-Z]+-[0-9]+"</code></pre>
|
|
|
566
566
|
- uses: actions/checkout@v4
|
|
567
567
|
with:
|
|
568
568
|
fetch-depth: 0
|
|
569
|
-
- uses: benner/commit-guard@v0.22.
|
|
569
|
+
- uses: benner/commit-guard@v0.22.3
|
|
570
570
|
with:
|
|
571
571
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
572
572
|
disable: signed-off,signature</code></pre>
|
|
573
573
|
|
|
574
574
|
<p>Check a specific commit SHA:</p>
|
|
575
|
-
<pre><code class="language-yaml"> - uses: benner/commit-guard@v0.22.
|
|
575
|
+
<pre><code class="language-yaml"> - uses: benner/commit-guard@v0.22.3
|
|
576
576
|
with:
|
|
577
577
|
rev: ${{ github.sha }}</code></pre>
|
|
578
578
|
|
|
@@ -591,7 +591,7 @@ require-subject-pattern = "[A-Z]+-[0-9]+"</code></pre>
|
|
|
591
591
|
When <code>output-file</code> is set the action exposes the path as
|
|
592
592
|
a step output, making JSONL results available to subsequent steps:
|
|
593
593
|
</p>
|
|
594
|
-
<pre><code class="language-yaml"> - uses: benner/commit-guard@v0.22.
|
|
594
|
+
<pre><code class="language-yaml"> - uses: benner/commit-guard@v0.22.3
|
|
595
595
|
id: cg
|
|
596
596
|
with:
|
|
597
597
|
range: ${{ env.PR_BASE }}..${{ env.PR_HEAD }}
|
|
@@ -604,7 +604,7 @@ require-subject-pattern = "[A-Z]+-[0-9]+"</code></pre>
|
|
|
604
604
|
<p>Add to <code>.pre-commit-config.yaml</code>:</p>
|
|
605
605
|
<pre><code class="language-yaml">repos:
|
|
606
606
|
- repo: https://github.com/benner/commit-guard
|
|
607
|
-
rev: v0.22.
|
|
607
|
+
rev: v0.22.3
|
|
608
608
|
hooks:
|
|
609
609
|
- id: commit-guard
|
|
610
610
|
- id: commit-guard-signature</code></pre>
|
|
@@ -16,7 +16,7 @@ classifiers = [
|
|
|
16
16
|
"Topic :: Software Development :: Version Control :: Git",
|
|
17
17
|
]
|
|
18
18
|
dependencies = [
|
|
19
|
-
"nltk>=3.9.
|
|
19
|
+
"nltk>=3.9.4",
|
|
20
20
|
]
|
|
21
21
|
|
|
22
22
|
[project.scripts]
|
|
@@ -36,6 +36,6 @@ source = "vcs"
|
|
|
36
36
|
|
|
37
37
|
[dependency-groups]
|
|
38
38
|
dev = [
|
|
39
|
-
"pytest>=9.0.
|
|
39
|
+
"pytest>=9.0.3",
|
|
40
40
|
"pytest-cov>=7.1.0",
|
|
41
41
|
]
|
|
@@ -295,9 +295,9 @@ def check_required_trailers(message, required, result):
|
|
|
295
295
|
result.error(f"missing required trailer: {trailer}")
|
|
296
296
|
|
|
297
297
|
|
|
298
|
-
def
|
|
298
|
+
def _get_committer_email(rev):
|
|
299
299
|
return subprocess.check_output( # noqa: S603
|
|
300
|
-
["git", "log", "-1", "--format=%
|
|
300
|
+
["git", "log", "-1", "--format=%ce", rev], # noqa: S607
|
|
301
301
|
text=True,
|
|
302
302
|
stderr=subprocess.PIPE,
|
|
303
303
|
timeout=_git_timeout(),
|
|
@@ -320,7 +320,7 @@ def _get_github_remote_info():
|
|
|
320
320
|
return match.group("owner"), match.group("repo")
|
|
321
321
|
|
|
322
322
|
|
|
323
|
-
def
|
|
323
|
+
def _fetch_github_commit_committer(owner, repo, sha):
|
|
324
324
|
url = f"https://api.github.com/repos/{owner}/{repo}/commits/{sha}"
|
|
325
325
|
headers = {"Accept": "application/vnd.github+json"}
|
|
326
326
|
token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
|
|
@@ -329,8 +329,8 @@ def _fetch_github_commit_author(owner, repo, sha):
|
|
|
329
329
|
req = urllib.request.Request(url, headers=headers) # noqa: S310 Audit URL open for permitted schemes
|
|
330
330
|
with urllib.request.urlopen(req, timeout=_git_timeout()) as resp: # noqa: S310 Audit URL open for permitted schemes
|
|
331
331
|
data = json.loads(resp.read())
|
|
332
|
-
|
|
333
|
-
return
|
|
332
|
+
committer = data.get("committer")
|
|
333
|
+
return committer["login"] if committer else None
|
|
334
334
|
|
|
335
335
|
|
|
336
336
|
def _parse_noreply_username(email):
|
|
@@ -435,7 +435,7 @@ def _resolve_github_username(rev, email):
|
|
|
435
435
|
if remote:
|
|
436
436
|
owner, repo = remote
|
|
437
437
|
try:
|
|
438
|
-
username =
|
|
438
|
+
username = _fetch_github_commit_committer(owner, repo, rev)
|
|
439
439
|
except urllib.error.HTTPError as e:
|
|
440
440
|
if e.code == HTTPStatus.NOT_FOUND:
|
|
441
441
|
commits_api_404 = True
|
|
@@ -450,24 +450,24 @@ def _resolve_github_username(rev, email):
|
|
|
450
450
|
return username, commits_api_404
|
|
451
451
|
|
|
452
452
|
|
|
453
|
-
def
|
|
453
|
+
def _committer_not_found_message(commits_api_404):
|
|
454
454
|
had_token = bool(os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN"))
|
|
455
455
|
if commits_api_404 and not had_token:
|
|
456
456
|
return (
|
|
457
|
-
"
|
|
457
|
+
"committer not found on GitHub — if the repo is private, "
|
|
458
458
|
"set GITHUB_TOKEN in the workflow step "
|
|
459
459
|
"(env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }})"
|
|
460
460
|
)
|
|
461
|
-
return "
|
|
461
|
+
return "committer not found on GitHub — cannot verify signature"
|
|
462
462
|
|
|
463
463
|
|
|
464
464
|
def check_signature(rev, result):
|
|
465
465
|
try:
|
|
466
|
-
email =
|
|
466
|
+
email = _get_committer_email(rev)
|
|
467
467
|
username, commits_api_404 = _resolve_github_username(rev, email)
|
|
468
468
|
if username is None:
|
|
469
469
|
result.error(
|
|
470
|
-
|
|
470
|
+
_committer_not_found_message(commits_api_404),
|
|
471
471
|
check=Check.SIGNATURE,
|
|
472
472
|
)
|
|
473
473
|
return
|