Skip to content

feat: Enhance configuration with CLI, env vars, and TOML support#357

Merged
shenxianpeng merged 4 commits intomainfrom
feature/enhance-configration
Feb 1, 2026
Merged

feat: Enhance configuration with CLI, env vars, and TOML support#357
shenxianpeng merged 4 commits intomainfrom
feature/enhance-configration

Conversation

@shenxianpeng
Copy link
Contributor

@shenxianpeng shenxianpeng commented Feb 1, 2026

closes #339

  • Introduced a new ConfigMerger class to handle merging configurations from multiple sources: command-line arguments, environment variables, TOML files, and defaults.
  • Added command-line options for various commit and branch configurations, including subject length, imperative mood, and allowed commit types.
  • Updated README and configuration documentation to reflect new configuration methods and examples.
  • Implemented comprehensive tests for CLI argument integration, environment variable handling, and configuration priority.
  • Ensured backward compatibility with existing configuration files while providing enhanced flexibility for users.

Summary by CodeRabbit

  • New Features

    • Configuration now supports CLI arguments, environment variables, and config files with defined precedence; many new commit and branch options exposed.
  • Documentation

    • Added detailed configuration guide with examples, precedence rules, mappings, and pre-commit usage.
  • Tests

    • Expanded unit and integration tests covering parsers, merging, priority chain, and CLI/env behavior.
  • Chores

    • Updated pre-commit hook tool version.

✏️ Tip: You can customize this high-level summary in your review settings.

…upport

- Introduced a new ConfigMerger class to handle merging configurations from multiple sources: command-line arguments, environment variables, TOML files, and defaults.
- Added command-line options for various commit and branch configurations, including subject length, imperative mood, and allowed commit types.
- Updated README and configuration documentation to reflect new configuration methods and examples.
- Implemented comprehensive tests for CLI argument integration, environment variable handling, and configuration priority.
- Ensured backward compatibility with existing configuration files while providing enhanced flexibility for users.
@shenxianpeng shenxianpeng requested a review from a team as a code owner February 1, 2026 18:45
@shenxianpeng shenxianpeng added the enhancement New feature or request label Feb 1, 2026
@netlify
Copy link

netlify bot commented Feb 1, 2026

Deploy Preview for commit-check ready!

Name Link
🔨 Latest commit 1d8f9a2
🔍 Latest deploy log https://app.netlify.com/projects/commit-check/deploys/697fa7ae9b72c60008eb0548
😎 Deploy Preview https://deploy-preview-357--commit-check.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions bot added the documentation Improvements or additions to documentation label Feb 1, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 1, 2026

📝 Walkthrough

Walkthrough

Adds a multi-source configuration system (CLI, environment variables, TOML, defaults) with a ConfigMerger, updates main to use it and exposes many new CLI options, updates docs and README with configuration guidance, updates pre-commit hook version, and adds extensive tests for merging and priority behavior.

Changes

Cohort / File(s) Summary
Pre-commit Hook Version
​.pre-commit-config.yaml
Bumped commit-check hook rev from v2.2.2 to v2.3.0.
Documentation
README.rst, docs/configuration.rst
Added detailed configuration guidance (CLI, environment, TOML), examples, precedence rules, and updated README headings/examples.
Config merger implementation
commit_check/config_merger.py
New module implementing parsing helpers (parse_bool, parse_list, parse_int), get_default_config, deep_merge, and ConfigMerger with parse_env_vars, parse_cli_args, and from_all_sources to merge defaults, TOML, env, and CLI in priority order.
Main integration & CLI surface
commit_check/main.py
Replaced prior config loading with ConfigMerger.from_all_sources(...), imported parsing helpers, and added many new CLI options for commit/branch rules.
Tests — unit and integration
tests/config_merger_test.py, tests/main_test.py
Added extensive tests for parser helpers, defaults, deep merging, env parsing, CLI parsing, priority chain, and integration tests validating CLI/env/config precedence. (+~522 lines across tests)

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Env as "Environment\n(CCHK_... vars)"
  participant TOML as "TOML File\n(commit-check.toml/cchk.toml)"
  participant Defaults
  participant Merger as ConfigMerger
  participant Main

  CLI->>Merger: provide CLI args
  Env->>Merger: provide CCHK_* env vars
  TOML->>Merger: provide parsed TOML (if present)
  Defaults->>Merger: provide default config
  Merger->>Merger: deep_merge(TOML into Defaults)\nthen merge Env, then CLI (priority)
  Merger->>Main: return merged config dict
  Main->>Main: build rules and run validations using merged config
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

