-
-
Notifications
You must be signed in to change notification settings - Fork 334
feat(version): add MANUAL_VERSION, --next and --patch to version command #1724
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
4482093
54db154
5212b31
55ee3b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,22 +2,32 @@ | |||||||||
| import sys | ||||||||||
| from typing import TypedDict | ||||||||||
|
|
||||||||||
| from packaging.version import InvalidVersion | ||||||||||
|
|
||||||||||
| from commitizen import out | ||||||||||
| from commitizen.__version__ import __version__ | ||||||||||
| 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_increment import VersionIncrement | ||||||||||
| from commitizen.version_schemes import get_version_scheme | ||||||||||
|
|
||||||||||
|
|
||||||||||
| class VersionArgs(TypedDict, total=False): | ||||||||||
| manual_version: str | None | ||||||||||
| next: str | None | ||||||||||
|
|
||||||||||
| # Exclusive groups 1 | ||||||||||
| commitizen: bool | ||||||||||
| report: bool | ||||||||||
| project: bool | ||||||||||
| verbose: bool | ||||||||||
|
|
||||||||||
| # Exclusive groups 2 | ||||||||||
| major: bool | ||||||||||
| minor: bool | ||||||||||
| patch: bool | ||||||||||
| tag: bool | ||||||||||
|
|
||||||||||
|
|
||||||||||
|
|
@@ -43,40 +53,74 @@ def __call__(self) -> None: | |||||||||
| if self.arguments.get("verbose"): | ||||||||||
| out.write(f"Installed Commitizen Version: {__version__}") | ||||||||||
|
|
||||||||||
| if not self.arguments.get("commitizen") and ( | ||||||||||
| self.arguments.get("project") or self.arguments.get("verbose") | ||||||||||
| if self.arguments.get("commitizen"): | ||||||||||
| out.write(__version__) | ||||||||||
| return | ||||||||||
|
|
||||||||||
| if ( | ||||||||||
| self.arguments.get("project") | ||||||||||
| or self.arguments.get("verbose") | ||||||||||
| or self.arguments.get("next") | ||||||||||
| or self.arguments.get("manual_version") | ||||||||||
| ): | ||||||||||
| version_str = self.arguments.get("manual_version") | ||||||||||
| if version_str is None: | ||||||||||
| try: | ||||||||||
| version_str = get_provider(self.config).get_version() | ||||||||||
| except NoVersionSpecifiedError: | ||||||||||
| out.error("No project information in this project.") | ||||||||||
| return | ||||||||||
| try: | ||||||||||
| version = get_provider(self.config).get_version() | ||||||||||
| except NoVersionSpecifiedError: | ||||||||||
| out.error("No project information in this project.") | ||||||||||
| return | ||||||||||
| try: | ||||||||||
| version_scheme = get_version_scheme(self.config.settings)(version) | ||||||||||
| scheme_factory = get_version_scheme(self.config.settings) | ||||||||||
| except VersionSchemeUnknown: | ||||||||||
| out.error("Unknown version scheme.") | ||||||||||
| return | ||||||||||
|
|
||||||||||
| try: | ||||||||||
| version = scheme_factory(version_str) | ||||||||||
| except InvalidVersion: | ||||||||||
| out.error(f"Invalid version: '{version_str}'") | ||||||||||
| return | ||||||||||
|
|
||||||||||
| if next_increment_str := self.arguments.get("next"): | ||||||||||
| if next_increment_str == "USE_GIT_COMMITS": | ||||||||||
| # TODO: implement this | ||||||||||
| raise NotImplementedError("USE_GIT_COMMITS is not implemented") | ||||||||||
|
||||||||||
| # TODO: implement this | |
| raise NotImplementedError("USE_GIT_COMMITS is not implemented") | |
| out.error("--next USE_GIT_COMMITS is not implemented yet.") | |
| return |
Copilot
AI
Apr 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VersionIncrement.safe_cast() can return NONE, but the code passes "NONE" into version.bump(). bump() is typed/implemented around Increment | None (MAJOR/MINOR/PATCH/None), so this can break custom schemes that validate the increment. Consider mapping VersionIncrement.NONE to None (no bump) and avoiding the type: ignore by passing a valid Increment | None.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize now that this creates problems with the (not)monotonic kind of versions (and possible non-semver). I'm not sure what to do about it.
I think for now it's fine that if you diverge too much from semver in your custom version scheme, then you won't get the full range of features.
Copilot
AI
Apr 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new --patch output path isn’t covered by tests (there are tests for --major/--minor, but none for --patch). Adding a simple assertion for the patch component would protect this behavior from regressions.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -14,17 +14,14 @@ | |||||
| from commitizen.version_schemes import ( | ||||||
| DEFAULT_SCHEME, | ||||||
| InvalidVersion, | ||||||
| Version, | ||||||
| VersionScheme, | ||||||
| VersionProtocol, | ||||||
| get_version_scheme, | ||||||
| ) | ||||||
|
|
||||||
| if TYPE_CHECKING: | ||||||
| import sys | ||||||
| from collections.abc import Iterable, Sequence | ||||||
|
|
||||||
| from commitizen.version_schemes import VersionScheme | ||||||
|
|
||||||
| # Self is Python 3.11+ but backported in typing-extensions | ||||||
| if sys.version_info < (3, 11): | ||||||
| from typing_extensions import Self | ||||||
|
|
@@ -75,15 +72,15 @@ class TagRules: | |||||
| assert not rules.is_version_tag("warn1.0.0", warn=True) # Does warn | ||||||
|
|
||||||
| assert rules.search_version("# My v1.0.0 version").version == "1.0.0" | ||||||
| assert rules.extract_version("v1.0.0") == Version("1.0.0") | ||||||
| assert rules.extract_version("v1.0.0") == VersionProtocol("1.0.0") | ||||||
|
||||||
| assert rules.extract_version("v1.0.0") == VersionProtocol("1.0.0") | |
| assert rules.extract_version("v1.0.0") == rules.scheme("1.0.0") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| from enum import IntEnum | ||
|
|
||
|
|
||
| class VersionIncrement(IntEnum): | ||
|
bearomorphism marked this conversation as resolved.
|
||
| """An enumeration representing semantic versioning increments. | ||
| This class defines the four types of version increments according to semantic versioning: | ||
| - NONE: For commits that don't require a version bump (docs, style, etc.) | ||
| - PATCH: For backwards-compatible bug fixes | ||
| - MINOR: For backwards-compatible functionality additions | ||
| - MAJOR: For incompatible API changes | ||
| """ | ||
|
|
||
| NONE = 0 | ||
| PATCH = 1 | ||
| MINOR = 2 | ||
| MAJOR = 3 | ||
|
|
||
| def __str__(self) -> str: | ||
| return self.name | ||
|
|
||
| @classmethod | ||
| def safe_cast(cls, value: object) -> "VersionIncrement": | ||
|
bearomorphism marked this conversation as resolved.
Outdated
|
||
| if not isinstance(value, str): | ||
| return VersionIncrement.NONE | ||
| try: | ||
| return cls[value] | ||
| except KeyError: | ||
| return VersionIncrement.NONE | ||
Uh oh!
There was an error while loading. Please reload this page.