Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add template for GitHub Releases #67

Merged
merged 4 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .github/workflows/package-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,12 @@ jobs:
with:
python-version: x
check-latest: true
- name: Check for unreleased entries in the Changelog
run: python scripts/check_unreleased_changelog_items.py
- name: Copy Changelog to template directory
- name: Check for unreleased entries in the Changelog and copy files to templates
run: |
cp CHANGELOG.md python_semantic_release_templates/.previous_changelog_for_template.md
git add python_semantic_release_templates/.previous_changelog_for_template.md
python scripts/check_unreleased_changelog_items.py
git add python_semantic_release_templates
- name: Python Semantic Release
uses: python-semantic-release/python-semantic-release@v8.1.2
uses: python-semantic-release/python-semantic-release@v8.3.0
id: release
with:
force: ${{ inputs.release_level }}
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ ______________________________________________________________________

Things to be included in the next release go here.

### Added

- Added a template for rendering custom Release Notes for GitHub Releases

______________________________________________________________________

## v0.1.19 (2023-10-24)
Expand Down
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"sphinx.ext.todo",
"sphinx.ext.inheritance_diagram",
"sphinx.ext.graphviz",
"sphinx.ext.githubpages",
"sphinxcontrib.jquery",
"sphinxcontrib.mermaid",
"sphinx_togglebutton",
Expand Down
26 changes: 26 additions & 0 deletions python_semantic_release_templates/.macros.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{%- macro populate_variables() %}
{%- set latest_release_dict_entry = (context.history.released.items()|list)[0] %}
{%- set latest_version_number = latest_release_dict_entry[0].as_tag() %}
{%- set latest_version_date = latest_release_dict_entry[1].tagged_date.strftime("%Y-%m-%d") %}
{%- set recently_merged_prs = {} %}
{%- for type_, commits in latest_release_dict_entry[1]["elements"] | dictsort %}
{%- for commit in commits %}
{%- set pr_num = commit.commit.message.rstrip().rsplit("(#", 1)[-1].rsplit(")", 1)[0]|int %}
{%- if pr_num %}
{%- do recently_merged_prs.update({commit.commit.message.split("\n")[0].rsplit("(#", 1)[0]|safe: pr_num}) %}
{%- endif %}
{%- endfor %}
{%- endfor %}

{%- if recently_merged_prs %}
{%- set merged_prs_text_list = ["\n\n### Merged Pull Requests\n\n"] %}
{%- for message, number in recently_merged_prs.items() %}
{%- do merged_prs_text_list.append("- " ~ message ~ "([#" + number|string ~ "](" ~ number|string|pull_request_url ~ "))\n") %}
{%- endfor %}
{%- set merged_prs_text = (merged_prs_text_list|join).rstrip() %}
{%- else %}
{%- set merged_prs_text = "" %}
{%- endif %}
{%- set output = (latest_version_number, latest_version_date, merged_prs_text) %}
{{- caller(output) }}
{%- endmacro %}
7 changes: 7 additions & 0 deletions python_semantic_release_templates/.release_notes.md.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{%- import ".macros.j2" as macros %}

{%- call(output) macros.populate_variables() %}
{%- filter replace("Things to be included in the next release go here.", "# " + output[0] + " (" + output[1] + ")" + output[2])|replace("##", "#") %}
{%- include ".previous_release_notes_for_template.md" %}
{% endfilter %}
{%- endcall %}
32 changes: 6 additions & 26 deletions python_semantic_release_templates/CHANGELOG.md.j2
Original file line number Diff line number Diff line change
@@ -1,27 +1,7 @@
{%- set latest_release_dict_entry = (context.history.released.items()|list)[0] %}
{%- set latest_version_number = latest_release_dict_entry[0].as_tag() %}
{%- set latest_version_date = latest_release_dict_entry[1].tagged_date.strftime("%Y-%m-%d") %}
{%- set recently_merged_prs = {} %}
{%- for type_, commits in latest_release_dict_entry[1]["elements"] | dictsort %}
{%- for commit in commits %}
{%- set pr_num = commit.commit.message.rstrip().rsplit("(#", 1)[-1].rsplit(")", 1)[0]|int %}
{%- if pr_num %}
{%- do recently_merged_prs.update({commit.commit.message.split("\n")[0].rsplit("(#", 1)[0]|safe: pr_num}) %}
{%- endif %}
{%- endfor %}
{%- endfor %}
{%- import ".macros.j2" as macros %}

