diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 18b877b2e..634c1bedf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: - tomli - repo: https://github.com/commitizen-tools/commitizen - rev: v4.16.1 # automatically updated by Commitizen + rev: v4.16.2 # automatically updated by Commitizen hooks: - id: commitizen - id: commitizen-branch diff --git a/commitizen/__version__.py b/commitizen/__version__.py index e7e757cb6..e2111981b 100644 --- a/commitizen/__version__.py +++ b/commitizen/__version__.py @@ -1 +1 @@ -__version__ = "4.16.1" +__version__ = "4.16.2" diff --git a/commitizen/defaults.py b/commitizen/defaults.py index 4865ccc18..84a3f0159 100644 --- a/commitizen/defaults.py +++ b/commitizen/defaults.py @@ -156,8 +156,17 @@ def get_tag_regexes( "major": r"(?P\d+)", "minor": r"(?P\d+)", "patch": r"(?P\d+)", - "prerelease": r"(?P\w+\d+)?", - "devrelease": r"(?P\.dev\d+)?", + # Allow ``\w+`` (PEP-440 ``rc0``) as well as ``\w+\.\w+(\.\w+)*`` + # (SemVer2 ``rc.0``, ``alpha.beta.1``). The original ``\w+\d+`` only + # matched the PEP-440 form and produced "Invalid version tag" warnings + # for SemVer2-style tags created by commitizen itself (#1614). + "prerelease": r"(?P\w+(?:\.\w+)*)?", + # Match either ``.dev1`` (PEP-440 with leading dot) or ``dev1`` + # (SemVer / SemVer2 / users substituting ``${devrelease}`` directly + # in a ``tag_format`` -- see #1615). A bare ``\d+`` after the prefix + # would let the regex match arbitrary numeric suffixes, so the + # ``dev`` literal is required. + "devrelease": r"(?P\.?dev\d+)?", } return { **{f"${k}": v for k, v in regexes.items()}, diff --git a/pyproject.toml b/pyproject.toml index a6402494f..6cc3e985c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "commitizen" -version = "4.16.1" +version = "4.16.2" description = "Python commitizen client tool" authors = [{ name = "Santiago Fraire", email = "santiwilly@gmail.com" }] maintainers = [ diff --git a/tests/test_tags.py b/tests/test_tags.py index 2471b8461..3d5f8fc35 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -99,3 +99,44 @@ def test_find_tag_for_partial_version_ignores_invalid_tags(): assert found is not None assert found.name == "1.2.1" + + +def test_is_version_tag_accepts_semver2_prerelease_in_custom_tag_format(): + """Regression test for #1614: a SemVer2-style prerelease segment such as + ``rc.0`` (with a literal dot) must be recognised when it appears at the + position of ``${prerelease}`` in a custom ``tag_format``. Before the + prerelease regex was widened from ``\\w+\\d+`` to ``\\w+(?:\\.\\w+)*``, + the tag commitizen itself just created emitted "Invalid version tag" + warnings on the next changelog/bump. + """ + from commitizen.version_schemes import get_version_scheme + + scheme = get_version_scheme({"version_scheme": "semver2"}) + rules = TagRules( + scheme=scheme, + tag_format="${major}.${minor}-${patch}${prerelease}", + ) + + assert rules.is_version_tag("0.0-2rc.0") is True + # Plain releases (no prerelease) are still accepted. + assert rules.is_version_tag("0.0-2") is True + # Multi-segment SemVer2 prereleases too. + assert rules.is_version_tag("0.0-2alpha.beta.1") is True + + # And ``extract_version`` round-trips the prerelease portion. + extracted = rules.extract_version(_git_tag("0.0-2rc.0")) + assert str(extracted) == "0.0.2-rc.0" + + +def test_is_version_tag_accepts_dotless_devrelease_in_custom_tag_format(): + """Regression test for #1614: ``${devrelease}`` accepts both ``dev1`` + and ``.dev1`` suffixes when a custom ``tag_format`` splits release and dev + portions explicitly. + """ + rules = TagRules(tag_format="version-${major}.${minor}.${patch}${devrelease}") + + assert rules.is_version_tag("version-1.2.3.dev1") is True + assert rules.is_version_tag("version-1.2.3dev1") is True + + extracted = rules.extract_version(_git_tag("version-1.2.3dev1")) + assert str(extracted) == "1.2.3.dev1" diff --git a/uv.lock b/uv.lock index 40ec44c59..acfbcc1ff 100644 --- a/uv.lock +++ b/uv.lock @@ -216,7 +216,7 @@ wheels = [ [[package]] name = "commitizen" -version = "4.16.1" +version = "4.16.2" source = { editable = "." } dependencies = [ { name = "argcomplete" },