Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
2f232b8
docs: add new configuration docs
shenxianpeng Sep 9, 2025
251797b
docs: update new configuration docs
shenxianpeng Sep 10, 2025
14daa97
docs: revert conf.py
shenxianpeng Sep 10, 2025
b34ed02
feat: remove .commit-check.yml and move config to rules
shenxianpeng Sep 10, 2025
2f95c58
chore: code cleanup
shenxianpeng Sep 10, 2025
7229ed6
feat(breaking): update commit-check commands
shenxianpeng Sep 12, 2025
76cc6e3
ci: update ci to pass failure
shenxianpeng Sep 12, 2025
decded8
fix: update rules.py and cchk.toml
shenxianpeng Sep 12, 2025
66860c9
fix: code cleanup and fix tests
shenxianpeng Sep 12, 2025
143803c
style: format code with ruff
shenxianpeng Sep 13, 2025
485bc28
chore: change error output style
shenxianpeng Sep 13, 2025
6d4cc18
fix: skip if merge commit
shenxianpeng Sep 13, 2025
0e3e604
fix: bypass when branch is HEAD
shenxianpeng Sep 13, 2025
bc89a4a
fix: update test
shenxianpeng Sep 13, 2025
fd7e123
feat: add original commands back
shenxianpeng Sep 14, 2025
f484cbb
fix: update main_test.py
shenxianpeng Sep 14, 2025
834c394
fix: update args and tests
shenxianpeng Sep 24, 2025
050beae
fix: revert noxfile.py to commit-check session
shenxianpeng Sep 25, 2025
da60df4
chore: remove author section
shenxianpeng Sep 25, 2025
16c82da
refactor: rename rules.py to _rules.py
shenxianpeng Sep 25, 2025
de94d3f
refactor: save progress
shenxianpeng Sep 25, 2025
74b7ef8
refactor: save progress
shenxianpeng Sep 25, 2025
d19a915
refactor: save progress
shenxianpeng Sep 25, 2025
8f56396
refactor: save progress
shenxianpeng Sep 25, 2025
6ca70f3
refactor: save progress
shenxianpeng Sep 25, 2025
76159a7
refactor: save progress
shenxianpeng Sep 25, 2025
5616cb3
refactor: remove legacy files
shenxianpeng Sep 25, 2025
4f82871
test: add more test
shenxianpeng Sep 25, 2025
699f43c
chore: update conf.py
shenxianpeng Oct 2, 2025
6b6c2e2
fix: update main.py to support stdin for other check
shenxianpeng Oct 3, 2025
c116654
fix: update tests
shenxianpeng Oct 3, 2025
68afa23
fix: checkout branch name
shenxianpeng Oct 3, 2025
bc700e2
fix: pint action to commit hash
shenxianpeng Oct 3, 2025
882e39d
fix: checkout branch name
shenxianpeng Oct 3, 2025
b43a3ef
fix: add checkout branch name
shenxianpeng Oct 3, 2025
56299b1
fix: update session name
shenxianpeng Oct 3, 2025
643a1a7
fix: update per code review
shenxianpeng Oct 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 0 additions & 39 deletions .commit-check.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ nox -s build
python3 -m pip wheel --no-deps -w dist . # NETWORK ISSUES: Also fails due to build dependencies