{%- if recently_merged_prs %}
{%- set merged_prs_text_list = ["\n\n### Merged Pull Requests\n\n"] %}
{%- for message, number in recently_merged_prs.items() %}
{%- do merged_prs_text_list.append("- " ~ message ~ "([#" + number|string ~ "](" ~ number|string|pull_request_url ~ "))\n") %}
{%- endfor %}
{%- set merged_prs_text = (merged_prs_text_list|join).rstrip() %}
{%- else %}
{%- set merged_prs_text = "" %}
{%- endif %}


{%- filter replace("Things to be included in the next release go here.", "Things to be included in the next release go here.\n\n______________________________________________________________________\n\n## " + latest_version_number + " (" + latest_version_date + ")" + merged_prs_text) %}
{%- include ".previous_changelog_for_template.md" %}
{% endfilter %}
{%- call(output) macros.populate_variables() %}
{%- filter replace("Things to be included in the next release go here.", "Things to be included in the next release go here.\n\n______________________________________________________________________\n\n## " + output[0] + " (" + output[1] + ")" + output[2]) %}
{%- include ".previous_changelog_for_template.md" %}
{% endfilter %}
{%- endcall %}
34 changes: 26 additions & 8 deletions scripts/check_unreleased_changelog_items.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
"""This script will check for unreleased entries in the CHANGELOG.md file.

It will exit with a non-zero exit code if there are no unreleased entries.

It will also copy the necessary files into the template directory to properly render the CHANGELOG
and Release Notes.
"""
import pathlib
import re
import shutil

CHANGELOG_FILENAME = "CHANGELOG.md"
CHANGELOG_FILEPATH = pathlib.Path(__file__).parent.parent / "CHANGELOG.md"
TEMPLATE_CHANGELOG_FILEPATH = (
pathlib.Path(__file__).parent.parent
/ "python_semantic_release_templates"
/ ".previous_changelog_for_template.md"
)
TEMPLATE_RELEASE_NOTES_FILEPATH = (
pathlib.Path(__file__).parent.parent
/ "python_semantic_release_templates"
/ ".previous_release_notes_for_template.md"
)


def main() -> None:
Expand All @@ -14,16 +28,17 @@ def main() -> None:
Raises:
SystemExit: Indicates no new entries were found.
"""
release_notes_content = ""
found_entries = False
with open(
pathlib.Path(__file__).parent.parent / CHANGELOG_FILENAME, encoding="utf-8"
) as changelog_file:
with CHANGELOG_FILEPATH.open(mode="r", encoding="utf-8") as changelog_file:
tracking_unreleased = False
tracking_entries = False
for line in changelog_file:
if line.startswith("___"):
tracking_unreleased = False
tracking_entries = False
if tracking_unreleased:
release_notes_content += line
if line.startswith("## Unreleased"):
tracking_unreleased = True
if tracking_unreleased and line.startswith(
Expand All @@ -37,15 +52,18 @@ def main() -> None:
)
):
tracking_entries = True
if tracking_entries:
if tracking_entries and not found_entries:
found_entries = bool(re.match(r"^- \w+", line))
if found_entries:
break

if not found_entries:
msg = f"No unreleased entries were found in {CHANGELOG_FILENAME}."
msg = f"No unreleased entries were found in {CHANGELOG_FILEPATH}."
raise SystemExit(msg)

# Copy the files to the correct location
shutil.copy(CHANGELOG_FILEPATH, TEMPLATE_CHANGELOG_FILEPATH)
with TEMPLATE_RELEASE_NOTES_FILEPATH.open("w", encoding="utf-8") as template_release_notes:
template_release_notes.write(release_notes_content.strip() + "\n")


if __name__ == "__main__":
main()