Skip to content

Commit a913011

Browse files
migaraclaude
andcommitted
feat(ci): Add enhanced release notes with tag-based ranges and commit links
The release workflow calls generate-release-notes.sh with --since-tag but the script only supported date-based filtering. This adds the full implementation with tag-based log ranges, the shared conventional commits library, PR/commit links, and a New Resources section. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 175dd96 commit a913011

2 files changed

Lines changed: 329 additions & 44 deletions

File tree

scripts/generate-release-notes.sh

Lines changed: 178 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,184 @@
1-
#!/bin/bash
1+
#!/usr/bin/env bash
22
#
33
# Generates markdown release notes from conventional commits in pan-os-codegen.
44
#
55
# Usage:
66
# generate-release-notes.sh <version> [since-date]
7+
# generate-release-notes.sh <version> [--since-tag <tag>] [--since-date <date>] [--repo-url <url>]
78
#
8-
# If since-date is provided, only includes commits after that date.
9-
# Otherwise includes all commits.
9+
# Options:
10+
# --since-tag Use commits after this tag (preferred over date-based filtering)
11+
# --since-date Only include commits after this date (fallback)
12+
# --repo-url GitHub repository URL for links (auto-detected from git remote)
13+
#
14+
# Sections generated:
15+
# - Breaking Changes (feat(MAJOR) or type! commits)
16+
# - New Resources (feat(specs) commits, listed by resource name)
17+
# - Features (feat commits, excluding specs)
18+
# - Bug Fixes (fix commits)
19+
# - Performance (perf commits)
20+
# - Reverts (revert commits)
1021

1122
set -euo pipefail
1223

13-
VERSION="${1:?Usage: generate-release-notes.sh <version> [since-date]}"
14-
SINCE_DATE="${2:-}"
24+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
25+
# shellcheck source=lib/conventional-commits.sh
26+
source "$SCRIPT_DIR/lib/conventional-commits.sh"
27+
28+
# --- Argument parsing ---
29+
30+
VERSION=""
31+
SINCE_TAG=""
32+
SINCE_DATE=""
33+
REPO_URL=""
34+
35+
# Support both old positional interface and new named flags
36+
if [ $# -ge 1 ] && [[ "$1" != --* ]]; then
37+
VERSION="$1"
38+
shift
39+
# Check if second positional arg is a date (old interface) or a flag
40+
if [ $# -ge 1 ] && [[ "$1" != --* ]]; then
41+
SINCE_DATE="$1"
42+
shift
43+
fi
44+
fi
45+
46+
while [ $# -gt 0 ]; do
47+
case "$1" in
48+
--since-tag)
49+
SINCE_TAG="$2"
50+
shift 2
51+
;;
52+
--since-date)
53+
SINCE_DATE="$2"
54+
shift 2
55+
;;
56+
--repo-url)
57+
REPO_URL="$2"
58+
shift 2
59+
;;
60+
*)
61+
if [ -z "$VERSION" ]; then
62+
VERSION="$1"
63+
shift
64+
else
65+
echo "Unknown argument: $1" >&2
66+
exit 1
67+
fi
68+
;;
69+
esac
70+
done
71+
72+
if [ -z "$VERSION" ]; then
73+
echo "Usage: generate-release-notes.sh <version> [--since-tag <tag>] [--since-date <date>] [--repo-url <url>]" >&2
74+
exit 1
75+
fi
76+
77+
if [ -z "$REPO_URL" ]; then
78+
REPO_URL=$(detect_repo_url)
79+
fi
80+
81+
# --- Build git log range ---
1582

