From fa9331c0aa45446337f8b046fad4aa5c43c6bb02 Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Wed, 14 Jan 2026 12:26:11 +0800 Subject: [PATCH 1/3] feat(cli): add cz --version back and add cz --report to separate them from cz version --- commitizen/cli.py | 24 +++++++++++++++++++ tests/test_cli.py | 19 +++++++++++++++ ...invalid_command_py_3_10___invalid_arg_.txt | 3 ++- ...nvalid_command_py_3_10_invalidCommand_.txt | 3 ++- ...invalid_command_py_3_11___invalid_arg_.txt | 3 ++- ...nvalid_command_py_3_11_invalidCommand_.txt | 3 ++- ...invalid_command_py_3_12___invalid_arg_.txt | 3 ++- ...nvalid_command_py_3_12_invalidCommand_.txt | 3 ++- ...invalid_command_py_3_13___invalid_arg_.txt | 3 ++- ...nvalid_command_py_3_13_invalidCommand_.txt | 3 ++- ...invalid_command_py_3_14___invalid_arg_.txt | 3 ++- ...nvalid_command_py_3_14_invalidCommand_.txt | 3 ++- tests/test_cli/test_no_argv_py_3_10_.txt | 5 +++- tests/test_cli/test_no_argv_py_3_11_.txt | 5 +++- tests/test_cli/test_no_argv_py_3_12_.txt | 5 +++- tests/test_cli/test_no_argv_py_3_13_.txt | 5 +++- tests/test_cli/test_no_argv_py_3_14_.txt | 5 +++- 17 files changed, 83 insertions(+), 15 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index 85674e8c4d..fbbe5e4f9f 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -2,6 +2,7 @@ import argparse import logging +import platform import sys from copy import deepcopy from functools import partial @@ -13,6 +14,7 @@ from decli import cli from commitizen import commands, config, out, version_schemes +from commitizen.__version__ import __version__ from commitizen.defaults import DEFAULT_SETTINGS from commitizen.exceptions import ( CommitizenException, @@ -104,6 +106,16 @@ def __call__( "required": False, "help": "Comma-separated error codes that won't raise error, e.g., cz -nr 1,2,3 bump. See codes at https://commitizen-tools.github.io/commitizen/exit_codes/", }, + { + "name": ["-v", "--version"], + "action": "store_true", + "help": "Show the version of the installed commitizen", + }, + { + "name": ["--report"], + "action": "store_true", + "help": "Show system information for reporting bugs", + }, ], "subcommands": { "title": "commands", @@ -677,6 +689,18 @@ def main() -> None: parser.print_help(sys.stderr) raise ExpectedExit() + # TODO(bearomorphism): mark `cz version --commitizen` as deprecated after `cz version` feature is stable + if "--version" in sys.argv: + out.write(__version__) + raise ExpectedExit() + + # TODO(bearomorphism): mark `cz version --report` as deprecated after `cz version` feature is stable + if "--report" in sys.argv: + out.write(f"Commitizen Version: {__version__}") + out.write(f"Python Version: {sys.version}") + out.write(f"Operating System: {platform.system()}") + raise ExpectedExit() + # This is for the command required constraint in 2.0 try: args, unknown_args = parser.parse_known_args() diff --git a/tests/test_cli.py b/tests/test_cli.py index c1f6d5beda..15e5bcb55c 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -8,6 +8,7 @@ from pytest_mock import MockFixture from commitizen import cli +from commitizen.__version__ import __version__ from commitizen.exceptions import ( ConfigFileNotFound, ExpectedExit, @@ -55,6 +56,24 @@ def test_cz_with_arg_but_without_command(util: UtilFixture): assert "Command is required" in str(excinfo.value) +def test_cz_with_version_arg(util: UtilFixture, capsys): + """Test that cz shows the version when --version is used.""" + with pytest.raises(ExpectedExit): + util.run_cli("--version") + out, _ = capsys.readouterr() + assert __version__ in out + + +def test_cz_with_report_arg(util: UtilFixture, capsys): + """Test that cz shows the report when --report is used.""" + with pytest.raises(ExpectedExit): + util.run_cli("--report") + out, _ = capsys.readouterr() + assert "Commitizen Version:" in out + assert "Python Version:" in out + assert "Operating System:" in out + + def test_name(util: UtilFixture, capsys): util.run_cli("-n", "cz_jira", "example") out, _ = capsys.readouterr() diff --git a/tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt index 148b4eacdb..33ae4930ed 100644 --- a/tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt +++ b/tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt @@ -1,4 +1,5 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_10_invalidCommand_.txt b/tests/test_cli/test_invalid_command_py_3_10_invalidCommand_.txt index e2d4416b81..ac64f94f97 100644 --- a/tests/test_cli/test_invalid_command_py_3_10_invalidCommand_.txt +++ b/tests/test_cli/test_invalid_command_py_3_10_invalidCommand_.txt @@ -1,4 +1,5 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... cz: error: argument {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}: invalid choice: 'invalidCommand' (choose from 'init', 'commit', 'c', 'ls', 'example', 'info', 'schema', 'bump', 'changelog', 'ch', 'check', 'version') diff --git a/tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt index 148b4eacdb..33ae4930ed 100644 --- a/tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt +++ b/tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt @@ -1,4 +1,5 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_11_invalidCommand_.txt b/tests/test_cli/test_invalid_command_py_3_11_invalidCommand_.txt index e2d4416b81..ac64f94f97 100644 --- a/tests/test_cli/test_invalid_command_py_3_11_invalidCommand_.txt +++ b/tests/test_cli/test_invalid_command_py_3_11_invalidCommand_.txt @@ -1,4 +1,5 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... cz: error: argument {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}: invalid choice: 'invalidCommand' (choose from 'init', 'commit', 'c', 'ls', 'example', 'info', 'schema', 'bump', 'changelog', 'ch', 'check', 'version') diff --git a/tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt index 148b4eacdb..33ae4930ed 100644 --- a/tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt +++ b/tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt @@ -1,4 +1,5 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_12_invalidCommand_.txt b/tests/test_cli/test_invalid_command_py_3_12_invalidCommand_.txt index c92220c4dc..e3b00a23b2 100644 --- a/tests/test_cli/test_invalid_command_py_3_12_invalidCommand_.txt +++ b/tests/test_cli/test_invalid_command_py_3_12_invalidCommand_.txt @@ -1,4 +1,5 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... cz: error: argument {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}: invalid choice: 'invalidCommand' (choose from init, commit, c, ls, example, info, schema, bump, changelog, ch, check, version) diff --git a/tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt index 4f0ba2b148..04a06a96a7 100644 --- a/tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt +++ b/tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt @@ -1,3 +1,4 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_13_invalidCommand_.txt b/tests/test_cli/test_invalid_command_py_3_13_invalidCommand_.txt index 749066c556..fa8e3d893f 100644 --- a/tests/test_cli/test_invalid_command_py_3_13_invalidCommand_.txt +++ b/tests/test_cli/test_invalid_command_py_3_13_invalidCommand_.txt @@ -1,3 +1,4 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... cz: error: argument {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}: invalid choice: 'invalidCommand' (choose from init, commit, c, ls, example, info, schema, bump, changelog, ch, check, version) diff --git a/tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt index 4f0ba2b148..04a06a96a7 100644 --- a/tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt +++ b/tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt @@ -1,3 +1,4 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_14_invalidCommand_.txt b/tests/test_cli/test_invalid_command_py_3_14_invalidCommand_.txt index 749066c556..fa8e3d893f 100644 --- a/tests/test_cli/test_invalid_command_py_3_14_invalidCommand_.txt +++ b/tests/test_cli/test_invalid_command_py_3_14_invalidCommand_.txt @@ -1,3 +1,4 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... cz: error: argument {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version}: invalid choice: 'invalidCommand' (choose from init, commit, c, ls, example, info, schema, bump, changelog, ch, check, version) diff --git a/tests/test_cli/test_no_argv_py_3_10_.txt b/tests/test_cli/test_no_argv_py_3_10_.txt index 69f410e96d..aba56be445 100644 --- a/tests/test_cli/test_no_argv_py_3_10_.txt +++ b/tests/test_cli/test_no_argv_py_3_10_.txt @@ -1,4 +1,5 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... @@ -16,6 +17,8 @@ options: e.g., cz -nr 1,2,3 bump. See codes at https://commitizen- tools.github.io/commitizen/exit_codes/ + -v, --version Show the version of the installed commitizen + --report Show system information for reporting bugs commands: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_no_argv_py_3_11_.txt b/tests/test_cli/test_no_argv_py_3_11_.txt index 69f410e96d..aba56be445 100644 --- a/tests/test_cli/test_no_argv_py_3_11_.txt +++ b/tests/test_cli/test_no_argv_py_3_11_.txt @@ -1,4 +1,5 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... @@ -16,6 +17,8 @@ options: e.g., cz -nr 1,2,3 bump. See codes at https://commitizen- tools.github.io/commitizen/exit_codes/ + -v, --version Show the version of the installed commitizen + --report Show system information for reporting bugs commands: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_no_argv_py_3_12_.txt b/tests/test_cli/test_no_argv_py_3_12_.txt index 69f410e96d..aba56be445 100644 --- a/tests/test_cli/test_no_argv_py_3_12_.txt +++ b/tests/test_cli/test_no_argv_py_3_12_.txt @@ -1,4 +1,5 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... @@ -16,6 +17,8 @@ options: e.g., cz -nr 1,2,3 bump. See codes at https://commitizen- tools.github.io/commitizen/exit_codes/ + -v, --version Show the version of the installed commitizen + --report Show system information for reporting bugs commands: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_no_argv_py_3_13_.txt b/tests/test_cli/test_no_argv_py_3_13_.txt index b47528ec3e..b90fc6834b 100644 --- a/tests/test_cli/test_no_argv_py_3_13_.txt +++ b/tests/test_cli/test_no_argv_py_3_13_.txt @@ -1,4 +1,5 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... Commitizen is a powerful release management tool that helps teams maintain consistent and meaningful commit messages while automating version management. @@ -15,6 +16,8 @@ options: e.g., cz -nr 1,2,3 bump. See codes at https://commitizen- tools.github.io/commitizen/exit_codes/ + -v, --version Show the version of the installed commitizen + --report Show system information for reporting bugs commands: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_no_argv_py_3_14_.txt b/tests/test_cli/test_no_argv_py_3_14_.txt index b47528ec3e..b90fc6834b 100644 --- a/tests/test_cli/test_no_argv_py_3_14_.txt +++ b/tests/test_cli/test_no_argv_py_3_14_.txt @@ -1,4 +1,5 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] +usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] + [--report] {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... Commitizen is a powerful release management tool that helps teams maintain consistent and meaningful commit messages while automating version management. @@ -15,6 +16,8 @@ options: e.g., cz -nr 1,2,3 bump. See codes at https://commitizen- tools.github.io/commitizen/exit_codes/ + -v, --version Show the version of the installed commitizen + --report Show system information for reporting bugs commands: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} From bffea3dc11c50dff4190437faba1c1832eef3463 Mon Sep 17 00:00:00 2001 From: Tim Hsiung Date: Mon, 4 May 2026 11:56:41 +0800 Subject: [PATCH 2/3] fix(cli): use argparse for top-level --version/-v and --report flags Replace raw sys.argv checks with proper argparse-based handling by making subcommands optional. This fixes three issues: - cz version --report was intercepted by the top-level handler instead of routing to the Version command - cz -v did not work despite being registered as a shorthand for --version - cz version --report and cz version --commitizen now emit deprecation warnings directing users to use cz --report and cz --version instead Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- commitizen/cli.py | 25 +++++++++---------- commitizen/commands/version.py | 13 ++++++++++ tests/commands/test_version_command.py | 20 +++++++++++++++ tests/test_cli.py | 8 ++++++ ...invalid_command_py_3_10___invalid_arg_.txt | 5 ---- ...invalid_command_py_3_11___invalid_arg_.txt | 5 ---- ...invalid_command_py_3_12___invalid_arg_.txt | 5 ---- ...invalid_command_py_3_13___invalid_arg_.txt | 4 --- ...invalid_command_py_3_14___invalid_arg_.txt | 4 --- 9 files changed, 53 insertions(+), 36 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index fbbe5e4f9f..9eda570868 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -119,7 +119,7 @@ def __call__( ], "subcommands": { "title": "commands", - "required": True, + "required": False, "commands": [ { "name": ["init"], @@ -689,18 +689,6 @@ def main() -> None: parser.print_help(sys.stderr) raise ExpectedExit() - # TODO(bearomorphism): mark `cz version --commitizen` as deprecated after `cz version` feature is stable - if "--version" in sys.argv: - out.write(__version__) - raise ExpectedExit() - - # TODO(bearomorphism): mark `cz version --report` as deprecated after `cz version` feature is stable - if "--report" in sys.argv: - out.write(f"Commitizen Version: {__version__}") - out.write(f"Python Version: {sys.version}") - out.write(f"Operating System: {platform.system()}") - raise ExpectedExit() - # This is for the command required constraint in 2.0 try: args, unknown_args = parser.parse_known_args() @@ -709,6 +697,17 @@ def main() -> None: raise NoCommandFoundError() raise e + if not hasattr(args, "func"): + if getattr(args, "version", False): + out.write(__version__) + raise ExpectedExit() + if getattr(args, "report", False): + out.write(f"Commitizen Version: {__version__}") + out.write(f"Python Version: {sys.version}") + out.write(f"Operating System: {platform.system()}") + raise ExpectedExit() + raise NoCommandFoundError() + arguments = vars(args) if unknown_args: # Raise error for extra-args without -- separation diff --git a/commitizen/commands/version.py b/commitizen/commands/version.py index 2a4bcea88a..2376589d48 100644 --- a/commitizen/commands/version.py +++ b/commitizen/commands/version.py @@ -1,5 +1,6 @@ import platform import sys +import warnings from typing import TypedDict from packaging.version import InvalidVersion @@ -45,6 +46,12 @@ def __init__(self, config: BaseConfig, arguments: VersionArgs) -> None: def __call__(self) -> None: if self.arguments.get("report"): + warnings.warn( + "`cz version --report` is deprecated and will be removed in v5. " + "Use `cz --report` instead.", + DeprecationWarning, + stacklevel=2, + ) out.write(f"Commitizen Version: {__version__}") out.write(f"Python Version: {sys.version}") out.write(f"Operating System: {platform.system()}") @@ -54,6 +61,12 @@ def __call__(self) -> None: out.write(f"Installed Commitizen Version: {__version__}") if self.arguments.get("commitizen"): + warnings.warn( + "`cz version --commitizen` is deprecated and will be removed in v5. " + "Use `cz --version` instead.", + DeprecationWarning, + stacklevel=2, + ) out.write(__version__) return diff --git a/tests/commands/test_version_command.py b/tests/commands/test_version_command.py index 099e7110e7..bbca193c70 100644 --- a/tests/commands/test_version_command.py +++ b/tests/commands/test_version_command.py @@ -296,3 +296,23 @@ def test_version_no_arguments_shows_commitizen_version(config, capsys): commands.Version(config, {})() captured = capsys.readouterr() assert captured.out.strip() == __version__ + + +def test_version_report_emits_deprecation_warning(config, capsys): + with pytest.warns( + DeprecationWarning, + match=r"`cz version --report` is deprecated.*Use `cz --report` instead", + ): + commands.Version(config, {"report": True})() + captured = capsys.readouterr() + assert f"Commitizen Version: {__version__}" in captured.out + + +def test_version_commitizen_emits_deprecation_warning(config, capsys): + with pytest.warns( + DeprecationWarning, + match=r"`cz version --commitizen` is deprecated.*Use `cz --version` instead", + ): + commands.Version(config, {"commitizen": True})() + captured = capsys.readouterr() + assert __version__ in captured.out diff --git a/tests/test_cli.py b/tests/test_cli.py index 15e5bcb55c..878f6783ab 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -64,6 +64,14 @@ def test_cz_with_version_arg(util: UtilFixture, capsys): assert __version__ in out +def test_cz_with_version_short_arg(util: UtilFixture, capsys): + """Test that cz shows the version when -v is used.""" + with pytest.raises(ExpectedExit): + util.run_cli("-v") + out, _ = capsys.readouterr() + assert __version__ in out + + def test_cz_with_report_arg(util: UtilFixture, capsys): """Test that cz shows the report when --report is used.""" with pytest.raises(ExpectedExit): diff --git a/tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt index 33ae4930ed..e69de29bb2 100644 --- a/tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt +++ b/tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt @@ -1,5 +0,0 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] - [--report] - {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} - ... -cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt index 33ae4930ed..e69de29bb2 100644 --- a/tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt +++ b/tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt @@ -1,5 +0,0 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] - [--report] - {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} - ... -cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt index 33ae4930ed..e69de29bb2 100644 --- a/tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt +++ b/tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt @@ -1,5 +0,0 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] - [--report] - {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} - ... -cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt index 04a06a96a7..e69de29bb2 100644 --- a/tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt +++ b/tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt @@ -1,4 +0,0 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] - [--report] - {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... -cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} diff --git a/tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt b/tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt index 04a06a96a7..e69de29bb2 100644 --- a/tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt +++ b/tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt @@ -1,4 +0,0 @@ -usage: cz [-h] [--config CONFIG] [--debug] [-n NAME] [-nr NO_RAISE] [-v] - [--report] - {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} ... -cz: error: the following arguments are required: {init,commit,c,ls,example,info,schema,bump,changelog,ch,check,version} From 1e6afc2b87a6f48b02bad5acf1b694858d3b58de Mon Sep 17 00:00:00 2001 From: Tim Hsiung Date: Mon, 4 May 2026 12:05:10 +0800 Subject: [PATCH 3/3] fix(cli): make --version and --report take precedence over subcommands Top-level meta flags like --version and --report now take priority even when a subcommand is also provided (e.g., cz --version bump shows the version instead of running bump). The --report flag correctly defers to the version subcommand when used as cz version --report. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- commitizen/cli.py | 20 ++++++++++++-------- tests/test_cli.py | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index 9eda570868..99bf1d7352 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -697,15 +697,19 @@ def main() -> None: raise NoCommandFoundError() raise e + if getattr(args, "version", False): + out.write(__version__) + raise ExpectedExit() + + if getattr(args, "report", False) and ( + not hasattr(args, "func") or args.func is not commands.Version + ): + out.write(f"Commitizen Version: {__version__}") + out.write(f"Python Version: {sys.version}") + out.write(f"Operating System: {platform.system()}") + raise ExpectedExit() + if not hasattr(args, "func"): - if getattr(args, "version", False): - out.write(__version__) - raise ExpectedExit() - if getattr(args, "report", False): - out.write(f"Commitizen Version: {__version__}") - out.write(f"Python Version: {sys.version}") - out.write(f"Operating System: {platform.system()}") - raise ExpectedExit() raise NoCommandFoundError() arguments = vars(args) diff --git a/tests/test_cli.py b/tests/test_cli.py index 878f6783ab..1d08df2a2d 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -72,6 +72,14 @@ def test_cz_with_version_short_arg(util: UtilFixture, capsys): assert __version__ in out +def test_cz_version_flag_takes_precedence_over_subcommand(util: UtilFixture, capsys): + """Test that --version takes precedence even when a subcommand is given.""" + with pytest.raises(ExpectedExit): + util.run_cli("--version", "bump") + out, _ = capsys.readouterr() + assert __version__ in out + + def test_cz_with_report_arg(util: UtilFixture, capsys): """Test that cz shows the report when --report is used.""" with pytest.raises(ExpectedExit): @@ -82,6 +90,14 @@ def test_cz_with_report_arg(util: UtilFixture, capsys): assert "Operating System:" in out +def test_cz_report_flag_takes_precedence_over_subcommand(util: UtilFixture, capsys): + """Test that --report takes precedence over non-version subcommands.""" + with pytest.raises(ExpectedExit): + util.run_cli("--report", "bump") + out, _ = capsys.readouterr() + assert "Commitizen Version:" in out + + def test_name(util: UtilFixture, capsys): util.run_cli("-n", "cz_jira", "example") out, _ = capsys.readouterr()