git-commit-guard 0.22.0__tar.gz → 0.22.1__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.
Files changed (26) hide show
  1. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.github/workflows/lint-commits.yml +1 -1
  2. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/PKG-INFO +12 -9
  3. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/README.md +11 -8
  4. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/docs/index.html +4 -4
  5. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/src/git_commit_guard/__init__.py +16 -0
  6. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/tests/test_git_commit_guard.py +33 -0
  7. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.editorconfig +0 -0
  8. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.github/workflows/coverage-baseline.yml +0 -0
  9. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.github/workflows/coverage-comment.yml +0 -0
  10. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.github/workflows/lint-md.yml +0 -0
  11. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.github/workflows/lint-python.yml +0 -0
  12. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.github/workflows/lint-workflows.yml +0 -0
  13. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.github/workflows/release.yml +0 -0
  14. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.github/workflows/test.yml +0 -0
  15. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.gitignore +0 -0
  16. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.markdownlint.json +0 -0
  17. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.pre-commit-hooks.yaml +0 -0
  18. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/.python-version +0 -0
  19. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/LICENSE +0 -0
  20. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/action.yml +0 -0
  21. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/cliff.toml +0 -0
  22. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/docs/commit-guard-icon.svg +0 -0
  23. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/pyproject.toml +0 -0
  24. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/ruff.toml +0 -0
  25. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/tests/__init__.py +0 -0
  26. {git_commit_guard-0.22.0 → git_commit_guard-0.22.1}/uv.lock +0 -0
@@ -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@22a3b0fdb044e874250fc6525ff0905b20fa3a62 # v0.21.0
25
+ uses: benner/commit-guard@e438d8c4c287a1575e0cda352222fbbe71a88231 # v0.22.0
26
26
  with:
27
27
  range: origin/${{ github.base_ref }}..HEAD
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: git-commit-guard
3
- Version: 0.22.0
3
+ Version: 0.22.1
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
@@ -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.0
319
+ - uses: benner/commit-guard@v0.22.1
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.0
403
+ - uses: benner/commit-guard@v0.22.1
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.0
419
+ - uses: benner/commit-guard@v0.22.1
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.0
427
+ - uses: benner/commit-guard@v0.22.1
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.0
445
+ - uses: benner/commit-guard@v0.22.1
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.0
465
+ - uses: benner/commit-guard@v0.22.1
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.0
481
+ rev: v0.22.1
482
482
  hooks:
483
483
  - id: commit-guard
484
484
  - id: commit-guard-signature
@@ -503,11 +503,14 @@ To selectively enable or disable checks, pass `args`:
503
503
 
504
504
  ## Imperative mood detection
505
505
 
506
- commit-guard combines two strategies to detect non-imperative descriptions:
506
+ commit-guard combines three strategies to detect non-imperative descriptions:
507
507
 
508
508
  1. nltk POS tagging — flags words tagged as past tense (`VBD`),
509
509
  gerund (`VBG`), third person (`VBZ`), etc.
510
510
  2. WordNet morphology as a fallback for words the tagger misclassifies.
511
+ 3. Hyphenated verb prefixes — accepts `re-enable`, `auto-detect`,
512
+ `pre-process`, `co-locate`, `under-mine` and similar
513
+ `<prefix>-<verb>` compounds the POS tagger misclassifies.
511
514
 
512
515
  This catches common mistakes like `added logging` or `fixes bug` while
513
516
  keeping false positives low.
@@ -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.0
298
+ - uses: benner/commit-guard@v0.22.1
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.0
382
+ - uses: benner/commit-guard@v0.22.1
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.0
398
+ - uses: benner/commit-guard@v0.22.1
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.0
406
+ - uses: benner/commit-guard@v0.22.1
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.0
424
+ - uses: benner/commit-guard@v0.22.1
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.0
444
+ - uses: benner/commit-guard@v0.22.1
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.0
460
+ rev: v0.22.1
461
461
  hooks:
462
462
  - id: commit-guard
463
463
  - id: commit-guard-signature
@@ -482,11 +482,14 @@ To selectively enable or disable checks, pass `args`:
482
482
 
483
483
  ## Imperative mood detection
484
484
 
