Skip to content

Commit 5212b31

Browse files
committed
fix(version): improve coverage, UX, and docs for cz version
- Rename VersionIncrement.safe_cast to from_value; add tests - Map NONE to no bump; user-facing error for USE_GIT_COMMITS - Add tests for patch component, unknown scheme, and default output - Clarify get_version_scheme Protocol check; fix TagRules docstring example - Document MANUAL_VERSION, --next, and --patch; refresh help fixtures/SVG Made-with: Cursor
1 parent 54db154 commit 5212b31

14 files changed

+151
-157
lines changed

commitizen/cli.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,10 @@ def __call__(
567567
},
568568
{
569569
"name": ["--patch"],
570-
"help": "Output the patch version only. Need to be used with MANUAL_VERSION, --project or --verbose.",
570+
"help": (
571+
"Output the patch version only. Must be used with MANUAL_VERSION, "
572+
"--project, or --verbose."
573+
),
571574
"action": "store_true",
572575
"exclusive_group": "group2",
573576
},

commitizen/commands/version.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from commitizen.providers import get_provider
1212
from commitizen.tags import TagRules
1313
from commitizen.version_increment import VersionIncrement
14-
from commitizen.version_schemes import get_version_scheme
14+
from commitizen.version_schemes import Increment, get_version_scheme
1515

1616

1717
class VersionArgs(TypedDict, total=False):
@@ -84,12 +84,20 @@ def __call__(self) -> None:
8484

8585
if next_increment_str := self.arguments.get("next"):
8686
if next_increment_str == "USE_GIT_COMMITS":
87-
# TODO: implement this
88-
raise NotImplementedError("USE_GIT_COMMITS is not implemented")
87+
out.error("--next USE_GIT_COMMITS is not implemented yet.")
88+
return
8989

90-
next_increment = VersionIncrement.safe_cast(next_increment_str)
91-
# TODO: modify the interface of bump to accept VersionIncrement
92-
version = version.bump(increment=str(next_increment)) # type: ignore[arg-type]
90+
next_increment = VersionIncrement.from_value(next_increment_str)
91+
increment: Increment | None
92+
if next_increment == VersionIncrement.NONE:
93+
increment = None
94+
elif next_increment == VersionIncrement.PATCH:
95+
increment = "PATCH"
96+
elif next_increment == VersionIncrement.MINOR:
97+
increment = "MINOR"
98+
else:
99+
increment = "MAJOR"
100+
version = version.bump(increment=increment)
93101

94102
if self.arguments.get("major"):
95103
out.write(version.major)

commitizen/tags.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class TagRules:
7272
assert not rules.is_version_tag("warn1.0.0", warn=True) # Does warn
7373
7474
assert rules.search_version("# My v1.0.0 version").version == "1.0.0"
75-
assert rules.extract_version("v1.0.0") == VersionProtocol("1.0.0")
75+
assert rules.extract_version("v1.0.0") == rules.scheme("1.0.0")
7676
try:
7777
assert rules.extract_version("not-a-v1.0.0")
7878
except InvalidVersion:

commitizen/version_increment.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1+
from __future__ import annotations
2+
13
from enum import IntEnum
24

35

46
class VersionIncrement(IntEnum):
5-
"""An enumeration representing semantic versioning increments.
6-
This class defines the four types of version increments according to semantic versioning:
7-
- NONE: For commits that don't require a version bump (docs, style, etc.)
8-
- PATCH: For backwards-compatible bug fixes
9-
- MINOR: For backwards-compatible functionality additions
10-
- MAJOR: For incompatible API changes
7+
"""Semantic versioning bump increments.
8+
9+
IntEnum keeps a total order compatible with NONE < PATCH < MINOR < MAJOR
10+
for comparisons across the codebase.
11+
12+
- NONE: no bump (docs-only / style commits, etc.)
13+
- PATCH: backwards-compatible bug fixes
14+
- MINOR: backwards-compatible features
15+
- MAJOR: incompatible API changes
1116
"""
1217

1318
NONE = 0
@@ -19,7 +24,7 @@ def __str__(self) -> str:
1924
return self.name
2025

2126
@classmethod
22-
def safe_cast(cls, value: object) -> "VersionIncrement":
27+
def from_value(cls, value: object) -> VersionIncrement:
2328
if not isinstance(value, str):
2429
return VersionIncrement.NONE
2530
try:

commitizen/version_schemes.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,10 @@ def get_version_scheme(
422422
raise VersionSchemeUnknown(f'Version scheme "{name}" unknown.')
423423
scheme = cast("type[VersionProtocol]", ep.load())
424424

425+
# `VersionProtocol` is a `@runtime_checkable` Protocol with properties, so
426+
# `issubclass(scheme, VersionProtocol)` is not supported. The historical
427+
# `isinstance(scheme, VersionProtocol)` check is only meaningful for instances;
428+
# for loaded classes it is effectively a no-op for valid schemes.
425429
if not isinstance(scheme, VersionProtocol):
426430
warnings.warn(f"Version scheme {name} does not implement the VersionProtocol")
427431

docs/commands/version.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
1-
Get the version of the installed Commitizen or the current project (default: installed commitizen)
1+
Get the version of the installed Commitizen or the current project (default: installed commitizen).
22

33
## Usage
44

55
![cz version --help](../images/cli_help/cz_version___help.svg)
66

7-
<!-- TODO: add documentation after this feature is stabilized -->
7+
## Project version and scheme
8+
9+
- **`cz version --project`** prints the version from your configured [version provider](../config/version_provider.md).
10+
- **`cz version MANUAL_VERSION`** (optional positional) uses that string instead of the provider, so you can try how your configured scheme parses and formats it.
11+
12+
## Components and next version
13+
14+
- **`--major`**, **`--minor`**, **`--patch`**: print only that component of the (possibly manual) project version. Requires `--project`, `--verbose`, or a manual version.
15+
- **`--next` `[MAJOR|MINOR|PATCH|NONE]`**: print the version after applying that bump to the current project or manual version. `NONE` leaves the version unchanged.
16+
- **`--tag`**: print the version formatted with your `tag_format` (requires `--project` or `--verbose`).
17+
18+
`--next USE_GIT_COMMITS` is reserved for a future feature (derive the bump from git history) and is not implemented yet.
19+
20+
## Examples
21+
22+
```bash
23+
cz version --project
24+
cz version 2.0.0 --next MAJOR
25+
cz version --project --major
26+
cz version --verbose
27+
```

0 commit comments

Comments
 (0)