16-
LOG_ARGS="--format=%s"
17-
if [ -n "$SINCE_DATE" ]; then
18-
LOG_ARGS="$LOG_ARGS --after=$SINCE_DATE"
83+
LOG_RANGE=""
84+
if [ -n "$SINCE_TAG" ]; then
85+
# Try codegen release tag format first
86+
CODEGEN_TAG="release/${SINCE_TAG}"
87+
if git rev-parse "$CODEGEN_TAG" >/dev/null 2>&1; then
88+
LOG_RANGE="${CODEGEN_TAG}..HEAD"
89+
elif git rev-parse "$SINCE_TAG" >/dev/null 2>&1; then
90+
LOG_RANGE="${SINCE_TAG}..HEAD"
91+
fi
1992
fi
2093

21-
# Collect commits into arrays by type
94+
if [ -z "$LOG_RANGE" ] && [ -n "$SINCE_DATE" ]; then
95+
LOG_RANGE="--after=${SINCE_DATE} HEAD"
96+
elif [ -z "$LOG_RANGE" ]; then
97+
LOG_RANGE="HEAD"
98+
fi
99+
100+
# --- Collect and parse commits ---
101+
102+
# Use simple arrays for each section (bash 3.2 compatible)
103+
BREAKING=()
104+
NEW_RESOURCES=()
22105
FEATS=()
23106
FIXES=()
24-
BREAKING=()
107+
PERFS=()
108+
REVERTS=()
25109

26-
while IFS= read -r subject; do
27-
[ -z "$subject" ] && continue
110+
while IFS= read -r line; do
111+
[ -z "$line" ] && continue
28112

29-
# feat(MAJOR) -> breaking
30-
if echo "$subject" | grep -qiE '^feat\(MAJOR\)'; then
31-
msg=$(echo "$subject" | sed 's/^feat(MAJOR)[!]*: //')
32-
BREAKING+=("- $msg")
33-
continue
34-
fi
113+
# Split on ||| separator
114+
local_hash="${line%%|||*}"
115+
local_subject="${line#*|||}"
35116

36-
# feat -> feature
37-
if echo "$subject" | grep -qE '^feat(\(|:)'; then
38-
scope=$(echo "$subject" | sed -n 's/^feat(\([^)]*\))[!]*:.*/\1/p')
39-
msg=$(echo "$subject" | sed 's/^feat([^)]*)[!]*: //' | sed 's/^feat[!]*: //')
40-
if [ -n "$scope" ]; then
41-
FEATS+=("- **$scope**: $msg")
42-
else
43-
FEATS+=("- $msg")
44-
fi
117+
parse_commit "$local_subject" "$local_hash"
118+
119+
# Skip hidden types
120+
if ! is_visible "$CC_TYPE" && ! $CC_BREAKING; then
45121
continue
46122
fi
47123

48-
# fix -> bug fix
49-
if echo "$subject" | grep -qE '^fix(\(|:)'; then
50-
scope=$(echo "$subject" | sed -n 's/^fix(\([^)]*\))[!]*:.*/\1/p')
51-
msg=$(echo "$subject" | sed 's/^fix([^)]*)[!]*: //' | sed 's/^fix[!]*: //')
52-
if [ -n "$scope" ]; then
53-
FIXES+=("- **$scope**: $msg")
54-
else
55-
FIXES+=("- $msg")
56-
fi
124+
# Format the entry
125+
entry=$(format_entry "$CC_MESSAGE" "$CC_PR" "$CC_HASH_FULL" "$REPO_URL")
126+
127+
# Breaking changes (from feat(MAJOR) or ! suffix)
128+
if $CC_BREAKING; then
129+
BREAKING+=("- $entry")
57130
continue
58131
fi
59132