485
- commit-guard combines two strategies to detect non-imperative descriptions:
485
+ commit-guard combines three strategies to detect non-imperative descriptions:
486
486
 
487
487
  1. nltk POS tagging — flags words tagged as past tense (`VBD`),
488
488
  gerund (`VBG`), third person (`VBZ`), etc.
489
489
  2. WordNet morphology as a fallback for words the tagger misclassifies.
490
+ 3. Hyphenated verb prefixes — accepts `re-enable`, `auto-detect`,
491
+ `pre-process`, `co-locate`, `under-mine` and similar
492
+ `<prefix>-<verb>` compounds the POS tagger misclassifies.
490
493
 
491
494
  This catches common mistakes like `added logging` or `fixes bug` while
492
495
  keeping false positives low.
@@ -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.0
569
+ - uses: benner/commit-guard@v0.22.1
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.0
575
+ <pre><code class="language-yaml"> - uses: benner/commit-guard@v0.22.1
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.0
594
+ <pre><code class="language-yaml"> - uses: benner/commit-guard@v0.22.1
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.0
607
+ rev: v0.22.1
608
608
  hooks:
609
609
  - id: commit-guard
610
610
  - id: commit-guard-signature</code></pre>
@@ -34,6 +34,15 @@ TYPES = frozenset(
34
34
  )
35
35
 
36
36
  _NON_IMPERATIVE_SUFFIX_RE = re.compile(r"(?:ing|ed)$")
37
+ _VERB_FORMING_PREFIXES = frozenset(
38
+ {
39
+ "re",
40
+ "pre",
41
+ "auto",
42
+ "co",
43
+ "under",
44
+ }
45
+ )
37
46
  _TRAILER_RE = re.compile(r"^[\w-]+:\s+\S")
38
47
  _GITHUB_REMOTE_RE = re.compile(
39
48
  r"github\.com[:/](?P<owner>[^/]+)/(?P<repo>[^/\s]+?)(?:\.git)?$"
@@ -235,6 +244,13 @@ def check_imperative(desc, result):
235
244
  if tagged[1][1] != "VB":
236
245
  if wordnet.morphy(first, wordnet.VERB) == first:
237
246
  return
247
+ if "-" in first:
248
+ hyphen_prefix, hyphen_base = first.split("-", 1)
249
+ if (
250
+ hyphen_prefix in _VERB_FORMING_PREFIXES
251
+ and wordnet.morphy(hyphen_base, wordnet.VERB) == hyphen_base
252
+ ):
253
+ return
238
254
  result.error(
239
255
  f"expected imperative verb, got '{tagged[1][0]}' (POS={tagged[1][1]})",
240
256
  check=Check.IMPERATIVE,
@@ -573,6 +573,39 @@ class TestCheckImperative:
573
573
  assert not r.ok
574
574
  assert "POS=NN" in r.errors[0][2]
575
575
 
576
+ def test_hyphen_re_prefix_verb_passes(self):
577
+ r = Result()
578
+ check_imperative("re-enable signature check", r)
579
+ assert r.ok
580
+
581
+ def test_hyphen_auto_prefix_verb_passes(self):
582
+ r = Result()
583
+ check_imperative("auto-detect format from header", r)
584
+ assert r.ok
585
+
586
+ def test_hyphen_pre_prefix_verb_passes(self):
587
+ r = Result()
588
+ check_imperative("pre-process input lines", r)
589
+ assert r.ok
590
+
591
+ def test_hyphen_unknown_prefix_fails(self):
592
+ # 'high' is not in the verb-forming prefix allowlist
593
+ r = Result()
594
+ check_imperative("high-level overview of foo", r)
595
+ assert not r.ok
596
+
597
+ def test_hyphen_non_verb_base_fails(self):
598
+ # 'in' is not a verb, so even though split shape matches, base check rejects
599
+ r = Result()
600
+ check_imperative("built-in helper function", r)
601
+ assert not r.ok
602
+
603
+ def test_hyphen_inflected_suffix_still_fails(self):
604
+ # Suffix check runs before hyphen escape — 're-running' caught by ing$
605
+ r = Result()
606
+ check_imperative("re-running the tests", r)
607
+ assert not r.ok
608
+
576
609
 
577
610
  class TestDownloadIfMissing:
578
611
  def test_skips_download_when_present(self):