Enhance release notes generation with commit range comparison
This commit is contained in:
@@ -301,10 +301,12 @@ jobs:
|
|||||||
id: release_notes
|
id: release_notes
|
||||||
run: |
|
run: |
|
||||||
chmod +x ./bin/generate_release_notes.py
|
chmod +x ./bin/generate_release_notes.py
|
||||||
NOTES=$(./bin/generate_release_notes.py ${{ needs.version.outputs.long }})
|
NOTES=$(./bin/generate_release_notes.py ${{ needs.version.outputs.long }} --compare-ref HEAD 2>release_notes.log)
|
||||||
echo "notes<<EOF" >> $GITHUB_OUTPUT
|
echo "notes<<EOF" >> $GITHUB_OUTPUT
|
||||||
echo "$NOTES" >> $GITHUB_OUTPUT
|
echo "$NOTES" >> $GITHUB_OUTPUT
|
||||||
echo "EOF" >> $GITHUB_OUTPUT
|
echo "EOF" >> $GITHUB_OUTPUT
|
||||||
|
echo "### Release note range" >> $GITHUB_STEP_SUMMARY
|
||||||
|
cat release_notes.log >> $GITHUB_STEP_SUMMARY
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
@@ -466,7 +468,7 @@ jobs:
|
|||||||
- name: Generate release notes
|
- name: Generate release notes
|
||||||
run: |
|
run: |
|
||||||
chmod +x ./bin/generate_release_notes.py
|
chmod +x ./bin/generate_release_notes.py
|
||||||
./bin/generate_release_notes.py ${{ needs.version.outputs.long }} > ./publish/release_notes.md
|
./bin/generate_release_notes.py ${{ needs.version.outputs.long }} --compare-ref HEAD > ./publish/release_notes.md
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,31 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""Generate release notes from the actual release commit range."""
|
||||||
Generate release notes from merged PRs on develop and master branches.
|
|
||||||
Categorizes PRs into Enhancements and Bug Fixes/Maintenance sections.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import subprocess
|
import argparse
|
||||||
import re
|
|
||||||
import json
|
import json
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
|
|
||||||
def get_last_release_tag():
|
def get_last_release_tag(compare_ref, exclude_tag=None):
|
||||||
"""Get the most recent release tag."""
|
"""Get the most recent version tag merged into compare_ref."""
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["git", "describe", "--tags", "--abbrev=0"],
|
["git", "tag", "--merged", compare_ref, "--sort=-version:refname", "v*"],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
check=True,
|
check=True,
|
||||||
)
|
)
|
||||||
return result.stdout.strip()
|
|
||||||
|
for line in result.stdout.splitlines():
|
||||||
|
candidate = line.strip()
|
||||||
|
if not candidate:
|
||||||
|
continue
|
||||||
|
if exclude_tag and candidate == exclude_tag:
|
||||||
|
continue
|
||||||
|
return candidate
|
||||||
|
|
||||||
|
raise subprocess.CalledProcessError(result.returncode, result.args, output=result.stdout, stderr=result.stderr)
|
||||||
|
|
||||||
|
|
||||||
def get_tag_date(tag):
|
def get_tag_date(tag):
|
||||||
@@ -33,18 +39,18 @@ def get_tag_date(tag):
|
|||||||
return result.stdout.strip()
|
return result.stdout.strip()
|
||||||
|
|
||||||
|
|
||||||
def get_merged_prs_since_tag(tag, branch):
|
def get_merged_prs_in_range(tag, compare_ref):
|
||||||
"""Get all merged PRs since the given tag on the specified branch."""
|
"""Get all merged PRs in the git range between tag and compare_ref."""
|
||||||
# Get commits since tag on the branch - look for PR numbers in parentheses
|
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
[
|
[
|
||||||
"git",
|
"git",
|
||||||
"log",
|
"log",
|
||||||
f"{tag}..origin/{branch}",
|
f"{tag}..{compare_ref}",
|
||||||
"--oneline",
|
"--oneline",
|
||||||
],
|
],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
|
check=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
prs = []
|
prs = []
|
||||||
@@ -65,6 +71,25 @@ def get_merged_prs_since_tag(tag, branch):
|
|||||||
return prs
|
return prs
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
"""Parse CLI arguments."""
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Generate release notes from the actual release commit range."
|
||||||
|
)
|
||||||
|
parser.add_argument("new_version", help="Version that will be tagged for this release")
|
||||||
|
parser.add_argument(
|
||||||
|
"--base-tag",
|
||||||
|
dest="base_tag",
|
||||||
|
help="Existing version tag to diff from. Defaults to the latest version tag merged into the compare ref.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--compare-ref",
|
||||||
|
default="HEAD",
|
||||||
|
help="Git ref to diff to. Defaults to HEAD.",
|
||||||
|
)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
def get_pr_details(pr_number):
|
def get_pr_details(pr_number):
|
||||||
"""Get PR details from GitHub API via gh CLI."""
|
"""Get PR details from GitHub API via gh CLI."""
|
||||||
try:
|
try:
|
||||||
@@ -268,28 +293,28 @@ def get_new_contributors(pr_details_list, tag, repo="meshtastic/firmware"):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) < 2:
|
args = parse_args()
|
||||||
print("Usage: generate_release_notes.py <new_version>", file=sys.stderr)
|
new_version = args.new_version
|
||||||
sys.exit(1)
|
compare_ref = args.compare_ref
|
||||||
|
current_tag = f"v{new_version}"
|
||||||
new_version = sys.argv[1]
|
|
||||||
|
|
||||||
# Get last release tag
|
# Get last release tag
|
||||||
try:
|
try:
|
||||||
last_tag = get_last_release_tag()
|
last_tag = args.base_tag or get_last_release_tag(compare_ref, exclude_tag=current_tag)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
print("Error: Could not find last release tag", file=sys.stderr)
|
print("Error: Could not find last release tag", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Collect PRs from both branches
|
print(
|
||||||
all_pr_numbers = set()
|
f"Resolved release note range: {last_tag}..{compare_ref}",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
|
||||||
for branch in ["develop", "master"]:
|
try:
|
||||||
try:
|
all_pr_numbers = set(get_merged_prs_in_range(last_tag, compare_ref))
|
||||||
prs = get_merged_prs_since_tag(last_tag, branch)
|
except subprocess.CalledProcessError as e:
|
||||||
all_pr_numbers.update(prs)
|
print(f"Error: Could not get PRs for range {last_tag}..{compare_ref}: {e}", file=sys.stderr)
|
||||||
except Exception as e:
|
sys.exit(1)
|
||||||
print(f"Warning: Could not get PRs from {branch}: {e}", file=sys.stderr)
|
|
||||||
|
|
||||||
# Get details for all PRs
|
# Get details for all PRs
|
||||||
enhancements = []
|
enhancements = []
|
||||||
|
|||||||
Reference in New Issue
Block a user