60-
# Skip chore, docs, ci, test, refactor, style, build — internal commits
61-
done < <(git log $LOG_ARGS HEAD 2>/dev/null)
133+
case "$CC_TYPE" in
134+
feat)
135+
if [[ "$CC_SCOPE" == "specs" || "$CC_SCOPE" == "spec" ]]; then
136+
# Extract resource name for New Resources section
137+
resource_name=$(extract_resource_name "$CC_MESSAGE")
138+
if [ -n "$resource_name" ]; then
139+
NEW_RESOURCES+=("- \`${resource_name}\` $(format_entry "" "$CC_PR" "$CC_HASH_FULL" "$REPO_URL")")
140+
else
141+
NEW_RESOURCES+=("- $entry")
142+
fi
143+
else
144+
if [ -n "$CC_SCOPE" ]; then
145+
FEATS+=("- **${CC_SCOPE}:** $entry")
146+
else
147+
FEATS+=("- $entry")
148+
fi
149+
fi
150+
;;
151+
fix)
152+
if [ -n "$CC_SCOPE" ]; then
153+
FIXES+=("- **${CC_SCOPE}:** $entry")
154+
else
155+
FIXES+=("- $entry")
156+
fi
157+
;;
158+
perf)
159+
if [ -n "$CC_SCOPE" ]; then
160+
PERFS+=("- **${CC_SCOPE}:** $entry")
161+
else
162+
PERFS+=("- $entry")
163+
fi
164+
;;
165+
revert)
166+
REVERTS+=("- $entry")
167+
;;
168+
esac
169+
done < <(git log $LOG_RANGE --format="%H|||%s" --no-merges 2>/dev/null)
62170

63-
# Also scan commit bodies for BREAKING CHANGE
171+
# Also scan commit bodies for BREAKING CHANGE footer
64172
while IFS= read -r body_line; do
65-
if echo "$body_line" | grep -q 'BREAKING CHANGE:'; then
66-
msg=$(echo "$body_line" | sed 's/BREAKING CHANGE: //')
173+
[ -z "$body_line" ] && continue
174+
if [[ "$body_line" == "BREAKING CHANGE:"* ]]; then
175+
msg="${body_line#BREAKING CHANGE: }"
67176
BREAKING+=("- $msg")
68177
fi
69-
done < <(git log ${SINCE_DATE:+--after=$SINCE_DATE} --format="%b" HEAD 2>/dev/null)
178+
done < <(git log $LOG_RANGE --format="%b" --no-merges 2>/dev/null)
179+
180+
# --- Output ---
70181

71-
# Output
72182
echo "## What's Changed in ${VERSION}"
73183
echo ""
74184

@@ -79,6 +189,13 @@ if [ ${#BREAKING[@]} -gt 0 ]; then
79189
echo ""
80190
fi
81191

192+
if [ ${#NEW_RESOURCES[@]} -gt 0 ]; then
193+
echo "### New Resources"
194+
echo ""
195+
printf '%s\n' "${NEW_RESOURCES[@]}"
196+
echo ""
197+
fi
198+
82199
if [ ${#FEATS[@]} -gt 0 ]; then
83200
echo "### Features"
84201
echo ""
@@ -93,7 +210,24 @@ if [ ${#FIXES[@]} -gt 0 ]; then
93210
echo ""
94211
fi
95212

96-
if [ ${#BREAKING[@]} -eq 0 ] && [ ${#FEATS[@]} -eq 0 ] && [ ${#FIXES[@]} -eq 0 ]; then
213+
if [ ${#PERFS[@]} -gt 0 ]; then
214+
echo "### Performance Improvements"
215+
echo ""
216+
printf '%s\n' "${PERFS[@]}"
217+
echo ""
218+
fi
219+
220+
if [ ${#REVERTS[@]} -gt 0 ]; then
221+
echo "### Reverts"
222+
echo ""
223+
printf '%s\n' "${REVERTS[@]}"
224+
echo ""
225+
fi
226+
227+
# Check if nothing was generated
228+
if [ ${#BREAKING[@]} -eq 0 ] && [ ${#NEW_RESOURCES[@]} -eq 0 ] && \
229+
[ ${#FEATS[@]} -eq 0 ] && [ ${#FIXES[@]} -eq 0 ] && \
230+
[ ${#PERFS[@]} -eq 0 ] && [ ${#REVERTS[@]} -eq 0 ]; then
97231
echo "No notable changes."
98232
echo ""
99233
fi

0 commit comments

Comments
 (0)