From 82ed0785ccfb09eabccb4eedd584f3c8b84f00d4 Mon Sep 17 00:00:00 2001 From: Ying-Fang Date: Mon, 26 Jan 2026 18:57:25 -0600 Subject: [PATCH 1/2] feat(version): add --tag for version command --- commitizen/cli.py | 6 +++ commitizen/commands/version.py | 13 +++++- ..._when_use_help_option_py_3_10_version_.txt | 3 +- ..._when_use_help_option_py_3_11_version_.txt | 3 +- ..._when_use_help_option_py_3_12_version_.txt | 3 +- ..._when_use_help_option_py_3_13_version_.txt | 3 +- ..._when_use_help_option_py_3_14_version_.txt | 3 +- tests/commands/test_version_command.py | 44 ++++++++++++++++++- 8 files changed, 70 insertions(+), 8 deletions(-) diff --git a/commitizen/cli.py b/commitizen/cli.py index 364bc93f85..9933a29a10 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -541,6 +541,12 @@ def __call__( "action": "store_true", "exclusive_group": "group1", }, + { + "name": ["--tag"], + "help": "get the version with tag prefix", + "action": "store_true", + "exclusive_group": "group2", + }, { "name": ["--major"], "help": "get just the major version. Need to be used with --project or --verbose.", diff --git a/commitizen/commands/version.py b/commitizen/commands/version.py index 9290e80b8f..4faebe0224 100644 --- a/commitizen/commands/version.py +++ b/commitizen/commands/version.py @@ -7,6 +7,7 @@ from commitizen.config import BaseConfig from commitizen.exceptions import NoVersionSpecifiedError, VersionSchemeUnknown from commitizen.providers import get_provider +from commitizen.tags import TagRules from commitizen.version_schemes import get_version_scheme @@ -17,6 +18,7 @@ class VersionArgs(TypedDict, total=False): verbose: bool major: bool minor: bool + tag: bool class Version: @@ -59,6 +61,9 @@ def __call__(self) -> None: version = f"{version_scheme.major}" elif self.arguments.get("minor"): version = f"{version_scheme.minor}" + elif self.arguments.get("tag"): + tag_rules = TagRules.from_settings(self.config.settings) + version = tag_rules.normalize_tag(version_scheme) out.write( f"Project Version: {version}" @@ -67,9 +72,13 @@ def __call__(self) -> None: ) return - if self.arguments.get("major") or self.arguments.get("minor"): + if ( + self.arguments.get("major") + or self.arguments.get("minor") + or self.arguments.get("tag") + ): out.error( - "Major or minor version can only be used with --project or --verbose." + "Major or minor or tag can only be used with --project or --verbose." ) return diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt index a194615a98..1aff02a69a 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_10_version_.txt @@ -1,4 +1,4 @@ -usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] +usage: cz version [-h] [-r | -p | -c | -v] [--tag | --major | --minor] get the version of the installed commitizen or the current project (default: installed commitizen) @@ -10,6 +10,7 @@ options: -c, --commitizen get the version of the installed commitizen -v, --verbose get the version of both the installed commitizen and the current project + --tag get the version with tag prefix --major get just the major version. Need to be used with --project or --verbose. --minor get just the minor version. Need to be used with --project diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt index a194615a98..1aff02a69a 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_11_version_.txt @@ -1,4 +1,4 @@ -usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] +usage: cz version [-h] [-r | -p | -c | -v] [--tag | --major | --minor] get the version of the installed commitizen or the current project (default: installed commitizen) @@ -10,6 +10,7 @@ options: -c, --commitizen get the version of the installed commitizen -v, --verbose get the version of both the installed commitizen and the current project + --tag get the version with tag prefix --major get just the major version. Need to be used with --project or --verbose. --minor get just the minor version. Need to be used with --project diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt index a194615a98..1aff02a69a 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_12_version_.txt @@ -1,4 +1,4 @@ -usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] +usage: cz version [-h] [-r | -p | -c | -v] [--tag | --major | --minor] get the version of the installed commitizen or the current project (default: installed commitizen) @@ -10,6 +10,7 @@ options: -c, --commitizen get the version of the installed commitizen -v, --verbose get the version of both the installed commitizen and the current project + --tag get the version with tag prefix --major get just the major version. Need to be used with --project or --verbose. --minor get just the minor version. Need to be used with --project diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt index a194615a98..1aff02a69a 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_13_version_.txt @@ -1,4 +1,4 @@ -usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] +usage: cz version [-h] [-r | -p | -c | -v] [--tag | --major | --minor] get the version of the installed commitizen or the current project (default: installed commitizen) @@ -10,6 +10,7 @@ options: -c, --commitizen get the version of the installed commitizen -v, --verbose get the version of both the installed commitizen and the current project + --tag get the version with tag prefix --major get just the major version. Need to be used with --project or --verbose. --minor get just the minor version. Need to be used with --project diff --git a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt index a194615a98..1aff02a69a 100644 --- a/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt +++ b/tests/commands/test_common_command/test_command_shows_description_when_use_help_option_py_3_14_version_.txt @@ -1,4 +1,4 @@ -usage: cz version [-h] [-r | -p | -c | -v] [--major | --minor] +usage: cz version [-h] [-r | -p | -c | -v] [--tag | --major | --minor] get the version of the installed commitizen or the current project (default: installed commitizen) @@ -10,6 +10,7 @@ options: -c, --commitizen get the version of the installed commitizen -v, --verbose get the version of both the installed commitizen and the current project + --tag get the version with tag prefix --major get just the major version. Need to be used with --project or --verbose. --minor get just the minor version. Need to be used with --project diff --git a/tests/commands/test_version_command.py b/tests/commands/test_version_command.py index 17f7238403..2ee342d2fe 100644 --- a/tests/commands/test_version_command.py +++ b/tests/commands/test_version_command.py @@ -158,6 +158,48 @@ def test_version_just_major_error_no_project(config, capsys, argument: str): captured = capsys.readouterr() assert not captured.out assert ( - "Major or minor version can only be used with --project or --verbose." + "Major or minor or tag can only be used with --project or --verbose." + in captured.err + ) + + +@pytest.mark.parametrize( + "version, tag_format, expected_output", + [ + ("1.2.3", "v$version", "v1.2.3\n"), + ("1.2.3", "$version", "1.2.3\n"), + ("2.0.0", "release-$version", "release-2.0.0\n"), + ("0.1.0", "ver$version", "ver0.1.0\n"), + ], +) +def test_version_with_tag_format( + config, capsys, version: str, tag_format: str, expected_output: str +): + """Test --tag option applies tag_format to version""" + config.settings["version"] = version + config.settings["tag_format"] = tag_format + commands.Version( + config, + { + "project": True, + "tag": True, + }, + )() + captured = capsys.readouterr() + assert captured.out == expected_output + + +def test_version_tag_without_project_error(config, capsys): + """Test --tag requires --project or --verbose""" + commands.Version( + config, + { + "tag": True, + }, + )() + captured = capsys.readouterr() + assert not captured.out + assert ( + "Major or minor or tag can only be used with --project or --verbose." in captured.err ) From 6e98f8ea0ec9845734573a342aa06765313d4560 Mon Sep 17 00:00:00 2001 From: Ying-Fang Date: Tue, 27 Jan 2026 15:37:32 -0600 Subject: [PATCH 2/2] refactor(version): separate error handling for the version command (--tag/--major/--minor) and their test cases --- commitizen/commands/version.py | 16 ++++---- tests/commands/test_version_command.py | 53 +++++++++++++++----------- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/commitizen/commands/version.py b/commitizen/commands/version.py index 4faebe0224..5092e49d4b 100644 --- a/commitizen/commands/version.py +++ b/commitizen/commands/version.py @@ -72,14 +72,14 @@ def __call__(self) -> None: ) return - if ( - self.arguments.get("major") - or self.arguments.get("minor") - or self.arguments.get("tag") - ): - out.error( - "Major or minor or tag can only be used with --project or --verbose." - ) + if self.arguments.get("major"): + out.error("Major can only be used with --project or --verbose.") + return + if self.arguments.get("minor"): + out.error("Minor can only be used with --project or --verbose.") + return + if self.arguments.get("tag"): + out.error("Tag can only be used with --project or --verbose.") return # If no arguments are provided, just show the installed commitizen version diff --git a/tests/commands/test_version_command.py b/tests/commands/test_version_command.py index 2ee342d2fe..078ee71fcf 100644 --- a/tests/commands/test_version_command.py +++ b/tests/commands/test_version_command.py @@ -147,20 +147,43 @@ def test_version_just_minor(config, capsys, version: str, expected_version: str) assert expected_version == captured.out -@pytest.mark.parametrize("argument", ("major", "minor")) -def test_version_just_major_error_no_project(config, capsys, argument: str): +def test_version_major_error_no_project(config, capsys): + """Test --major requires --project or --verbose""" commands.Version( config, { - argument: True, # type: ignore[misc] + "major": True, }, )() captured = capsys.readouterr() assert not captured.out - assert ( - "Major or minor or tag can only be used with --project or --verbose." - in captured.err - ) + assert "Major can only be used with --project or --verbose." in captured.err + + +def test_version_minor_error_no_project(config, capsys): + """Test --minor requires --project or --verbose""" + commands.Version( + config, + { + "minor": True, + }, + )() + captured = capsys.readouterr() + assert not captured.out + assert "Minor can only be used with --project or --verbose." in captured.err + + +def test_version_tag_error_no_project(config, capsys): + """Test --tag requires --project or --verbose""" + commands.Version( + config, + { + "tag": True, + }, + )() + captured = capsys.readouterr() + assert not captured.out + assert "Tag can only be used with --project or --verbose." in captured.err @pytest.mark.parametrize( @@ -187,19 +210,3 @@ def test_version_with_tag_format( )() captured = capsys.readouterr() assert captured.out == expected_output - - -def test_version_tag_without_project_error(config, capsys): - """Test --tag requires --project or --verbose""" - commands.Version( - config, - { - "tag": True, - }, - )() - captured = capsys.readouterr() - assert not captured.out - assert ( - "Major or minor or tag can only be used with --project or --verbose." - in captured.err - )