From 6a2c9ec372f26617cdea6a127fe93e26bc7df749 Mon Sep 17 00:00:00 2001 From: gataulin_vitaliy Date: Tue, 13 Oct 2026 13:09:17 +0300 Subject: [PATCH] fix(schemes): recognize PEP 440 devrelease tags The default version parser did not match PEP 440 development release tags such as 0.2.0.dev1. As a result, cz bump --devrelease created tags that were not recognized as version tags, and the next incremental changelog run failed with "No tag found to do an incremental changelog". Use the PEP 440 regular expression from the specification appendix, while keeping the version group and the -next pre-release support relied upon by existing tag formats. Closes #1367 --- commitizen/version_schemes.py | 7 +++- tests/commands/test_changelog_command.py | 32 +++++++++++++++++++ ...t_changelog_incremental_with_devrelease.md | 17 ++++++++++ tests/test_tags.py | 20 ++++++++++++ 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 tests/commands/test_changelog_command/test_changelog_incremental_with_devrelease.md diff --git a/commitizen/version_schemes.py b/commitizen/version_schemes.py index 14a55d6554..75b6f75312 100644 --- a/commitizen/version_schemes.py +++ b/commitizen/version_schemes.py @@ -34,7 +34,12 @@ Increment: TypeAlias = Literal["MAJOR", "MINOR", "PATCH"] # TODO: deprecate Prerelease: TypeAlias = Literal["alpha", "beta", "rc"] _DEFAULT_VERSION_PARSER = re.compile( - r"v?(?P([0-9]+)\.([0-9]+)(?:\.([0-9]+))?(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.]+)?(\w+)?)" + r"v?(?P(?:(?P[0-9]+)!)?(?P[0-9]+\.[0-9]+(?:\.[0-9]+)*)" + r"(?P
[-_\.]?(?Pa|b|c|rc|alpha|beta|pre|preview|next|dev)[-_\.]?(?P[0-9]+)?)?"
+    r"(?P(?:-(?P[0-9]+))|(?:[-_\.]?(?Ppost|rev|r)[-_\.]?(?P[0-9]+)?))?"
+    r"(?P[-_\.]?(?Pdev)[-_\.]?(?P[0-9]+)?)?"
+    r"(?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?)",
+    re.IGNORECASE,
 )
 
 
diff --git a/tests/commands/test_changelog_command.py b/tests/commands/test_changelog_command.py
index 8922b256f9..35327763f2 100644
--- a/tests/commands/test_changelog_command.py
+++ b/tests/commands/test_changelog_command.py
@@ -750,6 +750,38 @@ def test_changelog_incremental_with_prerelease_version_to_prerelease_version(
     file_regression.check(out, extension=".md")
 
 
+@pytest.mark.usefixtures("tmp_commitizen_project")
+@pytest.mark.freeze_time("2021-06-11")
+def test_changelog_incremental_with_devrelease(
+    changelog_path: Path,
+    file_regression: FileRegressionFixture,
+    util: UtilFixture,
+):
+    """Regression test for #1367: bumping with ``--devrelease`` twice must
+    update the incremental changelog.
+
+    The second devrelease bump used to fail with
+    "No tag found to do an incremental changelog" because the PEP 440
+    development-release tag (e.g. ``0.2.0.dev0``) was not recognised as a
+    version tag by the default version parser.
+    """
+    util.create_file_and_commit("irrelevant commit")
+    util.create_tag("1.0.0", annotated=True)
+
+    util.create_file_and_commit("feat: add new output")
+    util.create_file_and_commit("fix: output glitch")
+
+    util.run_cli("bump", "--changelog", "--devrelease", "0", "--yes")
+
+    util.create_file_and_commit("feat: add more stuff")
+
+    util.run_cli("bump", "--changelog", "--devrelease", "1", "--yes")
+
+    out = changelog_path.read_text()
+
+    file_regression.check(out, extension=".md")
+
+
 @pytest.mark.parametrize("test_input", ["rc", "alpha", "beta"])
 @pytest.mark.usefixtures("tmp_commitizen_project")
 @pytest.mark.freeze_time("2025-12-29")
diff --git a/tests/commands/test_changelog_command/test_changelog_incremental_with_devrelease.md b/tests/commands/test_changelog_command/test_changelog_incremental_with_devrelease.md
new file mode 100644
index 0000000000..937e178a8c
--- /dev/null
+++ b/tests/commands/test_changelog_command/test_changelog_incremental_with_devrelease.md
@@ -0,0 +1,17 @@
+## 0.2.0.dev1 (2021-06-11)
+
+### Feat
+
+- add more stuff
+
+## 0.2.0.dev0 (2021-06-11)
+
+### Feat
+
+- add new output
+
+### Fix
+
+- output glitch
+
+## 1.0.0 (2021-06-11)
diff --git a/tests/test_tags.py b/tests/test_tags.py
index bdd6714272..48b189b6d2 100644
--- a/tests/test_tags.py
+++ b/tests/test_tags.py
@@ -144,6 +144,26 @@ def test_is_version_tag_accepts_dotless_devrelease_in_custom_tag_format():
     assert str(extracted) == "1.2.3.dev1"
 
 
+def test_is_version_tag_accepts_pep440_devrelease_in_default_tag_format():
+    """Regression test for #1367: a PEP 440 development release tag such as
+    ``0.2.0.dev1`` (created by ``cz bump --devrelease``) must be recognised as
+    a version tag. Previously the default version parser only accepted
+    ``.dev`` suffixes after a hyphen, so the tag was dropped and the
+    incremental changelog failed with "No tag found to do an incremental
+    changelog".
+    """
+    rules = TagRules()
+
+    assert rules.is_version_tag("0.2.0.dev1") is True
+    assert rules.is_version_tag("0.2.0.dev0") is True
+    assert rules.is_version_tag("1.2.3.dev1+build.5") is True
+    assert rules.is_version_tag("1.0.0a2.dev1") is True
+
+    extracted = rules.extract_version(_git_tag("0.2.0.dev1"))
+    assert str(extracted) == "0.2.0.dev1"
+    assert extracted.dev == 1
+
+
 def test_monorepo_ignored_tag_formats_keep_own_tags(capsys: pytest.CaptureFixture):
     """Regression test for the monorepo workflow in
     ``docs/tutorials/monorepo_guidance.md``.