Skip to content

Commit c349d86

Browse files
committed
fix: only use version tags when generating a changelog
This commit ensures that the tags used to generate the changelog are all correctly parsed by Version() This fixes two bugs: - The header of the changelog could be a non-version tag - The rev-range computed when running could use a non-version tag as a lower bound
1 parent 4060cc2 commit c349d86

File tree

7 files changed

+242
-7
lines changed

7 files changed

+242
-7
lines changed

commitizen/changelog.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ def get_version(tag: GitTag) -> Optional[Version]:
6161
return version
6262

6363

64+
def get_version_tags(tags: List[GitTag]) -> List[GitTag]:
65+
return list(filter(get_version, tags))
66+
67+
6468
def tag_included_in_changelog(
6569
tag: GitTag, used_tags: List, merge_prerelease: bool
6670
) -> bool:

commitizen/commands/changelog.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def __call__(self):
138138
# Don't continue if no `file_name` specified.
139139
assert self.file_name
140140

141-
tags = git.get_tags()
141+
tags = changelog.get_version_tags(git.get_tags())
142142
if not tags:
143143
tags = []
144144

commitizen/git.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,14 @@ def tag(tag: str, annotated: bool = False, signed: bool = False) -> cmd.Command:
9292
return c
9393

9494

95-
def commit(message: str, args: str = "") -> cmd.Command:
95+
def commit(
96+
message: str, args: str = "", committer_date: Optional[str] = None
97+
) -> cmd.Command:
9698
f = NamedTemporaryFile("wb", delete=False)
9799
f.write(message.encode("utf-8"))
98100
f.close()
99-
c = cmd.run(f"git commit {args} -F {f.name}")
101+
FLAGS = f"GIT_COMMITTER_DATE={committer_date}" if committer_date else ""
102+
c = cmd.run(f"{FLAGS} git commit {args} -F {f.name}")
100103
os.unlink(f.name)
101104
return c
102105

poetry.lock

Lines changed: 128 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ types-termcolor = "^0.1.1"
6969
# documentation
7070
mkdocs = "^1.4.2"
7171
mkdocs-material = "^9.1.6"
72+
deprecated = "^1.2.13"
73+
types-deprecated = "^1.2.9.2"
74+
types-python-dateutil = "^2.8.19.13"
7275

7376

7477
[tool.poetry.scripts]

tests/commands/test_changelog_command.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import pytest
66
from pytest_mock import MockFixture
7+
from dateutil import relativedelta
78

89
from commitizen import cli, git
910
from commitizen.commands.changelog import Changelog
@@ -17,6 +18,7 @@
1718
from tests.utils import (
1819
create_branch,
1920
create_file_and_commit,
21+
create_tag,
2022
get_current_branch,
2123
merge_branch,
2224
switch_branch,
@@ -1271,3 +1273,88 @@ def test_changelog_prerelease_rev_with_use_version_type_semver(
12711273
out, _ = capsys.readouterr()
12721274

12731275
file_regression.check(out, extension=".second-prerelease.md")
1276+
1277+
1278+
@pytest.mark.usefixtures("tmp_commitizen_project")
1279+
def test_changelog_uses_version_tags_for_header(mocker: MockFixture, config):
1280+
"""Tests that changelog headers always use version tags even if there are non-version tags
1281+
1282+
This tests a scenario fixed in this commit:
1283+
The first header was using a non-version tag and outputting "## 0-not-a-version" instead of "## 1.0.0"""
1284+
create_file_and_commit("feat: commit in 1.0.0")
1285+
create_tag("0-not-a-version")
1286+
create_tag("1.0.0")
1287+
create_tag("also-not-a-version")
1288+
1289+
write_patch = mocker.patch("commitizen.commands.changelog.out.write")
1290+
1291+
changelog = Changelog(
1292+
config, {"dry_run": True, "incremental": True, "unreleased_version": None}
1293+
)
1294+
1295+
with pytest.raises(DryRunExit):
1296+
changelog()
1297+
1298+
assert write_patch.call_args[0][0].startswith("## 1.0.0")
1299+
1300+
1301+
@pytest.mark.usefixtures("tmp_commitizen_project")
1302+
def test_changelog_from_current_version_tag_with_nonversion_tag(
1303+
mocker: MockFixture, config
1304+
):
1305+
"""Tests that changelog generation for a single version works even if
1306+
there is a non-version tag in the list of tags
1307+
1308+
This tests a scenario which is fixed in this commit:
1309+
You have a commit in between two versions (1.0.0..2.0.0) which is tagged with a non-version tag (not-a-version).
1310+
In this case commitizen should disregard the non-version tag when determining the rev-range & generating the changelog.
1311+
"""
1312+
create_file_and_commit(
1313+
"feat: initial commit",
1314+
committer_date=(
1315+
datetime.now() - relativedelta.relativedelta(seconds=3)
1316+
).isoformat(),
1317+
)
1318+
create_tag("1.0.0")
1319+
1320+
create_file_and_commit(
1321+
"feat: commit 1",
1322+
committer_date=(
1323+
datetime.now() - relativedelta.relativedelta(seconds=2)
1324+
).isoformat(),
1325+
)
1326+
create_tag("1-not-a-version")
1327+
1328+
create_file_and_commit(
1329+
"feat: commit 2",
1330+
committer_date=(
1331+
datetime.now() - relativedelta.relativedelta(seconds=1)
1332+
).isoformat(),
1333+
)
1334+
1335+
create_file_and_commit("bump: version 1.0.0 → 2.0.0")
1336+
create_tag("2.0.0")
1337+
1338+
mocker.patch("commitizen.git.GitTag.date", "2022-02-13")
1339+
write_patch = mocker.patch("commitizen.commands.changelog.out.write")
1340+
1341+
changelog = Changelog(
1342+
config,
1343+
{
1344+
"dry_run": True,
1345+
"incremental": False,
1346+
"unreleased_version": None,
1347+
"rev_range": "2.0.0",
1348+
},
1349+
)
1350+
1351+
with pytest.raises(DryRunExit):
1352+
changelog()
1353+
1354+
full_changelog = "\
1355+
## 2.0.0 (2022-02-13)\n\n\
1356+
### Feat\n\n\
1357+
- commit 2\n\
1358+
- commit 1\n"
1359+
1360+
write_patch.assert_called_with(full_changelog)

0 commit comments

Comments
 (0)