diff --git a/src/semantic_release/data/templates/conventional/md/.components/changes.md.j2 b/src/semantic_release/data/templates/conventional/md/.components/changes.md.j2 index c81b0faa1..7cb60890b 100644 --- a/src/semantic_release/data/templates/conventional/md/.components/changes.md.j2 +++ b/src/semantic_release/data/templates/conventional/md/.components/changes.md.j2 @@ -67,7 +67,7 @@ EXAMPLE: # 1. Re-map the list to only the list of commits under the breaking category from the list of tuples # 2. Peel off the outer list to get a list of ParsedCommit objects # 3. Filter the list of ParsedCommits to only those with a breaking description -#}{% set breaking_commits = commit_objects | map(attribute="1.0") +#}{% set breaking_commits = commit_objects | map(attribute="1") | sum(start=[]) %}{% set breaking_commits = breaking_commits | rejectattr("error", "defined") | selectattr("breaking_descriptions.0") | list %}{# #}{% if breaking_commits | length > 0 @@ -100,7 +100,7 @@ EXAMPLE: # 1. Re-map the list to only the list of commits from the list of tuples # 2. Peel off the outer list to get a list of ParsedCommit objects # 3. Filter the list of ParsedCommits to only those with a release notice -#}{% set notice_commits = commit_objects | map(attribute="1.0") +#}{% set notice_commits = commit_objects | map(attribute="1") | sum(start=[]) %}{% set notice_commits = notice_commits | rejectattr("error", "defined") | selectattr("release_notices.0") | list %}{# #}{% if notice_commits | length > 0 diff --git a/src/semantic_release/data/templates/conventional/rst/.components/changes.rst.j2 b/src/semantic_release/data/templates/conventional/rst/.components/changes.rst.j2 index 7498aa787..c9fec7ee8 100644 --- a/src/semantic_release/data/templates/conventional/rst/.components/changes.rst.j2 +++ b/src/semantic_release/data/templates/conventional/rst/.components/changes.rst.j2 @@ -95,7 +95,7 @@ Additional Release Information # 1. Re-map the list to only the list of commits under the breaking category from the list of tuples # 2. Peel off the outer list to get a list of ParsedCommit objects # 3. Filter the list of ParsedCommits to only those with a breaking description -#}{% set breaking_commits = commit_objects | map(attribute="1.0") +#}{% set breaking_commits = commit_objects | map(attribute="1") | sum(start=[]) %}{% set breaking_commits = breaking_commits | rejectattr("error", "defined") | selectattr("breaking_descriptions.0") | list %}{# #}{% if breaking_commits | length > 0 @@ -129,7 +129,7 @@ Additional Release Information # 1. Re-map the list to only the list of commits from the list of tuples # 2. Peel off the outer list to get a list of ParsedCommit objects # 3. Filter the list of ParsedCommits to only those with a release notice -#}{% set notice_commits = commit_objects | map(attribute="1.0") +#}{% set notice_commits = commit_objects | map(attribute="1") | sum(start=[]) %}{% set notice_commits = notice_commits | rejectattr("error", "defined") | selectattr("release_notices.0") | list %}{# #}{% if notice_commits | length > 0 diff --git a/tests/unit/semantic_release/changelog/conftest.py b/tests/unit/semantic_release/changelog/conftest.py index a5e09813e..adc7688f9 100644 --- a/tests/unit/semantic_release/changelog/conftest.py +++ b/tests/unit/semantic_release/changelog/conftest.py @@ -365,6 +365,68 @@ def release_history_w_notice_n_brk_change( ) +@pytest.fixture +def release_history_w_nonleading_brk_n_notice( + release_history_w_notice_n_brk_change: ReleaseHistory, +) -> ReleaseHistory: + """Create a release where breaking changes and notices are not first in a category.""" + latest_version = next(iter(release_history_w_notice_n_brk_change.released.keys())) + latest_release = release_history_w_notice_n_brk_change.released[latest_version] + + normal_fix = ParsedCommit( + bump=LevelBump.PATCH, + type="fix", + scope="", + descriptions=["a newer non-breaking fix"], + breaking_descriptions=[], + commit=Commit( + Repo("."), + Object.NULL_BIN_SHA, + message="fix: a newer non-breaking fix", + ), + ) + normal_refactor = ParsedCommit( + bump=LevelBump.NO_RELEASE, + type="refactor", + scope="", + descriptions=["a newer refactor without a notice"], + breaking_descriptions=[], + commit=Commit( + Repo("."), + Object.NULL_BIN_SHA, + message="refactor: a newer refactor without a notice", + ), + ) + + return ReleaseHistory( + unreleased={}, + released={ + latest_version: Release( + tagger=latest_release["tagger"], + committer=latest_release["committer"], + tagged_date=latest_release["tagged_date"], + elements={ + **latest_release["elements"], + "Bug Fixes": [ + normal_fix, + *latest_release["elements"]["Bug Fixes"], + ], + "Refactoring": [ + normal_refactor, + *latest_release["elements"]["Refactoring"], + ], + }, + version=latest_version, + ), + **{ + version: release + for version, release in release_history_w_notice_n_brk_change.released.items() + if version != latest_version + }, + }, + ) + + @pytest.fixture def release_history_w_multiple_notices( release_history_w_a_notice: ReleaseHistory, diff --git a/tests/unit/semantic_release/changelog/test_default_changelog.py b/tests/unit/semantic_release/changelog/test_default_changelog.py index 1eefe69db..20ad9b5a8 100644 --- a/tests/unit/semantic_release/changelog/test_default_changelog.py +++ b/tests/unit/semantic_release/changelog/test_default_changelog.py @@ -121,6 +121,48 @@ def test_default_changelog_template( assert expected_changelog == actual_changelog +@pytest.mark.parametrize( + "output_format, breaking_header, notice_header", + [ + ( + ChangelogOutputFormat.MARKDOWN, + "### Breaking Changes", + "### Additional Release Information", + ), + ( + ChangelogOutputFormat.RESTRUCTURED_TEXT, + "Breaking Changes\n----------------", + "Additional Release Information\n------------------------------", + ), + ], +) +def test_default_changelog_includes_nonleading_breaking_changes_and_notices( + output_format: ChangelogOutputFormat, + breaking_header: str, + notice_header: str, + example_git_https_url: str, + release_history_w_nonleading_brk_n_notice: ReleaseHistory, + changelog_md_file: Path, +): + changelog = render_default_changelog_file( + output_format=output_format, + changelog_context=make_changelog_context( + hvcs_client=Github(example_git_https_url), + release_history=release_history_w_nonleading_brk_n_notice, + mode=ChangelogMode.INIT, + prev_changelog_file=changelog_md_file, + insertion_flag="", + mask_initial_release=True, + ), + changelog_style="conventional", + ) + + assert breaking_header in changelog + assert "This is a breaking change" in changelog + assert notice_header in changelog + assert "This is a multline release notice" in changelog + + @pytest.mark.parametrize("hvcs_client", [Github, Gitlab, Gitea, Bitbucket]) def test_default_changelog_template_w_a_brk_change( hvcs_client: type[Bitbucket | Gitea | Github | Gitlab],