|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +CHANGELOG="CHANGELOG.md" |
| 4 | + |
| 5 | +# ANSI color codes |
| 6 | +RED="\033[31m" |
| 7 | +GREEN="\033[32m" |
| 8 | +YELLOW="\033[33m" |
| 9 | +RESET="\033[0m" |
| 10 | + |
| 11 | +failed=0 |
| 12 | + |
| 13 | +# Fetch upstream |
| 14 | +git remote add upstream https://github.com/${GITHUB_REPOSITORY}.git |
| 15 | +git fetch upstream main >/dev/null 2>&1 |
| 16 | + |
| 17 | +# Get raw diff |
| 18 | +raw_diff=$(git diff upstream/main -- "$CHANGELOG") |
| 19 | + |
| 20 | +# 1️⃣ Show raw diff with colors |
| 21 | +echo "=== Raw git diff of $CHANGELOG against upstream/main ===" |
| 22 | +while IFS= read -r line; do |
| 23 | + if [[ $line =~ ^\+ && ! $line =~ ^\+\+\+ ]]; then |
| 24 | + echo -e "${GREEN}$line${RESET}" |
| 25 | + elif [[ $line =~ ^- && ! $line =~ ^--- ]]; then |
| 26 | + echo -e "${RED}$line${RESET}" |
| 27 | + else |
| 28 | + echo "$line" |
| 29 | + fi |
| 30 | +done <<< "$raw_diff" |
| 31 | +echo "=================================" |
| 32 | + |
| 33 | +# 2️⃣ Extract added bullet lines |
| 34 | +added_bullets=() |
| 35 | +while IFS= read -r line; do |
| 36 | + [[ -n "$line" ]] && added_bullets+=("$line") |
| 37 | +done < <(echo "$raw_diff" | sed -n 's/^+//p' | grep -E '^[[:space:]]*[-*]' | sed '/^[[:space:]]*$/d') |
| 38 | + |
| 39 | +# 2️⃣a Extract deleted bullet lines |
| 40 | +deleted_bullets=() |
| 41 | +while IFS= read -r line; do |
| 42 | + [[ -n "$line" ]] && deleted_bullets+=("$line") |
| 43 | +done < <(echo "$raw_diff" | grep '^\-' | grep -vE '^(--- |\+\+\+ |@@ )' | sed 's/^-//') |
| 44 | + |
| 45 | +# 2️⃣b Warn if no added entries |
| 46 | +if [[ ${#added_bullets[@]} -eq 0 ]]; then |
| 47 | + echo -e "${RED}❌ No new changelog entries detected in this PR.${RESET}" |
| 48 | + echo -e "${YELLOW}⚠️ Please add an entry in [UNRELEASED] under the appropriate subheading.${RESET}" |
| 49 | + failed=1 |
| 50 | +fi |
| 51 | + |
| 52 | +# 3️⃣ Initialize results |
| 53 | +correctly_placed="" |
| 54 | +orphan_entries="" |
| 55 | +wrong_release_entries="" |
| 56 | + |
| 57 | +# 4️⃣ Walk through changelog to classify entries |
| 58 | +current_release="" |
| 59 | +current_subtitle="" |
| 60 | +in_unreleased=0 |
| 61 | + |
| 62 | +while IFS= read -r line; do |
| 63 | + # Track release sections |
| 64 | + if [[ $line =~ ^##\ \[Unreleased\] ]]; then |
| 65 | + current_release="Unreleased" |
| 66 | + in_unreleased=1 |
| 67 | + current_subtitle="" |
| 68 | + continue |
| 69 | + elif [[ $line =~ ^##\ \[.*\] ]]; then |
| 70 | + current_release="$line" |
| 71 | + in_unreleased=0 |
| 72 | + current_subtitle="" |
| 73 | + continue |
| 74 | + elif [[ $line =~ ^### ]]; then |
| 75 | + current_subtitle="$line" |
| 76 | + continue |
| 77 | + fi |
| 78 | + |
| 79 | + # Check each added bullet |
| 80 | + for added in "${added_bullets[@]}"; do |
| 81 | + if [[ "$line" == "$added" ]]; then |
| 82 | + if [[ "$in_unreleased" -eq 1 && -n "$current_subtitle" ]]; then |
| 83 | + correctly_placed+="$added (placed under $current_subtitle)"$'\n' |
| 84 | + elif [[ "$in_unreleased" -eq 1 && -z "$current_subtitle" ]]; then |
| 85 | + orphan_entries+="$added (NOT under a subtitle)"$'\n' |
| 86 | + elif [[ "$in_unreleased" -eq 0 ]]; then |
| 87 | + wrong_release_entries+="$added (added under released version $current_release)"$'\n' |
| 88 | + fi |
| 89 | + fi |
| 90 | + done |
| 91 | +done < "$CHANGELOG" |
| 92 | + |
| 93 | +# 5️⃣ Display results |
| 94 | +if [[ -n "$orphan_entries" ]]; then |
| 95 | + echo -e "${RED}❌ Some CHANGELOG entries are not under a subtitle in [Unreleased]:${RESET}" |
| 96 | + echo "$orphan_entries" |
| 97 | + failed=1 |
| 98 | +fi |
| 99 | + |
| 100 | +if [[ -n "$wrong_release_entries" ]]; then |
| 101 | + echo -e "${RED}❌ Some changelog entries were added under a released version (should be in [Unreleased]):${RESET}" |
| 102 | + echo "$wrong_release_entries" |
| 103 | + failed=1 |
| 104 | +fi |
| 105 | + |
| 106 | +if [[ -n "$correctly_placed" ]]; then |
| 107 | + echo -e "${GREEN}✅ Some CHANGELOG entries are correctly placed under [Unreleased]:${RESET}" |
| 108 | + echo "$correctly_placed" |
| 109 | +fi |
| 110 | + |
| 111 | +# 6️⃣ Display deleted entries |
| 112 | +if [[ ${#deleted_bullets[@]} -gt 0 ]]; then |
| 113 | + echo -e "${RED}❌ Changelog entries removed in this PR:${RESET}" |
| 114 | + for deleted in "${deleted_bullets[@]}"; do |
| 115 | + echo -e " - ${RED}$deleted${RESET}" |
| 116 | + done |
| 117 | + echo -e "${YELLOW}⚠️ Please add these entries back under the appropriate sections${RESET}" |
| 118 | +fi |
| 119 | + |
| 120 | +# 7️⃣ Exit with failure if any bad entries exist |
| 121 | +if [[ $failed -eq 1 ]]; then |
| 122 | + echo -e "${RED}❌ Changelog check failed.${RESET}" |
| 123 | + exit 1 |
| 124 | +else |
| 125 | + echo -e "${GREEN}✅ Changelog check passed.${RESET}" |
| 126 | + exit 0 |
| 127 | +fi |
0 commit comments