enhancement, major, documentation, tests, developer

Poem

🐰 I stitched defaults, env, and CLI,
Merged them neat beneath my sky,
TOML tucked in, priorities true,
Tests hopped through each path I drew,
A little rabbit cheers—config made new!

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: Enhance configuration with CLI, env vars, and TOML support' clearly and concisely summarizes the main change: adding multi-source configuration support.
Linked Issues check ✅ Passed All coding requirements from issue #339 are met: CLI parameters (--subject-), environment variables (CCHK_ prefix), TOML files supported, and backward compatibility preserved through ConfigMerger.
Out of Scope Changes check ✅ Passed All changes are within scope of issue #339: configuration infrastructure, CLI/env var support, documentation, pre-commit hook version bump, and comprehensive tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/enhance-configration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Feb 1, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.35%. Comparing base (c169d35) to head (1d8f9a2).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #357      +/-   ##
==========================================
+ Coverage   93.22%   94.35%   +1.12%     
==========================================
  Files           8        9       +1     
  Lines         694      797     +103     
==========================================
+ Hits          647      752     +105     
+ Misses         47       45       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@commit_check/config_merger.py`:
- Around line 65-66: The default configuration in commit_check/config_merger.py
currently sets "subject_max_length": 80 and "subject_min_length": 5 which
conflicts with the documented defaults of None; update the defaults to match the
docs by changing the values for the keys subject_max_length and
subject_min_length to None (no limit) in the default config/dict (where these
keys are defined) so validation will behave as documented.

In `@docs/configuration.rst`:
- Around line 122-131: The documentation example shows the pre-commit hook repo
entry using rev: v2.2.0 which mismatches the updated .pre-commit-config.yaml;
update the example's rev value from v2.2.0 to v2.3.0 for the commit-check repo
entry (the block containing repo: https://github.com/commit-check/commit-check
and id: commit-check) so the docs match the actual hook version and the new CLI
args work as expected.

In `@README.rst`:
- Around line 106-115: Update the pre-commit example's repo revision from v2.2.0
to v2.3.0: locate the pre-commit hooks block that contains the line "rev:
v2.2.0" (the example under repos -> repo:
https://github.com/commit-check/commit-check and hook id: commit-check) and
change the revision string to "v2.3.0" so it matches the new features and the
docs/configuration.rst example.
🧹 Nitpick comments (6)
commit_check/config_merger.py (4)

51-55: Preserve exception chain with raise ... from.

When re-raising a ValueError inside an except block, use raise ... from to maintain the exception chain for better debugging.

♻️ Suggested fix
     if isinstance(value, str):
         try:
             return int(value.strip())
         except ValueError as err:
-            raise ValueError(f"Cannot parse '{value}' as integer")
+            raise ValueError(f"Cannot parse '{value}' as integer") from err
     raise TypeError(f"Cannot convert {type(value).__name__} to int")

100-122: Consider annotating mutable class attribute with ClassVar.

The ENV_VAR_MAPPING dictionary is a class-level constant that should be annotated with typing.ClassVar to indicate it's shared across all instances and not meant to be modified per-instance.

♻️ Suggested fix
+from typing import ClassVar
+
 class ConfigMerger:
     """Merges configurations from multiple sources with priority: CLI > Env > TOML > Defaults."""

     # Mapping of environment variable names to config keys
-    ENV_VAR_MAPPING: Dict[str, Tuple[str, str, Callable[[Any], Any]]] = {
+    ENV_VAR_MAPPING: ClassVar[Dict[str, Tuple[str, str, Callable[[Any], Any]]]] = {

135-137: Warning output to stdout may interfere with piped workflows.

Using print() for warnings sends output to stdout, which could interfere with scenarios where commit-check output is piped. Consider using sys.stderr or the logging module instead.

♻️ Suggested fix
+import sys
+
                 except (ValueError, TypeError) as e:
                     # Log warning but don't fail - just skip invalid env vars
-                    print(f"Warning: Invalid value for {env_var}: {e}")
+                    print(f"Warning: Invalid value for {env_var}: {e}", file=sys.stderr)

144-222: Consider reducing repetition in parse_cli_args.

The method has significant repetition with the hasattr/is not None pattern. A data-driven approach similar to ENV_VAR_MAPPING would reduce maintenance burden and be more consistent.

♻️ Example refactor approach
CLI_ARG_MAPPING = {
    # (attr_name, section, config_key)
    ("conventional_commits", "commit", "conventional_commits"),
    ("subject_capitalized", "commit", "subject_capitalized"),
    ("subject_imperative", "commit", "subject_imperative"),
    # ... etc
}

`@staticmethod`
def parse_cli_args(args: argparse.Namespace) -> Dict[str, Any]:
    config: Dict[str, Any] = {"commit": {}, "branch": {}}
    for attr, section, key in ConfigMerger.CLI_ARG_MAPPING:
        value = getattr(args, attr, None)
        if value is not None:
            config[section][key] = value
    config = {k: v for k, v in config.items() if v}
    return config
commit_check/main.py (1)

355-360: Dead code branch in stdin handling.

The elif not any(...) block at line 355-357 contains only a pass statement and has no effect. This could be simplified or removed.

♻️ Suggested simplification
             if args.message == "":
                 # Only set stdin_content if there's actual piped input
                 stdin_content = stdin_reader.read_piped_input()
                 if not stdin_content:
                     # No stdin and no file - let validators get data from git themselves
                     stdin_content = None
             else:
                 # Message is a file path
                 commit_file_path = args.message
-        elif not any([args.branch, args.author_name, args.author_email]):
-            # If no specific validation type is requested, don't read stdin
-            pass
-        else:
+        elif any([args.branch, args.author_name, args.author_email]):
             # For non-message validations (branch, author), check for stdin input
             stdin_content = stdin_reader.read_piped_input()
tests/config_merger_test.py (1)

254-261: Remove unused tmp_path fixture parameter.

The tmp_path fixture parameter is declared but not used in this test method.

♻️ Suggested fix
-    def test_default_config_only(self, tmp_path):
+    def test_default_config_only(self):
         # No TOML file, no env vars, no CLI args
         args = argparse.Namespace()
         config = ConfigMerger.from_all_sources(args)

Comment on lines +65 to +66
"subject_max_length": 80,
"subject_min_length": 5,
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

🧩 Analysis chain

🏁 Script executed:

# First, check the documentation as suggested
rg -n "subject_max_length|subject_min_length" docs/configuration.rst | head -20

Repository: commit-check/commit-check

Length of output: 427


🏁 Script executed:

# Read the full context around lines 65-66 in config_merger.py
cat -n commit_check/config_merger.py | sed -n '50,80p'

Repository: commit-check/commit-check

Length of output: 1794


🏁 Script executed:

# Also check if there are multiple config files or defaults defined elsewhere
fd -t f config || true
fd -t f "\.py$" commit_check/ | xargs rg -l "subject_max_length|subject_min_length"

Repository: commit-check/commit-check

Length of output: 326


🏁 Script executed:

# Get more context around lines 279-287 in the documentation
cat -n docs/configuration.rst | sed -n '270,300p'

Repository: commit-check/commit-check

Length of output: 1169


🏁 Script executed:

# Check broader context around lines 62-63 and 183-186
cat -n docs/configuration.rst | sed -n '55,75p'
cat -n docs/configuration.rst | sed -n '175,195p'

Repository: commit-check/commit-check

Length of output: 1978


Default values in code conflict with documented behavior.

The code sets subject_max_length to 80 and subject_min_length to 5, but the documentation at lines 279-287 specifies these options default to None (no limit). This mismatch could cause unexpected validation failures for users relying on the documented default behavior.

Align either the code defaults or documentation to ensure consistency.

🤖 Prompt for AI Agents
In `@commit_check/config_merger.py` around lines 65 - 66, The default
configuration in commit_check/config_merger.py currently sets
"subject_max_length": 80 and "subject_min_length": 5 which conflicts with the
documented defaults of None; update the defaults to match the docs by changing
the values for the keys subject_max_length and subject_min_length to None (no
limit) in the default config/dict (where these keys are defined) so validation
will behave as documented.

@codspeed-hq
Copy link

codspeed-hq bot commented Feb 1, 2026

Merging this PR will degrade performance by 57.64%

❌ 17 regressed benchmarks
✅ 137 untouched benchmarks
🆕 11 new benchmarks
⏩ 108 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
test_main_with_message_empty_string_no_stdin_with_git 7.8 ms 8.8 ms -11.18%
test_nonexistent_config_file_error 1 ms 2 ms -47.57%
test_main_with_message_file_argument 3.7 ms 4.8 ms -22.39%
🆕 test_cli_allow_commit_types N/A 5.1 ms N/A
🆕 test_cli_multiple_args_combined N/A 5.9 ms N/A
🆕 test_cli_allow_merge_commits_false N/A 5.1 ms N/A
🆕 test_env_overrides_default N/A 5.1 ms N/A
🆕 test_cli_overrides_env N/A 5.6 ms N/A
🆕 test_cli_subject_imperative_false N/A 5.6 ms N/A
🆕 test_cli_subject_max_length N/A 5.1 ms N/A
🆕 test_cli_subject_imperative_true N/A 5 ms N/A
🆕 test_env_allow_commit_types N/A 5.1 ms N/A
🆕 test_env_subject_imperative N/A 5 ms N/A
🆕 test_env_subject_max_length N/A 5.1 ms N/A
test_message_validation_from_file 3.7 ms 4.8 ms -22.48%
test_author_email_validation 2.6 ms 3.6 ms -27.72%
test_help 2.2 ms 5.3 ms -57.64%
test_message_validation_with_valid_commit 4.8 ms 5.8 ms -17.2%
test_no_args_shows_help 3 ms 6.1 ms -51.45%
test_message_validation_with_invalid_commit 4.1 ms 5.1 ms -19.81%
... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.


Comparing feature/enhance-configration (1d8f9a2) with main (c169d35)

Open in CodSpeed

Footnotes

  1. 108 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

shenxianpeng and others added 2 commits February 1, 2026 21:02
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@shenxianpeng shenxianpeng force-pushed the feature/enhance-configration branch from 6280a54 to 8f80ac6 Compare February 1, 2026 19:02
@shenxianpeng shenxianpeng requested a review from Copilot February 1, 2026 19:04
@shenxianpeng shenxianpeng added major-rfe For changelog: Major enhancement. Will be highlighted on the top and removed documentation Improvements or additions to documentation enhancement New feature or request labels Feb 1, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR enhances commit-check's configuration system to support CLI arguments, environment variables, and TOML files with a clear priority hierarchy (CLI > Env > TOML > Defaults), directly addressing issue #339 which requested the ability to configure the tool via CLI parameters in pre-commit hooks without requiring a TOML configuration file.

Changes:

  • Introduced a new ConfigMerger class that merges configurations from multiple sources with proper priority handling
  • Added comprehensive CLI arguments for all commit and branch validation options using custom parsers (parse_bool, parse_list, parse_int)
  • Implemented environment variable support with the CCHK_ prefix for all configuration options
  • Updated documentation extensively to explain the new configuration methods, priority system, and usage patterns

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
commit_check/config_merger.py New module implementing configuration merging logic with support for CLI args, env vars, TOML files, and defaults
commit_check/main.py Added CLI argument definitions for all configuration options and integrated ConfigMerger
tests/config_merger_test.py Comprehensive unit tests for ConfigMerger, parse functions, and priority handling
tests/main_test.py Integration tests verifying CLI args, env vars, and priority system work end-to-end
docs/configuration.rst Extensive documentation additions covering CLI args, env vars, priority system, and mapping tables
README.rst Updated to document the three configuration methods and their priority
.pre-commit-config.yaml Version bump to v2.3.0

Copy link
Contributor

Copilot AI commented Feb 1, 2026

@shenxianpeng I've opened a new pull request, #358, to work on those changes. Once the pull request is ready, I'll request review from you.

* Initial plan

* refactor: Use data-driven approach in parse_cli_args to reduce duplication

Co-authored-by: shenxianpeng <3353385+shenxianpeng@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: shenxianpeng <3353385+shenxianpeng@users.noreply.github.com>
@github-actions github-actions bot added documentation Improvements or additions to documentation enhancement New feature or request labels Feb 1, 2026
@shenxianpeng shenxianpeng removed documentation Improvements or additions to documentation enhancement New feature or request labels Feb 1, 2026
@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 1, 2026

@shenxianpeng shenxianpeng merged commit f1a4704 into main Feb 1, 2026
35 checks passed
@shenxianpeng shenxianpeng deleted the feature/enhance-configration branch February 1, 2026 19:25
@shenxianpeng shenxianpeng added the minor A minor version bump label Feb 1, 2026
- repo: https://github.com/commit-check/commit-check
rev: v2.3.0
hooks:
- id: commit-check
Copy link

Choose a reason for hiding this comment

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

The id: commit-check is not correct...
It is not defined in https://github.com/commit-check/commit-check/blob/main/.pre-commit-hooks.yaml

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! fixed into the main branch.

Copy link

Choose a reason for hiding this comment

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

I'm not sure if it is just on my side, but I'm getting error:

$ git commit -m 'feat: improve logging messages and add checks for .lycheecache'
...
...
...
check commit message.....................................................Failed
- hook id: check-message
- exit code: 2

  usage: commit-check [-h] [-v] [-c CONFIG] [-m [MESSAGE]] [-b] [-n] [-e] [-d]
                      [--conventional-commits BOOL] [--subject-capitalized BOOL]
                      [--subject-imperative BOOL] [--subject-max-length INT]
                      [--subject-min-length INT] [--allow-commit-types LIST]
                      [--allow-merge-commits BOOL] [--allow-revert-commits BOOL]
                      [--allow-empty-commits BOOL] [--allow-fixup-commits BOOL]
                      [--allow-wip-commits BOOL] [--require-body BOOL]
                      [--require-signed-off-by BOOL] [--ignore-authors LIST]
                      [--conventional-branch BOOL] [--allow-branch-types LIST]
                      [--allow-branch-names LIST]
                      [--require-rebase-target BRANCH]
                      [--branch-ignore-authors LIST]
  commit-check: error: unrecognized arguments: .git/COMMIT_EDITMSG

I have this in .pre-commit-config.yaml:

  - repo: https://github.com/commit-check/commit-check
    rev: v2.4.0
    hooks:
      - id: check-message
        args:
          - --subject-imperative=false
      - id: check-branch
      - id: check-author-name
      - id: check-author-email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

major-rfe For changelog: Major enhancement. Will be highlighted on the top minor A minor version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pre-commit hook with CLI parameters

3 participants