feat(cli): add cz --version back and add cz --report to separate them from cz version#1798
feat(cli): add cz --version back and add cz --report to separate them from cz version#1798bearomorphism wants to merge 8 commits intomasterfrom
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1798 +/- ##
==========================================
+ Coverage 98.23% 98.24% +0.01%
==========================================
Files 61 61
Lines 2772 2799 +27
==========================================
+ Hits 2723 2750 +27
Misses 49 49 ☔ View full report in Codecov by Sentry. |
072aa76 to
a42800c
Compare
|
Will deprecate |
|
Good. Remember that the existing ones, under |
a42800c to
fa9331c
Compare
There was a problem hiding this comment.
Pull request overview
This PR adjusts the Commitizen CLI interface to reintroduce a top-level cz --version/-v and add a top-level cz --report, separating these concerns from the evolving cz version subcommand (per #1785).
Changes:
- Added global
--version/-vhandling to print the installed Commitizen version and exit. - Added global
--reporthandling to print system info for bug reports and exit. - Deprecated
cz version --reportandcz version --commitizenvia warnings, and updated CLI regression snapshots/tests accordingly.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_cli/test_no_argv_py_3_14_.txt | Updates help output snapshot to include global -v/--version and --report. |
| tests/test_cli/test_no_argv_py_3_13_.txt | Updates help output snapshot to include global -v/--version and --report. |
| tests/test_cli/test_no_argv_py_3_12_.txt | Updates help output snapshot to include global -v/--version and --report. |
| tests/test_cli/test_no_argv_py_3_11_.txt | Updates help output snapshot to include global -v/--version and --report. |
| tests/test_cli/test_no_argv_py_3_10_.txt | Updates help output snapshot to include global -v/--version and --report. |
| tests/test_cli/test_invalid_command_py_3_14_invalidCommand_.txt | Updates invalid-command snapshot to reflect new global options in usage. |
| tests/test_cli/test_invalid_command_py_3_14___invalid_arg_.txt | Modifies invalid-arg snapshot file content (currently emptied in this PR). |
| tests/test_cli/test_invalid_command_py_3_13_invalidCommand_.txt | Updates invalid-command snapshot to reflect new global options in usage. |
| tests/test_cli/test_invalid_command_py_3_13___invalid_arg_.txt | Modifies invalid-arg snapshot file content (currently emptied in this PR). |
| tests/test_cli/test_invalid_command_py_3_12_invalidCommand_.txt | Updates invalid-command snapshot to reflect new global options in usage. |
| tests/test_cli/test_invalid_command_py_3_12___invalid_arg_.txt | Modifies invalid-arg snapshot file content (currently emptied in this PR). |
| tests/test_cli/test_invalid_command_py_3_11_invalidCommand_.txt | Updates invalid-command snapshot to reflect new global options in usage. |
| tests/test_cli/test_invalid_command_py_3_11___invalid_arg_.txt | Modifies invalid-arg snapshot file content (currently emptied in this PR). |
| tests/test_cli/test_invalid_command_py_3_10_invalidCommand_.txt | Updates invalid-command snapshot to reflect new global options in usage. |
| tests/test_cli/test_invalid_command_py_3_10___invalid_arg_.txt | Modifies invalid-arg snapshot file content (currently emptied in this PR). |
| tests/test_cli.py | Adds tests for global --version/-v and --report behavior/precedence. |
| tests/commands/test_version_command.py | Adds tests ensuring deprecated cz version --report/--commitizen emit warnings. |
| commitizen/commands/version.py | Emits deprecation warnings for cz version --report and cz version --commitizen. |
| commitizen/cli.py | Adds global args (--version/-v, --report) and implements top-level handling logic. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 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() |
| 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) |
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>
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>
…d conflict Use dest='global_report' for the top-level --report flag so it does not share the same attribute as the version subcommand's --report. This ensures 'cz --report version' behaves as a top-level report instead of routing through the version subcommand with a deprecation warning. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Revert the global_report dest approach. Keep --report as a simple top-level flag that works only without a subcommand, matching the original intent. Update version.md and README.md to document the new cz --version/-v and cz --report top-level flags. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
3b5f594 to
12584e3
Compare
Consolidate three separate version flag tests into a single parametrized test. Merge standalone deprecation warning tests into the existing test_version_for_showing_commitizen_version and test_version_for_showing_commitizen_system_info tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When invoked with unknown arguments and no subcommand (e.g. `cz --invalid-arg`), the parser silently fell through to `NoCommandFoundError` because `parse_known_args()` collects unknown args without erroring. Re-run `parser.parse_args()` in that path so argparse's `unrecognized arguments` error is surfaced to stderr, then convert the `SystemExit` into `NoCommandFoundError` to keep the existing exit-code contract. Regenerate the empty `test_invalid_command_py_*___invalid_arg_.txt` regression baselines accordingly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
`parser.parse_args()` in this guard is only invoked when `parse_known_args()` already produced unknown args, so it can only raise `SystemExit(2)`. Catch `SystemExit` unconditionally and convert it into `NoCommandFoundError` so codecov/patch is no longer blocked by an unreachable `raise e` branch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Analysis: impact of
|
| Setting | Behavior when no subcommand given |
|---|---|
True (master) |
argparse aborts with cz: error: the following arguments are required: {init,…,version} and exits before user code runs. |
False (this PR) |
argparse accepts the args silently. args.func simply isn't set; main() decides what to do. |
The flip is necessary for cz --version / cz -v / cz --report to work without a subcommand.
Master vs PR — direct comparison
Verified locally on Windows / Python 3.13. Exit codes unchanged across the board.
| Input | Master stderr | PR stderr | Exit |
|---|---|---|---|
cz |
help (unchanged) | help (unchanged) | 0 = 0 |
cz --debug |
argparse "the following arguments are required: …" + "Command is required" | "Command is required" | 13 = 13 |
cz -n cz_jira |
same as above | "Command is required" | 13 = 13 |
cz --invalid-arg |
argparse "the following arguments are required: …" (misleading — real issue is the unknown flag) | argparse "unrecognized arguments: --invalid-arg" (accurate) | 13 = 13 |
cz invalidCommand |
argparse "invalid choice" | argparse "invalid choice" | 13 = 13 |
cz init, cz commit, … |
normal | normal | unchanged |
cz init --invalid-arg |
InvalidCommandArgumentError |
InvalidCommandArgumentError |
18 = 18 |
cz --version / -v |
n/a | prints installed version | new |
cz --report |
n/a | prints version/python/OS | new |
Regression assessment
Functional: none.
- Every exit code is preserved, including the documented
cz --debug→ 13 contract indocs/exit_codes.md:25. - Every previously valid invocation still works.
- Every previously invalid invocation still errors with the same exit code.
grep -r "following arguments are required" .andgrep -r "subcommands.*required"turn up nothing — no code, tests, or docs parse the old argparse string.
UX: minor cosmetic changes, neutral-to-positive.
- For "global-flag-only" invocations (
cz --debug,cz -n NAME) without a subcommand, users no longer see the argparse usage block before the "Command is required" error. They still get a clear actionable error and can runcz(no args) for the full help. Very niche scenario. - For typos like
cz --invalid-arg, the error is now strictly more accurate ("unrecognized arguments: --invalid-arg" vs. the misleading "the following arguments are required").
Tests: test_no_argv, test_invalid_command[--invalid-arg], test_invalid_command[invalidCommand], test_cz_with_arg_but_without_command, test_cz_with_version_arg, test_cz_with_report_arg, test_unknown_args_raises, test_unknown_args_before_double_dash_raises all pass; the full python-check matrix (3.10–3.14 × ubuntu/macos/windows) is green.
Generated-by: GitHub Copilot following the guidelines
Description
Currently, all of
cz version,cz version --commitizen, andcz version --reportprint the installed Commitizen version / system info. As we extendcz versionto also report the project version (see #1785), it makes sense to extract those two installed-Commitizen / bug-report concerns out of theversionsubcommand and back into top-level flags:cz --version/cz -v— print the installed Commitizen version and exit.cz --report— print Commitizen version, Python version, and OS, intended for bug reports, and exit.The corresponding subcommand options are kept and emit a
DeprecationWarningpointing at the new flags; they will be removed in v5.Closes part of #1785.
Checklist
Was generative AI tooling used to co-author this PR?
Generated-by: GitHub Copilot following the guidelines
Code Changes
uv run poe alllocally to ensure this change passes linter check and testscz version --commitizen/cz version --reportkeep working with deprecation warnings)Documentation Changes
uv run poe doclocally to ensure the documentation pages renders correctlyExpected Behavior
cz --version/cz -vcz --reportcz --report versionversionsubcommand (top-level--reportis a "no subcommand" flag — kept simple by design).cz version --commitizenDeprecationWarningpointing atcz --version.cz version --reportDeprecationWarningpointing atcz --report.cz --invalid-argunrecognized arguments: --invalid-arg(previously silently fell through).cz(no args)cz invalidCommandinvalid choiceerror — unchanged.Steps to Test This Pull Request
Additional Context
Related: #1785.
Reviewer feedback addressed in this PR:
tests/test_cli/test_invalid_command_py_*___invalid_arg_.txtbaselines were a side effect of changingsubcommands.requiredtoFalse(needed so the new top-level flags work without a subcommand).parse_known_args()then silently swallowed--invalid-arg. Fixed by re-runningparser.parse_args()when there is no subcommand and unknown args are present, so argparse'sunrecognized argumentserror reaches stderr; baselines regenerated for Python 3.10–3.14.cz --report versionroute to the top-level--reportwas intentionally left as-is:--reportstays a simple "no subcommand" flag (per @woile's note: existingcz version --*options are kept until all the new features are out, then removed in v5).