This is an automated email from the ASF dual-hosted git repository.

reiabreu pushed a commit to branch release-notes-upgrade-notes
in repository https://gitbox.apache.org/repos/asf/storm.git

commit d0d61be9d35d5e32cc1d2b867fd7b0871fb02cc8
Author: Rui Abreu <[email protected]>
AuthorDate: Sat Oct 24 01:38:24 2026 +0100

    Print PR upgrade notes in the generated release notes
    
    release_notes.py now adds an "Upgrade notes" section with the text under an
    "Upgrade notes" heading in the description of each PR in the milestone. The 
PR
    template gets that optional heading. Output is unchanged when no PR has one.
    
    Refs #9188
    
    Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
---
 .github/pull_request_template.md |  6 +++++-
 dev-tools/release_notes.py       | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 1caca76e3..e3eaffcfe 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -4,4 +4,8 @@
 
 ## How was the change tested
 
-*(Explain what tests did you do to verify the code change)*
\ No newline at end of file
+*(Explain what tests did you do to verify the code change)*
+
+## Upgrade notes
+
+*(Only for breaking or behaviour changes: what changes for users and what they 
must do. Delete this section otherwise.)*
\ No newline at end of file
diff --git a/dev-tools/release_notes.py b/dev-tools/release_notes.py
index 21fcda027..4d077f672 100755
--- a/dev-tools/release_notes.py
+++ b/dev-tools/release_notes.py
@@ -26,6 +26,8 @@ Generates release notes for a Storm release by generating an 
HTML doc containing
 
 """
 
+import html
+import re
 import requests
 import sys
 import os
@@ -95,6 +97,26 @@ def get_issues(owner, repo, milestone):
 def issue_link(issue):
     return issue["html_url"]
 
+UPGRADE_NOTES_HEADING = re.compile(r"^#{1,6}[ \t]*Upgrade notes[ \t]*$", 
re.IGNORECASE | re.MULTILINE)
+NEXT_HEADING = re.compile(r"^#{1,6}[ \t]", re.MULTILINE)
+TEMPLATE_HINT = re.compile(r"^\*\(.*\)\*$")
+
+def extract_upgrade_notes(issue):
+    """
+    Return the text under the "Upgrade notes" heading of the issue body, or 
None if there is none.
+    The italic hint from the pull request template does not count as a note.
+    """
+    body = (issue.get("body") or "").replace("\r\n", "\n")
+    heading = UPGRADE_NOTES_HEADING.search(body)
+    if not heading:
+        return None
+    section = body[heading.end():]
+    next_heading = NEXT_HEADING.search(section)
+    if next_heading:
+        section = section[:next_heading.start()]
+    lines = [line for line in section.strip().split("\n") if not 
TEMPLATE_HINT.match(line.strip())]
+    return "\n".join(lines).strip() or None
+
 if __name__ == "__main__":
     issues = get_issues(owner, repo, milestone)
 
@@ -160,6 +182,16 @@ if __name__ == "__main__":
         for label, issues in issues_by_label.items()
     ])
 
+    # Pull requests can describe breaking or behaviour changes under an 
"Upgrade notes" heading in their description
+    upgrade_notes = [(issue, extract_upgrade_notes(issue)) for issue in issues]
+    upgrade_notes = [(issue, note) for issue, note in upgrade_notes if note]
+    if upgrade_notes:
+        issues_str = "\n\t<h2>Upgrade notes</h2>\n\t<ul>" + "\n\t\t".join([
+            f'<li>[<a href="{issue_link(issue)}">#{issue["number"]}</a>] - 
{issue["title"]}'
+            f'\n<pre>{html.escape(note)}</pre></li>'
+            for issue, note in upgrade_notes
+        ]) + "\n\t</ul>" + issues_str
+
     version = get_milestone_title(owner, repo, milestone)
 
     print(f"""<!DOCTYPE html>

Reply via email to