Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
43 changes: 37 additions & 6 deletions commit_check/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@

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
Expand All @@ -20,10 +18,43 @@
YELLOW = "\033[93m"
RESET_COLOR = "\033[0m"

# 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]}
# Follow conventional commits
DEFAULT_COMMIT_TYPES = [
"feat",
"fix",
"docs",
"style",
"refactor",
"test",
"chore",
"perf",
"build",
"ci",
]
# Follow conventional branch
DEFAULT_BRANCH_TYPES = [
"feature",
"bugfix",
"hotfix",
"release",
"chore",
"feat",
"fix",
]

# Handle different default values for different rules
DEFAULT_BOOLEAN_RULES = {
"subject_capitalized": True,
"subject_imperative": True,
"allow_merge_commits": True,
"allow_revert_commits": True,
"allow_empty_commits": True,
"allow_fixup_commits": True,
"allow_wip_commits": True,
"require_body": False,
"require_signed_off_by": False,
}


CONFIG_FILE = "." # Search current directory for commit-check.toml or cchk.toml
__version__ = version("commit-check")
37 changes: 8 additions & 29 deletions commit_check/rule_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
from typing import Dict, Any, List, Optional
from dataclasses import dataclass
from commit_check.rules_catalog import COMMIT_RULES, BRANCH_RULES, RuleCatalogEntry
from commit_check import (
DEFAULT_COMMIT_TYPES,
DEFAULT_BRANCH_TYPES,
DEFAULT_BOOLEAN_RULES,
)


@dataclass(frozen=True)
Expand Down Expand Up @@ -38,19 +43,6 @@ def to_dict(self) -> Dict[str, Any]:
class RuleBuilder:
"""Builds validation rules from config and catalog entries."""

# Follow conventional commits
DEFAULT_COMMIT_TYPES = ["feat", "fix", "docs", "style", "refactor", "test", "chore"]
# Follow conventional branch
DEFAULT_BRANCH_TYPES = [
"feature",
"bugfix",
"hotfix",
"release",
"chore",
"feat",
"fix",
]

def __init__(self, config: Dict[str, Any]):
self.config = config
self.commit_config = config.get("commit", {})
Expand Down Expand Up @@ -197,20 +189,7 @@ def _build_boolean_rule(
"""Build boolean-based validation rule."""
check = catalog_entry.check

# Handle different default values for different rules
defaults = {
"subject_capitalized": True,
"subject_imperative": True,
"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,
}

default_value = defaults.get(check, True)
default_value = DEFAULT_BOOLEAN_RULES.get(check, True)
config_value = section_config.get(check, default_value)

# For "allow_*" rules, only create rule if they're disabled (False)
Expand All @@ -235,12 +214,12 @@ def _build_boolean_rule(

def _get_allowed_commit_types(self) -> List[str]:
"""Get deduplicated list of allowed commit types."""
types = self.commit_config.get("allow_commit_types", self.DEFAULT_COMMIT_TYPES)
types = self.commit_config.get("allow_commit_types", DEFAULT_COMMIT_TYPES)
return list(dict.fromkeys(types)) # Preserve order, remove duplicates

def _get_allowed_branch_types(self) -> List[str]:
"""Get deduplicated list of allowed branch types."""
types = self.branch_config.get("allow_branch_types", self.DEFAULT_BRANCH_TYPES)
types = self.branch_config.get("allow_branch_types", DEFAULT_BRANCH_TYPES)
return list(dict.fromkeys(types)) # Preserve order, remove duplicates

def _build_conventional_commit_regex(self, allowed_types: List[str]) -> str:
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
what-is-new
configuration
migration
troubleshoot
changelog

.. toctree::
Expand Down
45 changes: 45 additions & 0 deletions docs/troubleshoot.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
Troubleshooting
===============

How to Skip Author Name Check
-----------------------------

In some cases, Commit Check may fail due to an invalid ``author_name``, as shown below:

.. code-block:: shell
check committer name.....................................................Failed
- hook id: check-author-name
- exit code: 1
Commit rejected by Commit-Check.
Type author_name check failed => 12
It doesn't match regex: ^[A-Za-zÀ-ÖØ-öø-ÿ\u0100-\u017F\u0180-\u024F ,.\'-]+$|.*(\[bot])
The committer name seems invalid
Suggest: run command `git config user.name "Your Name"`
To fix it, you can either update your Git config or temporarily skip the check using one of the following methods.

Bypass Specific Hook
~~~~~~~~~~~~~~~~~~~~

Use the ``--no-verify`` flag to skip the pre-commit hook:

.. code-block:: shell
# Amend the commit without running hooks
git commit --amend --author="Xianpeng Shen <xianpeng.shen@gmail.com>" --no-edit --no-verify
Bypass All Hooks
----------------

Alternatively, use the ``SKIP=your-hook-name`` environment variable, like below:

.. code-block:: shell
# Set the correct Git author name
git config user.name "Xianpeng Shen"
# Force amend while skipping the specified hook
SKIP=check-author-name git commit --amend --author="Xianpeng Shen <xianpeng.shen@gmail.com>" --no-edit
Comment on lines +24 to +45
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix misleading hook-bypass guidance

git commit --no-verify disables all hooks, while SKIP=… (pre-commit) skips only named hooks. The current headings/text invert that behavior and will mislead users. Please correct the descriptions/headings so they reflect the actual scope of each option.

-Bypass Specific Hook
-~~~~~~~~~~~~~~~~~~~~
-
-Use the ``--no-verify`` flag to skip the pre-commit hook:
+Bypass All Hooks
+----------------
+
+Use the ``--no-verify`` flag to skip every pre-commit and commit-msg hook:
@@
-Bypass All Hooks
-----------------
-
-Alternatively, use the ``SKIP=your-hook-name`` environment variable, like below:
+Skip Selected Hooks
+~~~~~~~~~~~~~~~~~~~
+
+Alternatively, use the ``SKIP=your-hook-name`` environment variable with pre-commit to skip only particular hooks:
🤖 Prompt for AI Agents
In docs/troubleshoot.rst around lines 24 to 45 the headings and descriptions
incorrectly state hook scopes: git commit --no-verify actually disables all
hooks while SKIP=your-hook-name only skips the named pre-commit hooks; update
the headings and explanatory text so the "Bypass All Hooks" section describes
--no-verify and its example, and the "Bypass Specific Hook" section describes
SKIP=your-hook-name and its example, adjusting the comments to state that
--no-verify disables all hooks and SKIP skips only the specified hook(s).

Loading