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``.