From fc225bb6beb4d31de16e8719eda3840e1b952f44 Mon Sep 17 00:00:00 2001 From: munitkala <83668383+munitkala@users.noreply.github.com> Date: Wed, 11 Nov 2026 14:25:00 -0500 Subject: [PATCH] fix(hook): catch an option and its value passed as one argument pre-commit passes each item in args as a single argument, so args: [--scopes api] reaches the hook as the one string "--scopes api". argparse can't match it to an option, so it took it as a commit type. The standard types were then added back and no scope rule was applied, so commits that should fail passed. The hook now fails with a message saying how to pass the option, and the README notes that each option and value go in separate items. --- README.md | 3 +++ conventional_pre_commit/hook.py | 8 ++++++++ tests/test_hook.py | 13 +++++++++++++ 3 files changed, 24 insertions(+) diff --git a/README.md b/README.md index aae0870..4638d54 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,9 @@ repos: **NOTE:** when using as a pre-commit hook, `input` is supplied automatically (with the current commit's message). +**NOTE:** pre-commit passes each item in `args` as a single argument, so an option and its value go in separate items, +like `[--scopes, api]` (or `[--scopes=api]`), not `[--scopes api]`. + ## Development `conventional-pre-commit` comes with a [VS Code devcontainer](https://code.visualstudio.com/learn/develop-cloud/containers) diff --git a/conventional_pre_commit/hook.py b/conventional_pre_commit/hook.py index 8c144e0..4077387 100644 --- a/conventional_pre_commit/hook.py +++ b/conventional_pre_commit/hook.py @@ -44,6 +44,14 @@ def main(argv=[]): try: args = parser.parse_args(argv) + # pre-commit passes each item in `args` as one argument, so `--scopes api` arrives + # as a single string. argparse doesn't see an option in it and takes it as a type. + for commit_type in args.types: + if commit_type.startswith("-"): + parser.error( + f'"{commit_type}" looks like an option and its value in one argument. ' + + "Pass them separately, e.g. [--scopes, api] or [--scopes=api]." + ) except SystemExit: return RESULT_FAIL diff --git a/tests/test_hook.py b/tests/test_hook.py index 695b4c3..907d74c 100644 --- a/tests/test_hook.py +++ b/tests/test_hook.py @@ -78,6 +78,19 @@ def test_main_success__conventional_with_scope(cmd, conventional_commit_with_sco assert result == RESULT_SUCCESS +def test_main_fail__option_and_value_in_one_arg(conventional_commit_with_scope_path, capsys): + result = main(["--force-scope", "--scopes api", conventional_commit_with_scope_path]) + + assert result == RESULT_FAIL + assert '"--scopes api" looks like an option and its value in one argument' in capsys.readouterr().err + + +def test_main_success__option_and_value_with_equals(conventional_commit_with_scope_path): + result = main(["--force-scope", "--scopes=scope", conventional_commit_with_scope_path]) + + assert result == RESULT_SUCCESS + + def test_main_success__fixup_commit(fixup_commit_path): result = main([fixup_commit_path])