7373 # List files in the PR and check for CHANGELOG.md (root or any path ending with /CHANGELOG.md)
7474 FILES_JSON="$(gh api repos/${{ github.repository }}/pulls/${PR_NUMBER}/files --paginate)"
7575 if ! echo "${FILES_JSON}" | jq -e '.[] | select(.filename | test("(^|/)CHANGELOG\\.md$"; "i"))' >/dev/null; then
76- echo "FAIL: CHANGELOG.md was not changed in this PR."
76+ echo "❌ FAIL: CHANGELOG.md was not changed in this PR."
77+ echo ""
78+ echo "Please add an entry to CHANGELOG.md under the [Unreleased] section."
7779 exit 1
7880 fi
7981
@@ -83,15 +85,84 @@ jobs:
8385
8486 # If no patch is returned (very large file or API omission), treat presence as sufficient
8587 if [[ -z "${PATCH_CONTENT}" ]]; then
86- echo "CHANGELOG.md modified (no patch provided by API). Passing ."
88+ echo "✅ PASS: CHANGELOG.md modified (no patch provided by API)."
8789 exit 0
8890 fi
8991
90- # Look for actual line changes (exclude diff headers +++/---)
91- if echo "${PATCH_CONTENT}" | awk '{print $0}' | grep -E '^[+-]' | grep -vE '^\+\+\+|^\-\-\-' >/dev/null; then
92- echo "PASS: CHANGELOG.md contains line-level changes."
92+ # Extract only the added lines from the patch (lines starting with +, excluding +++ header)
93+ ADDED_LINES="$(echo "${PATCH_CONTENT}" | grep -E '^\+' | grep -v '^\+\+\+' || true)"
94+
95+ # Check if there are any actual additions
96+ if [[ -z "${ADDED_LINES}" ]]; then
97+ echo "❌ FAIL: No line-level additions detected in CHANGELOG.md."
98+ echo ""
99+ echo "Please add an entry to CHANGELOG.md under the [Unreleased] section."
100+ exit 1
101+ fi
102+
103+ # Check if changes are under [Unreleased]
104+ # Parse the patch to track which section we're in and validate additions
105+ IN_UNRELEASED=false
106+ IN_RELEASED_VERSION=false
107+ FOUND_VALID_ADDITION=false
108+ RELEASED_VERSION_FOUND=""
109+
110+ while IFS= read -r line; do
111+ # Check for [Unreleased] header (context line or added line)
112+ if [[ "$line" =~ \[Unreleased\] ]]; then
113+ IN_UNRELEASED=true
114+ IN_RELEASED_VERSION=false
115+ RELEASED_VERSION_FOUND=""
116+ fi
117+
118+ # Check for released version header pattern: ## [X.Y.Z] - DATE
119+ # Match both context and added lines
120+ if [[ "$line" =~ \[([0-9]+\.[0-9]+\.[0-9]+)\].*-.*[0-9]{4} ]]; then
121+ # We found a released version header
122+ RELEASED_VERSION_FOUND="${BASH_REMATCH[1]}"
123+ IN_UNRELEASED=false
124+ IN_RELEASED_VERSION=true
125+ fi
126+
127+ # Check for added lines (starting with +, not +++)
128+ if [[ "$line" =~ ^\+[^+] ]]; then
129+ # Extract the actual content (remove the leading +)
130+ ADDED_CONTENT="${line:1}"
131+
132+ # Skip empty lines and section headers
133+ if [[ -n "$ADDED_CONTENT" && ! "$ADDED_CONTENT" =~ ^###\ ]]; then
134+ if [[ "$IN_UNRELEASED" == true ]]; then
135+ FOUND_VALID_ADDITION=true
136+ elif [[ "$IN_RELEASED_VERSION" == true && -n "$RELEASED_VERSION_FOUND" ]]; then
137+ # Found an addition under a released version - this is wrong
138+ echo "❌ FAIL: Changelog entry found under a released version, not under [Unreleased]."
139+ echo ""
140+ echo "You added content under version [$RELEASED_VERSION_FOUND] instead of [Unreleased]:"
141+ echo " $ADDED_CONTENT"
142+ echo ""
143+ echo "📝 Please move your changes to the [Unreleased] section at the top of CHANGELOG.md"
144+ echo ""
145+ echo "Example structure:"
146+ echo " ## [Unreleased]"
147+ echo " ### Added"
148+ echo " - Your new feature or fix here"
149+ exit 1
150+ fi
151+ fi
152+ fi
153+ done <<< "$PATCH_CONTENT"
154+
155+ if [[ "$FOUND_VALID_ADDITION" == true ]]; then
156+ echo "✅ PASS: CHANGELOG.md contains valid additions under [Unreleased]."
93157 exit 0
94158 else
95- echo "FAIL: No line-level changes detected in CHANGELOG.md."
159+ echo "❌ FAIL: No valid changelog entries found under [Unreleased]."
160+ echo ""
161+ echo "Please ensure your changes are added under the [Unreleased] section of CHANGELOG.md"
162+ echo ""
163+ echo "Example:"
164+ echo " ## [Unreleased]"
165+ echo " ### Added"
166+ echo " - Your feature/fix description"
96167 exit 1
97168 fi
0 commit comments