Skip to content

Commit 38b02dc

Browse files
fix(bump): only consider commit titles when matching bump patterns
`find_increment` previously scanned every line of every commit message when looking for the conventional-commits type token. Auto-generated commit bodies (notably Dependabot PR descriptions that quote upstream changelog lines like `fix: ...`) frequently contain text that matches the bump pattern even though no in-repo change of that type happened. The result was false-positive `PATCH` bumps on plain `ci:` commits (#1772). Restrict type-pattern matching to the commit title (the first line), where the conventional-commits type lives. The body is still scanned, but only for `BREAKING CHANGE:` / `BREAKING-CHANGE:` footers, which the spec places there. Other body lines no longer drive the increment. Closes #1772 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 4d99415 commit 38b02dc

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

commitizen/bump.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,20 @@ def find_increment(
3434
increment: str | None = None
3535

3636
for commit in commits:
37-
for message in commit.message.split("\n"):
37+
# We only consider:
38+
# * the commit title (the first line, where the commit type lives), and
39+
# * lines in the body that are a ``BREAKING CHANGE:`` /
40+
# ``BREAKING-CHANGE:`` footer (per the Conventional Commits spec).
41+
# Scanning every body line for type-prefixed text matches generated
42+
# commit bodies (e.g. Dependabot quoting an upstream changelog with a
43+
# ``fix:`` line) and produces false-positive bumps -- see #1772.
44+
candidate_lines = [commit.title]
45+
for body_line in commit.body.split("\n"):
46+
stripped = body_line.lstrip()
47+
if stripped.startswith(("BREAKING CHANGE:", "BREAKING-CHANGE:")):
48+
candidate_lines.append(stripped)
49+
50+
for message in candidate_lines:
3851
result = select_pattern.search(message)
3952

4053
if result:

tests/test_bump_find_increment.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,51 @@ def test_find_increment_sve(messages, expected_type):
122122
commits, regex=semantic_version_pattern, increments_map=semantic_version_map
123123
)
124124
assert increment_type == expected_type
125+
126+
127+
# Mimics the dependabot pull request body that triggered #1772: a ``ci:``
128+
# title with a commit body that quotes upstream changelog lines, including
129+
# ``fix: ...`` text. None of the body lines should bump the version.
130+
DEPENDABOT_BODY = (
131+
"Bumps actions/upload-artifact from 5 to 6.\n"
132+
"<details>\n"
133+
"<summary>Commits</summary>\n"
134+
"<ul>\n"
135+
'<li><a href="...">b5b1a91</a>\n'
136+
"fix: update <code>@​actions/artifact</code> to ^5.0.0 for Node.js 24\n"
137+
"punycode fix</li>\n"
138+
'<li><a href="...">5f643d3</a>\n'
139+
"chore: update license files</li>\n"
140+
"</ul>\n"
141+
"</details>\n"
142+
)
143+
144+
145+
def test_find_increment_ignores_type_tokens_in_commit_body():
146+
"""Regression test for #1772: a ``ci:`` commit whose body lists upstream
147+
commit messages -- including ones that look like ``fix:`` -- must not
148+
trigger a PATCH bump. Only the title's commit type counts."""
149+
commit = GitCommit(rev="test", title="ci: bump dep", body=DEPENDABOT_BODY)
150+
increment_type = bump.find_increment(
151+
[commit],
152+
regex=ConventionalCommitsCz.bump_pattern,
153+
increments_map=ConventionalCommitsCz.bump_map,
154+
)
155+
assert increment_type is None
156+
157+
158+
def test_find_increment_still_honors_breaking_change_in_body():
159+
"""The ``BREAKING CHANGE:`` / ``BREAKING-CHANGE:`` footer in a commit body
160+
must still trigger a MAJOR bump even after the #1772 fix; only commit
161+
*types* are now restricted to the title."""
162+
commit = GitCommit(
163+
rev="test",
164+
title="feat: new user interface",
165+
body="some body content\n\nBREAKING CHANGE: age is no longer supported",
166+
)
167+
increment_type = bump.find_increment(
168+
[commit],
169+
regex=ConventionalCommitsCz.bump_pattern,
170+
increments_map=ConventionalCommitsCz.bump_map,
171+
)
172+
assert increment_type == "MAJOR"

0 commit comments

Comments
 (0)