From 36b2a70edc660f7c06e6db275e1e59d8543cd299 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Tue, 5 Dec 2023 20:10:34 -0500 Subject: [PATCH 1/4] feat(changelog): new angular changelog templates --- semantic_release/commit_parser/angular.py | 8 +- .../data/templates/CHANGELOG.angular.md.j2 | 91 +++++++++++++++++++ .../templates/release_notes.angular.md.j2 | 52 +++++++++++ 3 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 semantic_release/data/templates/CHANGELOG.angular.md.j2 create mode 100644 semantic_release/data/templates/release_notes.angular.md.j2 diff --git a/semantic_release/commit_parser/angular.py b/semantic_release/commit_parser/angular.py index 8436d11e3..b943ff960 100644 --- a/semantic_release/commit_parser/angular.py +++ b/semantic_release/commit_parser/angular.py @@ -29,9 +29,11 @@ def _logged_parse_error(commit: Commit, error: str) -> ParseError: # types with long names in changelog LONG_TYPE_NAMES = { - "feat": "feature", + "build": "build system", "docs": "documentation", - "perf": "performance", + "feat": "features", + "fix": "fixes", + "perf": "performance improvements", } @@ -82,7 +84,7 @@ def __init__(self, options: AngularParserOptions | None = None) -> None: def get_default_options() -> AngularParserOptions: return AngularParserOptions() - # Maybe this can be cached as an optimisation, similar to how + # Maybe this can be cached as an optimization, similar to how # mypy/pytest use their own caching directories, for very large commit # histories? # The problem is the cache likely won't be present in CI environments diff --git a/semantic_release/data/templates/CHANGELOG.angular.md.j2 b/semantic_release/data/templates/CHANGELOG.angular.md.j2 new file mode 100644 index 000000000..6942d9377 --- /dev/null +++ b/semantic_release/data/templates/CHANGELOG.angular.md.j2 @@ -0,0 +1,91 @@ +# CHANGELOG + +{% if context.history.unreleased | length > 0 %} +{# UNRELEASED #} +## Unreleased + {% for type_, commits in context.history.unreleased | dictsort if type_ != "unknown" %} +{##} +### {{ type_ | capitalize }} + + {% for commit in commits if type_ != "unknown" %} +{##} + {% if commit.scope %} +{{ "- **%s**: %s ([`%s`](%s))\n" | format( + commit.scope, + commit.descriptions[0], + commit.short_hash, + commit.hexsha | commit_hash_url + ) +}} + {% else %} +{{ "- %s ([`%s`](%s))\n" | format( + commit.descriptions[0] | capitalize, + commit.short_hash, + commit.hexsha | commit_hash_url + ) +}} + {% endif %} + {% endfor %} + {% endfor %} +{% endif %} +{# +RELEASED +#} +{% for version, release in context.history.released.items() %} +{##} +{{ "## %s (%s)\n" | format( + version.as_semver_tag(), + release.tagged_date.strftime("%Y-%m-%d") + ) +}} + {% for type_, commits in release["elements"] | dictsort if type_ != "unknown" %} +{##} +{{ "### %s\n" | format(type_ | capitalize) }} +{##} + {% for commit in commits if type_ != "unknown" %} +{##} + {% if commit.scope %} +{{ "- **%s**: %s ([`%s`](%s))\n" | format( + commit.scope, + commit.descriptions[0], + commit.short_hash, + commit.hexsha | commit_hash_url + ) +}} + {% else %} +{{ "- %s ([`%s`](%s))\n" | format( + commit.descriptions[0] | capitalize, + commit.short_hash, + commit.hexsha | commit_hash_url + ) +}} + {% endif %} + {% endfor %} + {% endfor %} +{##} + {% if "breaking" in release["elements"] %} +{##} +### BREAKING CHANGES + + {% for type_, commits in release["elements"] | dictsort if type_ != "unknown" %} +{##} + {% for commit in commits if type_ == "breaking" %} +{##} + {% if commit.breaking_descriptions | length > 0 %} + {% if commit.scope %} +{{ "- **%s**: %s\n" | format( + commit.scope, + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) +}} + {% else %} +{{ "- %s\n" | format( + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) +}} + {% endif %} + {% endif %} + {% endfor %} + {% endfor %} + {% endif %} +{% endfor %} diff --git a/semantic_release/data/templates/release_notes.angular.md.j2 b/semantic_release/data/templates/release_notes.angular.md.j2 new file mode 100644 index 000000000..bd8f89a8a --- /dev/null +++ b/semantic_release/data/templates/release_notes.angular.md.j2 @@ -0,0 +1,52 @@ +{{ "# %s (%s)\n" | format(version.as_semver_tag(), release.tagged_date.strftime("%Y-%m-%d")) }} + +{% for type_, commits in release["elements"] | dictsort if type_ != "unknown" %} +{##} + {{ "## %s\n" | format(type_ | capitalize) }} +{##} + {% for commit in commits if type_ != "unknown" %} +{##} + {% if commit.scope %} +{{ "- **%s**: %s ([`%s`](%s))\n" | format( + commit.scope, + commit.descriptions[0], + commit.short_hash, + commit.hexsha | commit_hash_url + ) +}} + {% else %} +{{ "- %s ([`%s`](%s))\n" | format( + commit.descriptions[0] | capitalize, + commit.short_hash, + commit.hexsha | commit_hash_url + ) +}} + {% endif %} + {% endfor %} +{% endfor %} +{##} +{% if "breaking" in release["elements"] %} +{##} +### BREAKING CHANGES + + {% for type_, commits in release["elements"] | dictsort if type_ != "unknown" %} +{##} + {% for commit in commits if type_ == "breaking" %} +{##} + {% if commit.breaking_descriptions | length > 0 %} + {% if commit.scope %} +{{ "- **%s**: %s\n" | format( + commit.scope, + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) +}} + {% else %} +{{ "- %s\n" | format( + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) +}} + {% endif %} + {% endif %} + {% endfor %} + {% endfor %} +{% endif %} From f4db03c8e026093fc27fd02598cee84ed11d8df9 Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Mon, 4 Mar 2024 01:08:17 -0500 Subject: [PATCH 2/4] feat(changelog): add emoji & pr/mr url replacement in commit msgs --- .../templates/.macros/commit_msg_links.j2 | 33 ++++ .../templates/.macros/headings.angular.j2 | 17 ++ .../data/templates/CHANGELOG.angular.md.j2 | 152 ++++++++---------- .../templates/release_notes.angular.md.j2 | 102 ++++++------ 4 files changed, 172 insertions(+), 132 deletions(-) create mode 100644 semantic_release/data/templates/.macros/commit_msg_links.j2 create mode 100644 semantic_release/data/templates/.macros/headings.angular.j2 diff --git a/semantic_release/data/templates/.macros/commit_msg_links.j2 b/semantic_release/data/templates/.macros/commit_msg_links.j2 new file mode 100644 index 000000000..a0dabe52e --- /dev/null +++ b/semantic_release/data/templates/.macros/commit_msg_links.j2 @@ -0,0 +1,33 @@ +{# MACRO: commit message links or PR/MR links of commit + @param commit: Commit object + @return: Commit message with PR/MR or commit hash links embedded +#} +{% macro commit_msg_links(commit) +%}{% set description = commit.descriptions[0] | capitalize +%}{# + # Replace PR references in the form of (!123) with a link to the PR +#}{% if description.split("(!") | length > 1 +%}{% set pr_num = description.split("(!")[1].split(")")[0] +%}{% set replacement = "([!%s](%s))" | format(pr_num, pr_num | pull_request_url) +%}{% set description = description | replace("(!" ~ pr_num ~ ")", replacement) +%}{# + # Replace PR references in the form of (#123) with a link to the PR +#}{% elif description.split("(#") | length > 1 +%}{% set pr_num = description.split("(#")[1].split(")")[0] +%}{% set replacement = "([#%s](%s))" | format(pr_num, pr_num | pull_request_url) +%}{% set description = description | replace("(#" ~ pr_num ~ ")", replacement) +%}{# + # DEFAULT: Append commit hash as url to the commit description +#}{% else +%}{% set description = "%s ([`%s`](%s))" | format( + description, + commit.short_hash, + commit.hexsha | commit_hash_url + ) +%}{% endif +%}{# + # Return the modified description +#}{{ description + +}}{% endmacro +%} diff --git a/semantic_release/data/templates/.macros/headings.angular.j2 b/semantic_release/data/templates/.macros/headings.angular.j2 new file mode 100644 index 000000000..651370641 --- /dev/null +++ b/semantic_release/data/templates/.macros/headings.angular.j2 @@ -0,0 +1,17 @@ +{% set heading_to_emoji_map = { + 'breaking': '💥', + 'feature': '✨', + 'fix': '🪲', + 'performance': '⚡', + 'refactor': '♻️', + 'chore': '🧹', + 'documentation': '📖', + 'test': '✅', + 'ci': '🤖', + 'style': '🎨', + 'build system': '⚙️', + 'unknown': '❗', +} %} + +{# The ordered list of which headings to display in order #} +{% set section_headings = heading_to_emoji_map.keys() %} diff --git a/semantic_release/data/templates/CHANGELOG.angular.md.j2 b/semantic_release/data/templates/CHANGELOG.angular.md.j2 index 6942d9377..8c589447d 100644 --- a/semantic_release/data/templates/CHANGELOG.angular.md.j2 +++ b/semantic_release/data/templates/CHANGELOG.angular.md.j2 @@ -1,91 +1,77 @@ # CHANGELOG +{# +#}{% from '.macros/commit_msg_links.j2' import commit_msg_links +%}{% from '.macros/headings.angular.j2' import section_headings -{% if context.history.unreleased | length > 0 %} -{# UNRELEASED #} -## Unreleased - {% for type_, commits in context.history.unreleased | dictsort if type_ != "unknown" %} -{##} -### {{ type_ | capitalize }} +%}{% if context.history.unreleased | length > 0 +%}{{ + "\n## Unreleased\n" + +}}{% for type_ in section_headings if type_ in context.history.unreleased +%}{{ + "\n### %s\n" | format(type_ | capitalize) + +}}{% for commit in context.history.unreleased[type_] | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format(commit.scope, commit_msg_links(commit) ) + +}}{% endfor +%}{% for commit in context.history.unreleased[type_] | rejectattr("scope") | sort(attribute='descriptions.0') +%}{{ + "\n- %s\n" | format(commit_msg_links(commit)) + +}}{% endfor +%}{% endfor +%}{{ "\n" +}}{% endif +%}{# - {% for commit in commits if type_ != "unknown" %} -{##} - {% if commit.scope %} -{{ "- **%s**: %s ([`%s`](%s))\n" | format( - commit.scope, - commit.descriptions[0], - commit.short_hash, - commit.hexsha | commit_hash_url - ) -}} - {% else %} -{{ "- %s ([`%s`](%s))\n" | format( - commit.descriptions[0] | capitalize, - commit.short_hash, - commit.hexsha | commit_hash_url - ) -}} - {% endif %} - {% endfor %} - {% endfor %} -{% endif %} -{# RELEASED -#} -{% for version, release in context.history.released.items() %} -{##} -{{ "## %s (%s)\n" | format( - version.as_semver_tag(), - release.tagged_date.strftime("%Y-%m-%d") - ) -}} - {% for type_, commits in release["elements"] | dictsort if type_ != "unknown" %} -{##} -{{ "### %s\n" | format(type_ | capitalize) }} -{##} - {% for commit in commits if type_ != "unknown" %} -{##} - {% if commit.scope %} -{{ "- **%s**: %s ([`%s`](%s))\n" | format( + +#}{% for version, release in context.history.released.items() +%}{{ + "\n## %s (%s)\n" | format( + version.as_semver_tag(), + release.tagged_date.strftime("%Y-%m-%d") + ) + +}}{% for type_ in section_headings if type_ in release["elements"] +%}{{ + "\n### %s\n" | format(type_ | capitalize) + +}}{% for commit in release["elements"][type_] | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format(commit.scope, commit_msg_links(commit) ) + +}}{% endfor +%}{% for commit in release["elements"][type_] | rejectattr("scope") | sort(attribute='descriptions.0') +%}{{ + "\n- %s\n" | format(commit_msg_links(commit)) + +}}{% endfor +%}{% endfor +%}{# + +#}{% if "breaking" in release["elements"] +%}{{ + "\n### BREAKING CHANGES\n" +}}{# +#}{% set breaking_commits = release["elements"]["breaking"] | selectattr("breaking_descriptions") +%}{% for commit in breaking_commits | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format( commit.scope, - commit.descriptions[0], - commit.short_hash, - commit.hexsha | commit_hash_url + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize ) -}} - {% else %} -{{ "- %s ([`%s`](%s))\n" | format( - commit.descriptions[0] | capitalize, - commit.short_hash, - commit.hexsha | commit_hash_url + +}}{% endfor +%}{% for commit in breaking_commits | rejectattr("scope") | sort(attribute='breaking_descriptions.0') +%}{{ + "\n- %s\n" | format( + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize ) -}} - {% endif %} - {% endfor %} - {% endfor %} -{##} - {% if "breaking" in release["elements"] %} -{##} -### BREAKING CHANGES - {% for type_, commits in release["elements"] | dictsort if type_ != "unknown" %} -{##} - {% for commit in commits if type_ == "breaking" %} -{##} - {% if commit.breaking_descriptions | length > 0 %} - {% if commit.scope %} -{{ "- **%s**: %s\n" | format( - commit.scope, - commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize - ) -}} - {% else %} -{{ "- %s\n" | format( - commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize - ) -}} - {% endif %} - {% endif %} - {% endfor %} - {% endfor %} - {% endif %} -{% endfor %} +}}{% endfor +%}{% endif +%}{% endfor +%} diff --git a/semantic_release/data/templates/release_notes.angular.md.j2 b/semantic_release/data/templates/release_notes.angular.md.j2 index bd8f89a8a..f9896c3dc 100644 --- a/semantic_release/data/templates/release_notes.angular.md.j2 +++ b/semantic_release/data/templates/release_notes.angular.md.j2 @@ -1,52 +1,56 @@ -{{ "# %s (%s)\n" | format(version.as_semver_tag(), release.tagged_date.strftime("%Y-%m-%d")) }} - -{% for type_, commits in release["elements"] | dictsort if type_ != "unknown" %} -{##} - {{ "## %s\n" | format(type_ | capitalize) }} -{##} - {% for commit in commits if type_ != "unknown" %} -{##} - {% if commit.scope %} -{{ "- **%s**: %s ([`%s`](%s))\n" | format( +{# RELEASE NOTES TEMPLATE +## This template is used to generate the release notes for a project that uses +## the conventional commits (ie angular) commit message standard. +#}{% from '.macros/commit_msg_links.j2' import commit_msg_links +%}{% from '.macros/headings.angular.j2' import section_headings, heading_to_emoji_map +%}{# + +vX.X.X.X (YYYY-MMM-DD) + +#}{{ + + "# %s (%s)\n" | format( + version.as_semver_tag(), + release.tagged_date.strftime("%Y-%m-%d") + ) + +}}{% for type_ in section_headings if type_ in release["elements"] + +%}{{ + "\n## %s %s\n" | format(emoji_map[type_], type_ | capitalize) + +}}{% for commit in release["elements"][type_] | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format(commit.scope, commit_msg_links(commit) ) + +}}{% endfor +%}{% for commit in release["elements"][type_] | rejectattr("scope") | sort(attribute='descriptions.0') +%}{{ + "\n- %s\n" | format(commit_msg_links(commit)) + +}}{% endfor +%}{% endfor +%}{# + +#}{% if "breaking" in release["elements"] +%}{{ + "\n### BREAKING CHANGES\n" +}}{# +#}{% set breaking_commits = release["elements"]["breaking"] | selectattr("breaking_descriptions") +%}{% for commit in breaking_commits | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format( commit.scope, - commit.descriptions[0], - commit.short_hash, - commit.hexsha | commit_hash_url + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize ) -}} - {% else %} -{{ "- %s ([`%s`](%s))\n" | format( - commit.descriptions[0] | capitalize, - commit.short_hash, - commit.hexsha | commit_hash_url + +}}{% endfor +%}{% for commit in breaking_commits | rejectattr("scope") | sort(attribute='breaking_descriptions.0') +%}{{ + "\n- %s\n" | format( + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize ) -}} - {% endif %} - {% endfor %} -{% endfor %} -{##} -{% if "breaking" in release["elements"] %} -{##} -### BREAKING CHANGES - - {% for type_, commits in release["elements"] | dictsort if type_ != "unknown" %} -{##} - {% for commit in commits if type_ == "breaking" %} -{##} - {% if commit.breaking_descriptions | length > 0 %} - {% if commit.scope %} -{{ "- **%s**: %s\n" | format( - commit.scope, - commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize - ) -}} - {% else %} -{{ "- %s\n" | format( - commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize - ) -}} - {% endif %} - {% endif %} - {% endfor %} - {% endfor %} -{% endif %} + +}}{% endfor +%}{% endif +%} From e9cf3605f7ad284ae2cdd6c35d0366a270f5493b Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Mon, 4 Mar 2024 01:09:03 -0500 Subject: [PATCH 3/4] feat(changelog): temporary emoji, scipy, tag templates --- .../data/templates/.macros/headings.emoji.j2 | 24 ++++++ .../data/templates/.macros/headings.scipy.j2 | 17 ++++ .../data/templates/.macros/headings.tag.j2 | 18 +++++ .../data/templates/CHANGELOG.emoji.md.j2 | 77 +++++++++++++++++++ .../data/templates/CHANGELOG.scipy.md.j2 | 77 +++++++++++++++++++ .../data/templates/CHANGELOG.tag.md.j2 | 77 +++++++++++++++++++ .../data/templates/release_notes.emoji.md.j2 | 56 ++++++++++++++ .../data/templates/release_notes.scipy.md.j2 | 56 ++++++++++++++ .../data/templates/release_notes.tag.md.j2 | 56 ++++++++++++++ 9 files changed, 458 insertions(+) create mode 100644 semantic_release/data/templates/.macros/headings.emoji.j2 create mode 100644 semantic_release/data/templates/.macros/headings.scipy.j2 create mode 100644 semantic_release/data/templates/.macros/headings.tag.j2 create mode 100644 semantic_release/data/templates/CHANGELOG.emoji.md.j2 create mode 100644 semantic_release/data/templates/CHANGELOG.scipy.md.j2 create mode 100644 semantic_release/data/templates/CHANGELOG.tag.md.j2 create mode 100644 semantic_release/data/templates/release_notes.emoji.md.j2 create mode 100644 semantic_release/data/templates/release_notes.scipy.md.j2 create mode 100644 semantic_release/data/templates/release_notes.tag.md.j2 diff --git a/semantic_release/data/templates/.macros/headings.emoji.j2 b/semantic_release/data/templates/.macros/headings.emoji.j2 new file mode 100644 index 000000000..6cbf7c1af --- /dev/null +++ b/semantic_release/data/templates/.macros/headings.emoji.j2 @@ -0,0 +1,24 @@ +{# The ordered list of which headings to display in order #} +{% set section_headings = [ + ':boom:', + ':sparkles:', + ":children_crossing:", + ":lipstick:", + ":iphone:", + ":egg:", + ":chart_with_upwards_trend:", + ":ambulance:", + ":lock:", + ":bug:", + ":zap:", + ":goal_net:", + ":alien:", + ":wheelchair:", + ":speech_balloon:", + ":mag:", + ":apple:", + ":penguin:", + ":checkered_flag:", + ":robot:", + ":green_apple:", +] %} diff --git a/semantic_release/data/templates/.macros/headings.scipy.j2 b/semantic_release/data/templates/.macros/headings.scipy.j2 new file mode 100644 index 000000000..651370641 --- /dev/null +++ b/semantic_release/data/templates/.macros/headings.scipy.j2 @@ -0,0 +1,17 @@ +{% set heading_to_emoji_map = { + 'breaking': '💥', + 'feature': '✨', + 'fix': '🪲', + 'performance': '⚡', + 'refactor': '♻️', + 'chore': '🧹', + 'documentation': '📖', + 'test': '✅', + 'ci': '🤖', + 'style': '🎨', + 'build system': '⚙️', + 'unknown': '❗', +} %} + +{# The ordered list of which headings to display in order #} +{% set section_headings = heading_to_emoji_map.keys() %} diff --git a/semantic_release/data/templates/.macros/headings.tag.j2 b/semantic_release/data/templates/.macros/headings.tag.j2 new file mode 100644 index 000000000..65128e2b7 --- /dev/null +++ b/semantic_release/data/templates/.macros/headings.tag.j2 @@ -0,0 +1,18 @@ + +{% set heading_to_emoji_map = { + 'breaking': '💥', + 'feature': '✨', + 'fix': '🪲', + 'performance': '⚡', + 'refactor': '♻️', + 'chore': '🧹', + 'documentation': '📖', + 'test': '✅', + 'ci': '🤖', + 'style': '🎨', + 'build system': '⚙️', + 'unknown': '❗', +} %} + +{# The ordered list of which headings to display in order #} +{% set section_headings = heading_to_emoji_map.keys() %} diff --git a/semantic_release/data/templates/CHANGELOG.emoji.md.j2 b/semantic_release/data/templates/CHANGELOG.emoji.md.j2 new file mode 100644 index 000000000..397f23c67 --- /dev/null +++ b/semantic_release/data/templates/CHANGELOG.emoji.md.j2 @@ -0,0 +1,77 @@ +# CHANGELOG +{# +#}{% from '.macros/commit_msg_links.j2' import commit_msg_links +%}{% from '.macros/headings.emoji.j2' import section_headings + +%}{% if context.history.unreleased | length > 0 +%}{{ + "\n## Unreleased\n" + +}}{% for type_ in section_headings if type_ in context.history.unreleased +%}{{ + "\n### %s\n" | format(type_ | capitalize) + +}}{% for commit in context.history.unreleased[type_] | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format(commit.scope, commit_msg_links(commit) ) + +}}{% endfor +%}{% for commit in context.history.unreleased[type_] | rejectattr("scope") | sort(attribute='descriptions.0') +%}{{ + "\n- %s\n" | format(commit_msg_links(commit)) + +}}{% endfor +%}{% endfor +%}{{ "\n" +}}{% endif +%}{# + +RELEASED + +#}{% for version, release in context.history.released.items() +%}{{ + "\n## %s (%s)\n" | format( + version.as_semver_tag(), + release.tagged_date.strftime("%Y-%m-%d") + ) + +}}{% for type_ in section_headings if type_ in release["elements"] +%}{{ + "\n### %s\n" | format(type_ | capitalize) + +}}{% for commit in release["elements"][type_] | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format(commit.scope, commit_msg_links(commit) ) + +}}{% endfor +%}{% for commit in release["elements"][type_] | rejectattr("scope") | sort(attribute='descriptions.0') +%}{{ + "\n- %s\n" | format(commit_msg_links(commit)) + +}}{% endfor +%}{% endfor +%}{# + +#}{% if "breaking" in release["elements"] +%}{{ + "\n### BREAKING CHANGES\n" +}}{# +#}{% set breaking_commits = release["elements"]["breaking"] | selectattr("breaking_descriptions") +%}{% for commit in breaking_commits | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format( + commit.scope, + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) + +}}{% endfor +%}{% for commit in breaking_commits | rejectattr("scope") | sort(attribute='breaking_descriptions.0') +%}{{ + "\n- %s\n" | format( + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) + +}}{% endfor +%}{% endif +%}{% endfor +%} diff --git a/semantic_release/data/templates/CHANGELOG.scipy.md.j2 b/semantic_release/data/templates/CHANGELOG.scipy.md.j2 new file mode 100644 index 000000000..ac17f9206 --- /dev/null +++ b/semantic_release/data/templates/CHANGELOG.scipy.md.j2 @@ -0,0 +1,77 @@ +# CHANGELOG +{# +#}{% from '.macros/commit_msg_links.j2' import commit_msg_links +%}{% from '.macros/headings.scipy.j2' import section_headings + +%}{% if context.history.unreleased | length > 0 +%}{{ + "\n## Unreleased\n" + +}}{% for type_ in section_headings if type_ in context.history.unreleased +%}{{ + "\n### %s\n" | format(type_ | capitalize) + +}}{% for commit in context.history.unreleased[type_] | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format(commit.scope, commit_msg_links(commit) ) + +}}{% endfor +%}{% for commit in context.history.unreleased[type_] | rejectattr("scope") | sort(attribute='descriptions.0') +%}{{ + "\n- %s\n" | format(commit_msg_links(commit)) + +}}{% endfor +%}{% endfor +%}{{ "\n" +}}{% endif +%}{# + +RELEASED + +#}{% for version, release in context.history.released.items() +%}{{ + "\n## %s (%s)\n" | format( + version.as_semver_tag(), + release.tagged_date.strftime("%Y-%m-%d") + ) + +}}{% for type_ in section_headings if type_ in release["elements"] +%}{{ + "\n### %s\n" | format(type_ | capitalize) + +}}{% for commit in release["elements"][type_] | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format(commit.scope, commit_msg_links(commit) ) + +}}{% endfor +%}{% for commit in release["elements"][type_] | rejectattr("scope") | sort(attribute='descriptions.0') +%}{{ + "\n- %s\n" | format(commit_msg_links(commit)) + +}}{% endfor +%}{% endfor +%}{# + +#}{% if "breaking" in release["elements"] +%}{{ + "\n### BREAKING CHANGES\n" +}}{# +#}{% set breaking_commits = release["elements"]["breaking"] | selectattr("breaking_descriptions") +%}{% for commit in breaking_commits | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format( + commit.scope, + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) + +}}{% endfor +%}{% for commit in breaking_commits | rejectattr("scope") | sort(attribute='breaking_descriptions.0') +%}{{ + "\n- %s\n" | format( + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) + +}}{% endfor +%}{% endif +%}{% endfor +%} diff --git a/semantic_release/data/templates/CHANGELOG.tag.md.j2 b/semantic_release/data/templates/CHANGELOG.tag.md.j2 new file mode 100644 index 000000000..8aa6f99cd --- /dev/null +++ b/semantic_release/data/templates/CHANGELOG.tag.md.j2 @@ -0,0 +1,77 @@ +# CHANGELOG +{# +#}{% from '.macros/commit_msg_links.j2' import commit_msg_links +%}{% from '.macros/headings.tag.j2' import section_headings + +%}{% if context.history.unreleased | length > 0 +%}{{ + "\n## Unreleased\n" + +}}{% for type_ in section_headings if type_ in context.history.unreleased +%}{{ + "\n### %s\n" | format(type_ | capitalize) + +}}{% for commit in context.history.unreleased[type_] | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format(commit.scope, commit_msg_links(commit) ) + +}}{% endfor +%}{% for commit in context.history.unreleased[type_] | rejectattr("scope") | sort(attribute='descriptions.0') +%}{{ + "\n- %s\n" | format(commit_msg_links(commit)) + +}}{% endfor +%}{% endfor +%}{{ "\n" +}}{% endif +%}{# + +RELEASED + +#}{% for version, release in context.history.released.items() +%}{{ + "\n## %s (%s)\n" | format( + version.as_semver_tag(), + release.tagged_date.strftime("%Y-%m-%d") + ) + +}}{% for type_ in section_headings if type_ in release["elements"] +%}{{ + "\n### %s\n" | format(type_ | capitalize) + +}}{% for commit in release["elements"][type_] | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format(commit.scope, commit_msg_links(commit) ) + +}}{% endfor +%}{% for commit in release["elements"][type_] | rejectattr("scope") | sort(attribute='descriptions.0') +%}{{ + "\n- %s\n" | format(commit_msg_links(commit)) + +}}{% endfor +%}{% endfor +%}{# + +#}{% if "breaking" in release["elements"] +%}{{ + "\n### BREAKING CHANGES\n" +}}{# +#}{% set breaking_commits = release["elements"]["breaking"] | selectattr("breaking_descriptions") +%}{% for commit in breaking_commits | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format( + commit.scope, + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) + +}}{% endfor +%}{% for commit in breaking_commits | rejectattr("scope") | sort(attribute='breaking_descriptions.0') +%}{{ + "\n- %s\n" | format( + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) + +}}{% endfor +%}{% endif +%}{% endfor +%} diff --git a/semantic_release/data/templates/release_notes.emoji.md.j2 b/semantic_release/data/templates/release_notes.emoji.md.j2 new file mode 100644 index 000000000..6efe5ae7e --- /dev/null +++ b/semantic_release/data/templates/release_notes.emoji.md.j2 @@ -0,0 +1,56 @@ +{# RELEASE NOTES TEMPLATE +## This template is used to generate the release notes for a project that uses +## emoji commit message style. +#}{% from '.macros/commit_msg_links.j2' import commit_msg_links +%}{% from '.macros/headings.emoji.j2' import section_headings +%}{# + +vX.X.X.X (YYYY-MMM-DD) + +#}{{ + + "# %s (%s)\n" | format( + version.as_semver_tag(), + release.tagged_date.strftime("%Y-%m-%d") + ) + +}}{% for type_ in section_headings if type_ in release["elements"] + +%}{{ + "\n## %s %s\n" | format(emoji_map[type_], type_ | capitalize) + +}}{% for commit in release["elements"][type_] | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format(commit.scope, commit_msg_links(commit) ) + +}}{% endfor +%}{% for commit in release["elements"][type_] | rejectattr("scope") | sort(attribute='descriptions.0') +%}{{ + "\n- %s\n" | format(commit_msg_links(commit)) + +}}{% endfor +%}{% endfor +%}{# + +#}{% if "breaking" in release["elements"] +%}{{ + "\n### BREAKING CHANGES\n" +}}{# +#}{% set breaking_commits = release["elements"]["breaking"] | selectattr("breaking_descriptions") +%}{% for commit in breaking_commits | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format( + commit.scope, + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) + +}}{% endfor +%}{% for commit in breaking_commits | rejectattr("scope") | sort(attribute='breaking_descriptions.0') +%}{{ + "\n- %s\n" | format( + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) + +}}{% endfor +%}{% endif +%} diff --git a/semantic_release/data/templates/release_notes.scipy.md.j2 b/semantic_release/data/templates/release_notes.scipy.md.j2 new file mode 100644 index 000000000..f61d77f87 --- /dev/null +++ b/semantic_release/data/templates/release_notes.scipy.md.j2 @@ -0,0 +1,56 @@ +{# RELEASE NOTES TEMPLATE +## This template is used to generate the release notes for a project that uses +## the scipy commit message standard. +#}{% from '.macros/commit_msg_links.j2' import commit_msg_links +%}{% from '.macros/headings.scipy.j2' import section_headings, heading_to_emoji_map +%}{# + +vX.X.X.X (YYYY-MMM-DD) + +#}{{ + + "# %s (%s)\n" | format( + version.as_semver_tag(), + release.tagged_date.strftime("%Y-%m-%d") + ) + +}}{% for type_ in section_headings if type_ in release["elements"] + +%}{{ + "\n## %s %s\n" | format(emoji_map[type_], type_ | capitalize) + +}}{% for commit in release["elements"][type_] | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format(commit.scope, commit_msg_links(commit) ) + +}}{% endfor +%}{% for commit in release["elements"][type_] | rejectattr("scope") | sort(attribute='descriptions.0') +%}{{ + "\n- %s\n" | format(commit_msg_links(commit)) + +}}{% endfor +%}{% endfor +%}{# + +#}{% if "breaking" in release["elements"] +%}{{ + "\n### BREAKING CHANGES\n" +}}{# +#}{% set breaking_commits = release["elements"]["breaking"] | selectattr("breaking_descriptions") +%}{% for commit in breaking_commits | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format( + commit.scope, + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) + +}}{% endfor +%}{% for commit in breaking_commits | rejectattr("scope") | sort(attribute='breaking_descriptions.0') +%}{{ + "\n- %s\n" | format( + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) + +}}{% endfor +%}{% endif +%} diff --git a/semantic_release/data/templates/release_notes.tag.md.j2 b/semantic_release/data/templates/release_notes.tag.md.j2 new file mode 100644 index 000000000..3640a6aba --- /dev/null +++ b/semantic_release/data/templates/release_notes.tag.md.j2 @@ -0,0 +1,56 @@ +{# RELEASE NOTES TEMPLATE +## This template is used to generate the release notes for a project that uses +## emoji tag commits convention. +#}{% from '.macros/commit_msg_links.j2' import commit_msg_links +%}{% from '.macros/headings.tag.j2' import section_headings, heading_to_emoji_map +%}{# + +vX.X.X.X (YYYY-MMM-DD) + +#}{{ + + "# %s (%s)\n" | format( + version.as_semver_tag(), + release.tagged_date.strftime("%Y-%m-%d") + ) + +}}{% for type_ in section_headings if type_ in release["elements"] + +%}{{ + "\n## %s %s\n" | format(emoji_map[type_], type_ | capitalize) + +}}{% for commit in release["elements"][type_] | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format(commit.scope, commit_msg_links(commit) ) + +}}{% endfor +%}{% for commit in release["elements"][type_] | rejectattr("scope") | sort(attribute='descriptions.0') +%}{{ + "\n- %s\n" | format(commit_msg_links(commit)) + +}}{% endfor +%}{% endfor +%}{# + +#}{% if "breaking" in release["elements"] +%}{{ + "\n### BREAKING CHANGES\n" +}}{# +#}{% set breaking_commits = release["elements"]["breaking"] | selectattr("breaking_descriptions") +%}{% for commit in breaking_commits | selectattr("scope") | sort(attribute='scope') +%}{{ + "\n- **%s**: %s\n" | format( + commit.scope, + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) + +}}{% endfor +%}{% for commit in breaking_commits | rejectattr("scope") | sort(attribute='breaking_descriptions.0') +%}{{ + "\n- %s\n" | format( + commit.breaking_descriptions | join("\n\n") | indent(4) | capitalize + ) + +}}{% endfor +%}{% endif +%} From c70a67e38c611872d41c98aed464ac57eefe0caf Mon Sep 17 00:00:00 2001 From: codejedi365 Date: Thu, 9 May 2024 22:26:20 -0400 Subject: [PATCH 4/4] fix(parser-angular): adjust long name headings for all commit types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Paduszyński <92403542+paduszyk@users.noreply.github.com> --- semantic_release/commit_parser/angular.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/semantic_release/commit_parser/angular.py b/semantic_release/commit_parser/angular.py index b943ff960..392381550 100644 --- a/semantic_release/commit_parser/angular.py +++ b/semantic_release/commit_parser/angular.py @@ -30,10 +30,15 @@ def _logged_parse_error(commit: Commit, error: str) -> ParseError: # types with long names in changelog LONG_TYPE_NAMES = { "build": "build system", + "ci": "continuous integration", + "chore": "chores", "docs": "documentation", "feat": "features", "fix": "fixes", "perf": "performance improvements", + "refactor": "refactoring", + "style": "code style", + "test": "tests", }