Skip to content

Commit 778edcb

Browse files
fix(bump): Preserve existing changelog header when changelog_merge_prerelease is used with cz bump --changelog, and no prereleases exist
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
1 parent 681a433 commit 778edcb

File tree

3 files changed

+85
-7
lines changed

3 files changed

+85
-7
lines changed

commitizen/commands/changelog.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -227,20 +227,34 @@ def __call__(self) -> None:
227227
latest_full_release_info = self.changelog_format.get_latest_full_release(
228228
self.file_name
229229
)
230-
if latest_full_release_info.index:
230+
# Determine if there are prereleases to merge:
231+
# - Only prereleases in changelog (no full release found), OR
232+
# - First version in changelog is before first full release (prereleases exist)
233+
has_prereleases_to_merge = latest_full_release_info.index is not None and (
234+
latest_full_release_info.name is None
235+
or (
236+
changelog_meta.latest_version_position is not None
237+
and changelog_meta.latest_version_position
238+
< latest_full_release_info.index
239+
)
240+
)
241+
242+
if has_prereleases_to_merge and latest_full_release_info.index is not None:
231243
# Use the existing unreleased_start if available (from get_metadata()).
232244
# Otherwise, use the position of the first version entry (prerelease)
233245
# to preserve the changelog header.
234246
if changelog_meta.unreleased_start is None:
235-
changelog_meta.unreleased_start = changelog_meta.latest_version_position
247+
changelog_meta.unreleased_start = (
248+
changelog_meta.latest_version_position
249+
)
236250
changelog_meta.latest_version_position = latest_full_release_info.index
237251
changelog_meta.unreleased_end = latest_full_release_info.index - 1
238252

239-
start_rev = latest_full_release_info.name or ""
240-
if not start_rev and latest_full_release_info.index:
241-
# Only pre-releases in changelog
242-
changelog_meta.latest_version_position = None
243-
changelog_meta.unreleased_end = latest_full_release_info.index + 1
253+
start_rev = latest_full_release_info.name or ""
254+
if not start_rev:
255+
# Only pre-releases in changelog
256+
changelog_meta.latest_version_position = None
257+
changelog_meta.unreleased_end = latest_full_release_info.index + 1
244258

245259
commits = git.get_commits(start=start_rev, end=end_rev, args="--topo-order")
246260
if not commits and (

tests/commands/test_bump_command.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,51 @@ def test_changelog_merge_prerelease_preserves_header(
15341534
file_regression.check(out, extension=".md")
15351535

15361536

1537+
@pytest.mark.usefixtures("tmp_commitizen_project")
1538+
@pytest.mark.freeze_time("2025-01-01")
1539+
def test_changelog_merge_prerelease_no_prereleases_to_merge(
1540+
mocker: MockFixture,
1541+
util: UtilFixture,
1542+
changelog_path: Path,
1543+
config_path: Path,
1544+
file_regression: FileRegressionFixture,
1545+
):
1546+
"""Test that merge_prerelease works correctly when there are no prereleases.
1547+
1548+
When changelog_merge_prerelease is enabled but there are no prereleases to merge,
1549+
the normal incremental changelog behavior should apply and the existing changelog
1550+
content should be preserved.
1551+
"""
1552+
with config_path.open("a") as f:
1553+
f.write("changelog_merge_prerelease = true\n")
1554+
f.write("update_changelog_on_bump = true\n")
1555+
f.write("annotated_tag = true\n")
1556+
1557+
# Create initial version with changelog that has a header
1558+
util.create_file_and_commit("feat: initial feature")
1559+
mocker.patch("commitizen.git.GitTag.date", "1970-01-01")
1560+
git.tag("0.1.0")
1561+
1562+
# Create a changelog with a header manually
1563+
changelog_path.write_text(
1564+
"# Changelog\n\nAll notable changes.\n\n## 0.1.0 (1970-01-01)\n\n### Feat\n\n- initial feature\n"
1565+
)
1566+
1567+
# Add new commits and do a regular bump (no prerelease)
1568+
util.create_file_and_commit("feat: add new output")
1569+
util.create_file_and_commit("fix: output glitch")
1570+
util.run_cli("bump", "--changelog")
1571+
1572+
with changelog_path.open() as f:
1573+
out = f.read()
1574+
1575+
# The header and existing content should be preserved
1576+
assert out.startswith("# Changelog\n")
1577+
assert "All notable changes." in out
1578+
assert "## 0.1.0 (1970-01-01)" in out
1579+
file_regression.check(out, extension=".md")
1580+
1581+
15371582
@pytest.mark.usefixtures("tmp_commitizen_project")
15381583
def test_bump_deprecate_files_only(util: UtilFixture):
15391584
util.create_file_and_commit("feat: new file")
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Changelog
2+
3+
All notable changes.
4+
5+
## 0.2.0 (2025-01-01)
6+
7+
### Feat
8+
9+
- add new output
10+
11+
### Fix
12+
13+
- output glitch
14+
15+
## 0.1.0 (1970-01-01)
16+
17+
### Feat
18+
19+
- initial feature

0 commit comments

Comments
 (0)