# Install wheel (depends on build)
nox -s install-wheel # NETWORK ISSUES: Often fails due to PyPI timeouts in CI environments
nox -s install # NETWORK ISSUES: Often fails due to PyPI timeouts in CI environments
```

### Testing
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ jobs:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
with:
ref: ${{ github.head_ref }} # get current branch name
- uses: actions/setup-python@v6
with:
python-version: '3.x'
Expand Down Expand Up @@ -48,7 +50,7 @@ jobs:
- name: Collect Coverage
run: nox -s coverage

- uses: codecov/codecov-action@v5.0.2
- uses: codecov/codecov-action@5c47607acb93fed5485fdbf7232e8a31425f672a # v5.0.2
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.xml
Expand Down Expand Up @@ -81,7 +83,7 @@ jobs:
- name: Install test
# using a wildcard as filename on Windows requires a bash shell
shell: bash
run: nox -s install-wheel
run: nox -s install

docs:
runs-on: ubuntu-24.04
Expand Down Expand Up @@ -110,7 +112,7 @@ jobs:
- name: Upload docs to github pages
# only publish doc changes from main branch
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v4
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./_build/html
7 changes: 3 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ repos:
- id: trailing-whitespace
- id: name-tests-test
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.12.12
rev: v0.13.2
hooks:
# Run the linter.
- id: ruff
- id: ruff-check
args: [ --fix ]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.17.1
hooks:
Expand Down
25 changes: 2 additions & 23 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
language: python
stages: [commit-msg]
- id: check-branch
name: check branch naming
description: ensures branch naming to match regex
name: check branch name
description: ensures branch name to match regex
entry: commit-check
args: [--branch]
pass_filenames: false
Expand All @@ -27,24 +27,3 @@
args: [--author-email]
pass_filenames: false
language: python
- id: check-commit-signoff
name: check committer signoff
description: ensures committer to add a Signed-off-by trailer
entry: commit-check
args: [--commit-signoff]
pass_filenames: false
language: python
- id: check-merge-base
name: check merge base
description: ensures current branch is rebased onto target branch
entry: commit-check
args: [--merge-base]
pass_filenames: false
language: python
- id: check-imperative
name: check imperative mood
description: ensures commit message uses imperative mood
entry: commit-check
args: [--imperative]
pass_filenames: true
language: python
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ Check Commit Signature Failed

Commit rejected.

Type commit_signoff check failed => c92ce259ff041c91859c7fb61afdbb391e769d0f
Type signoff check failed => c92ce259ff041c91859c7fb61afdbb391e769d0f
It doesn't match regex: Signed-off-by:.*[A-Za-z0-9]\s+<.+@.+>
Signed-off-by not found in latest commit
Suggest: run command `git commit -m "conventional commit message" --signoff`
Expand Down
23 changes: 23 additions & 0 deletions cchk.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[commit]
# https://www.conventionalcommits.org
conventional_commits = true
subject_capitalized = false
subject_imperative = true
Copy link
Contributor

@coderabbitai coderabbitai bot Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use ‘imperative’ key to match engine/rule_builder.

Current ‘subject_imperative’ is ignored by engine; rename to imperative.

-subject_imperative = true
+imperative = true
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
subject_imperative = true
imperative = true
🤖 Prompt for AI Agents
In cchk.toml around line 5, the key subject_imperative is ignored by the engine;
rename the key to imperative so it matches engine/rule_builder expectations.
Replace subject_imperative = true with imperative = true (preserving the boolean
value) and save the file to ensure the rule builder reads the setting correctly.

Copy link
Contributor Author

@shenxianpeng shenxianpeng Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai The option should still be subject_imperative

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how subject_imperative is used in rule_builder.py
echo "=== Checking rule_builder.py for subject_imperative usage ==="
rg -n "subject_imperative" commit_check/rule_builder.py -C 3

echo ""
echo "=== Checking engine.py for imperative vs subject_imperative ==="
rg -n "imperative" commit_check/engine.py -C 2

echo ""
echo "=== Checking for validator mapping in engine.py ==="
rg -n "VALIDATOR_MAP" commit_check/engine.py -A 20

echo ""
echo "=== Checking rules_catalog.py for imperative references ==="
rg -n "imperative" commit_check/rules_catalog.py -C 2

Length of output: 3255


🏁 Script executed:

#!/bin/bash
# Check the complete flow in rule_builder for subject_imperative
echo "=== Checking _build_boolean_rule method ==="
rg -n "_build_boolean_rule" commit_check/rule_builder.py -A 15

echo ""
echo "=== Checking build_commit_rules method ==="
rg -n "def build_commit_rules" commit_check/rule_builder.py -A 40

echo ""
echo "=== Checking if there's a mapping from subject_imperative to imperative ==="
rg -n "subject_imperative.*imperative|imperative.*subject_imperative" commit_check/rule_builder.py -C 3

Length of output: 1537


🏁 Script executed:

#!/bin/bash
# Get the complete view of how rules are built
echo "=== Checking complete build_commit_rules implementation ==="
ast-grep --pattern $'def build_commit_rules($$$) {
  $$$
}'

echo ""
echo "=== Getting the catalog entry for imperative ==="
rg -n "check=\"imperative\"" commit_check/ -B 2 -A 3

echo ""
echo "=== Checking the _build_boolean_rule logic for check name usage ==="
ast-grep --pattern $'def _build_boolean_rule($$$) {
  $$$
  check = $$$
  $$$
}'

Length of output: 613


🏁 Script executed:

#!/bin/bash
# Read the _build_boolean_rule method completely
echo "=== Complete _build_boolean_rule method ==="
sed -n '/def _build_boolean_rule/,/^    def [a-zA-Z]/p' commit_check/rule_builder.py | head -n -1

echo ""
echo "=== Check the build_commit_rules method ==="
sed -n '/def build_commit_rules/,/^    def [a-zA-Z]/p' commit_check/rule_builder.py | head -n -1

Length of output: 2674


@shenxianpeng, I've verified the implementation, and I need to clarify the situation. There's actually an inconsistency in the codebase that affects this:

The config key should be imperative, not subject_imperative. Here's why:

  1. In rules_catalog.py (line 30): The catalog entry is defined as check="imperative"

  2. In engine.py (line 481): The VALIDATOR_MAP uses "imperative": SubjectImperativeValidator

  3. In rule_builder.py (line 220): When building rules, it does:

    check = catalog_entry.check  # This is "imperative"
    config_value = section_config.get(check, default_value)  # Looks for "imperative" in config
  4. The bug: The defaults dict (line 211) and the special case check (line 231) incorrectly reference "subject_imperative" instead of "imperative". This is a leftover inconsistency.

What happens with subject_imperative = true in the config:

  • The rule_builder will look for key "imperative" in the config (not "subject_imperative")
  • It won't find it, so it uses the default
  • The subject_imperative key in your config file is effectively ignored

To verify this is working correctly, you should:

  • Use imperative = true in the config (as the bot suggested)
  • Consider opening an issue to fix the inconsistency in rule_builder.py where it references "subject_imperative" in the defaults and special case handling

The original suggestion to rename to imperative was correct. Would you like me to help identify where the codebase should be updated to make the naming consistent?

subject_max_length = 50
subject_min_length = 5
allow_commit_types = ["feat", "fix", "docs", "style", "refactor", "test", "chore", "ci"]
allow_merge_commits = true
allow_revert_commits = true
allow_empty_commits = false
allow_fixup_commits = true
allow_wip_commits = false
require_body = false
require_signed_off_by = false
allow_authors = []
ignore_authors = ["dependabot[bot]", "copilot[bot]"]

[branch]
# https://conventional-branch.github.io/
conventional_branch = true
allow_branch_types = ["feature", "bugfix", "hotfix", "release", "chore", "feat", "fix"]
require_rebase_target = "main"
86 changes: 21 additions & 65 deletions commit_check/__init__.py
Original file line number Diff line number Diff line change
@@ -1,73 +1,29 @@
"""The commit-check package's base module."""
from importlib.metadata import version
"""The commit-check package's base module.

RED = '\033[0;31m'
GREEN = "\033[32m"
YELLOW = '\033[93m'
RESET_COLOR = '\033[0m'
Exports:
PASS / FAIL exit codes
DEFAULT_CONFIG: minimal default rule set used when no config found
ANSI color constants
__version__ (package version)
"""

from importlib.metadata import version
from commit_check.rule_builder import RuleBuilder

# Exit codes used across the package
PASS = 0
FAIL = 1

"""
Use default config if .commit-check.yml not exist.
"""
DEFAULT_CONFIG = {
'checks': [
{
'check': 'message',
'regex': r'^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test){1}(\([\w\-\.]+\))?(!)?: ([\w ])+([\s\S]*)|(Merge).*|(fixup!.*)',
'error': 'The commit message should be structured as follows:\n\n'
'<type>[optional scope]: <description>\n'
'[optional body]\n'
'[optional footer(s)]\n\n'
'More details please refer to https://www.conventionalcommits.org',
'suggest': 'please check your commit message whether matches above regex'
},
{
'check': 'branch',
'regex': r'^(bugfix|feature|release|hotfix|task|chore)\/.+|(master)|(main)|(HEAD)|(PR-.+)',
'error': 'Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/ chore/',
'suggest': 'run command `git checkout -b type/branch_name`',
},
{
'check': 'author_name',
'regex': r'^[A-Za-zÀ-ÖØ-öø-ÿ\u0100-\u017F\u0180-\u024F ,.\'-]+$|.*(\[bot])',
'error': 'The committer name seems invalid',
'suggest': 'run command `git config user.name "Your Name"`',
},
{
'check': 'author_email',
'regex': r'^.+@.+$',
'error': 'The committer\'s email seems invalid',
'suggest': 'run command `git config user.email yourname@example.com`',
},
{
'check': 'commit_signoff',
'regex': r'Signed-off-by:.*[A-Za-z0-9]\s+<.+@.+>',
'error': 'Signed-off-by not found in latest commit',
'suggest': 'run command `git commit -m "conventional commit message" --signoff`',
},
{
'check': 'merge_base',
'regex': r'main', # it can be master, develop, devel etc based on your project.
'error': 'Current branch is not rebased onto target branch',
'suggest': 'Please ensure your branch is rebased with the target branch',
},
{
'check': 'imperative',
'regex': r'', # Not used for imperative mood check
'error': 'Commit message should use imperative mood (e.g., "Add feature" not "Added feature")',
'suggest': 'Use imperative mood in commit message like "Add", "Fix", "Update", "Remove"',
},
],
}


"""
Overwrite DEFAULT_CONFIG if `.commit-check.yml` exist.
"""
# ANSI color codes used for CLI output
RED = "\033[91m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
RESET_COLOR = "\033[0m"

CONFIG_FILE = '.commit-check.yml'
# Default (empty) configuration translated into internal checks structure
_rule_builder = RuleBuilder({})
_default_rules = _rule_builder.build_all_rules()
DEFAULT_CONFIG = {"checks": [rule.to_dict() for rule in _default_rules]}

CONFIG_FILE = "." # Search current directory for commit-check.toml or cchk.toml
__version__ = version("commit-check")
50 changes: 0 additions & 50 deletions commit_check/author.py

This file was deleted.

56 changes: 0 additions & 56 deletions commit_check/branch.py

This file was deleted.

Loading
Loading