Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8123bcb

Browse files
sacha-cLee-W
authored andcommitted
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 e7d81d6 commit 8123bcb

File tree

7 files changed

+263
-9
lines changed

7 files changed

+263
-9
lines changed

‎commitizen/changelog.py‎

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,20 @@
3030
import re
3131
from collections import OrderedDict, defaultdict
3232
from datetime import date
33-
from typing import TYPE_CHECKING, Callable, Iterable, cast
33+
from typing import TYPE_CHECKING, Callable, Iterable, Type, cast
3434

3535
from jinja2 import Environment, PackageLoader
3636

37+
from commitizen import out
3738
from commitizen.bump import normalize_tag
3839
from commitizen.exceptions import InvalidConfigurationError, NoCommitsFoundError
3940
from commitizen.git import GitCommit, GitTag
40-
from commitizen.version_schemes import DEFAULT_SCHEME, Pep440, InvalidVersion
41+
from commitizen.version_schemes import (
42+
DEFAULT_SCHEME,
43+
BaseVersion,
44+
InvalidVersion,
45+
Pep440,
46+
)
4147

4248
if TYPE_CHECKING:
4349
from commitizen.version_schemes import VersionScheme
@@ -67,6 +73,19 @@ def tag_included_in_changelog(
6773
return True
6874

6975

76+
def get_version_tags(scheme: Type[BaseVersion], tags: list[GitTag]) -> list[GitTag]:
77+
valid_tags: list[GitTag] = []
78+
for tag in tags:
79+
try:
80+
scheme(tag.name)
81+
except InvalidVersion:
82+
out.warn(f"InvalidVersion {tag}")
83+
else:
84+
valid_tags.append(tag)
85+
86+
return valid_tags
87+
88+
7089
def generate_tree_from_commits(
7190
commits: list[GitCommit],
7291
tags: list[GitTag],

‎commitizen/commands/changelog.py‎

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

140-
tags = git.get_tags()
140+
tags = changelog.get_version_tags(self.scheme, git.get_tags())
141141
if not tags:
142142
tags = []
143143

‎commitizen/git.py‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,22 @@ 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: str | None = 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+
102+
command = f"git commit {args} -F {f.name}"
103+
104+
if committer_date and os.name == "nt": # pragma: no cover
105+
# Using `cmd /v /c "{command}"` sets environment variables only for that command
106+
command = f'cmd /v /c "set GIT_COMMITTER_DATE={committer_date}&& {command}"'
107+
elif committer_date:
108+
command = f"GIT_COMMITTER_DATE={committer_date} {command}"
109+
110+
c = cmd.run(command)
100111
os.unlink(f.name)
101112
return c
102113

‎poetry.lock‎

Lines changed: 124 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,
@@ -1267,3 +1269,88 @@ def test_changelog_prerelease_rev_with_use_scheme_semver(
12671269
out, _ = capsys.readouterr()
12681270

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

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /