Tweak release action
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 23 Oct 2025 01:50:30 +0000 (03:50 +0200)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 23 Oct 2025 01:50:30 +0000 (03:50 +0200)
.github/workflows/RELEASE_NOTES_GENERATION.md [new file with mode: 0644]
.github/workflows/release.yml

diff --git a/.github/workflows/RELEASE_NOTES_GENERATION.md b/.github/workflows/RELEASE_NOTES_GENERATION.md
new file mode 100644 (file)
index 0000000..de219de
--- /dev/null
@@ -0,0 +1,169 @@
+# Release Notes Generation - Channel-Specific Behavior
+
+## Overview
+
+The release workflow generates release notes **specific to each channel** by only including commits since the last release of that same channel. It uses your **Release Drafter configuration** (`.github/release-drafter.yml`) for label-based categorization.
+
+## How It Works
+
+### 1. Previous Release Detection
+
+The workflow identifies the previous release for each channel using tag patterns:
+
+#### Stable Channel
+- **Pattern**: `^[0-9]+\.[0-9]+\.[0-9]+$` (e.g., `2.1.0`, `2.0.5`)
+- **Branch**: `stable`
+- **Finds**: Latest stable release (no suffix)
+
+#### Beta Channel
+- **Pattern**: `^[0-9]+\.[0-9]+\.[0-9]+\.b[0-9]+$` (e.g., `2.1.0.b1`, `2.1.0.b2`)
+- **Branch**: `dev`
+- **Finds**: Latest beta release (`.bN` suffix)
+
+#### Nightly Channel
+- **Pattern**: `^[0-9]+\.[0-9]+\.[0-9]+\.dev[0-9]+$` (e.g., `2.1.0.dev20251023`)
+- **Branch**: `dev`
+- **Finds**: Latest nightly release (`.devYYYYMMDD` suffix)
+
+### 2. Release Notes Generation
+
+The workflow generates notes in three steps:
+
+1. **Find PRs in commit range**: Extracts PR numbers from merge commits between the previous tag and HEAD
+2. **Categorize by labels**: Applies the category rules from `.github/release-drafter.yml`:
+   - ⚠ Breaking Changes (`breaking-change` label)
+   - 🚀 New Providers (`new-provider` label)
+   - 🚀 Features and enhancements (`feature`, `enhancement`, `new-feature` labels)
+   - 🐛 Bugfixes (`bugfix` label)
+   - 🧰 Maintenance (`ci`, `documentation`, `maintenance`, `dependencies` labels)
+3. **Add contributors**: Lists all unique contributors from the PRs
+
+### 3. What This Means
+
+#### ✅ Stable Release Notes
+- Include **only commits since the last stable release**
+- **Do NOT include** beta or nightly commits that happened in between
+- Example: `2.0.5` → `2.1.0` only shows stable branch commits
+
+#### ✅ Beta Release Notes
+- Include **only commits since the last beta release**
+- **Do NOT include** nightly commits
+- **Do NOT include** stable commits from stable branch
+- Example: `2.1.0.b2` → `2.1.0.b3` only shows dev branch commits since b2
+
+#### ✅ Nightly Release Notes
+- Include **only commits since the last nightly release**
+- **Do NOT include** beta or stable releases in between
+- Example: `2.1.0.dev20251022` → `2.1.0.dev20251023` only shows dev branch commits since yesterday
+
+## Release Drafter Configuration
+
+✅ The workflow **uses your `.github/release-drafter.yml` configuration** for:
+- Category definitions (labels → section headers)
+- Category titles and emoji
+- Excluded contributors (bots)
+- PR title format
+
+The workflow manually implements the categorization logic to ensure channel-specific commit ranges while preserving your custom formatting.
+
+## Example Release Notes Format
+
+```markdown
+## 📦 Beta Release
+
+_Changes since [2.1.0.b1](https://github.com/music-assistant/server/releases/tag/2.1.0.b1)_
+
+### ⚠ Breaking Changes
+
+- Major API refactoring (by @contributor1 in #123)
+
+### 🚀 Features and enhancements
+
+- Add new audio processor (by @contributor2 in #124)
+- Improve queue management (by @contributor3 in #125)
+
+### 🐛 Bugfixes
+
+- Fix playback issue (by @contributor1 in #126)
+
+### 🧰 Maintenance and dependency bumps
+
+- Update dependencies (by @dependabot in #127)
+- Improve CI pipeline (by @contributor2 in #128)
+
+## :bow: Thanks to our contributors
+
+Special thanks to the following contributors who helped with this release:
+
+@contributor1, @contributor2, @contributor3
+```
+
+## Testing
+
+To verify channel-specific release notes:
+
+1. **Create a beta release** after a stable release:
+   ```bash
+   # Should only show commits on dev branch since last beta
+   # Should NOT include stable branch commits
+   ```
+
+2. **Create a nightly release** after a beta release:
+   ```bash
+   # Should only show commits since yesterday's nightly
+   # Should NOT include beta release notes
+   ```
+
+3. **Create a stable release** after multiple betas:
+   ```bash
+   # Should only show commits on stable branch since last stable
+   # Should NOT include any beta or nightly commits
+   ```
+
+## Verification Commands
+
+```bash
+# Check what will be in next stable release
+git log $(git tag | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1)..stable --oneline
+
+# Check what will be in next beta release
+git log $(git tag | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.b[0-9]+$' | sort -V | tail -1)..dev --oneline
+
+# Check what will be in next nightly release
+git log $(git tag | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.dev[0-9]+$' | sort -V | tail -1)..dev --oneline
+```
+
+## Testing
+
+To verify channel-specific release notes:
+
+1. **Create a beta release** after a stable release:
+   ```bash
+   # Should only show commits on dev branch since last beta
+   # Should NOT include stable branch commits
+   ```
+
+2. **Create a nightly release** after a beta release:
+   ```bash
+   # Should only show commits since yesterday's nightly
+   # Should NOT include beta release notes
+   ```
+
+3. **Create a stable release** after multiple betas:
+   ```bash
+   # Should only show commits on stable branch since last stable
+   # Should NOT include any beta or nightly commits
+   ```
+
+## Verification Commands
+
+```bash
+# Check what will be in next stable release
+git log $(git tag | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1)..stable --oneline
+
+# Check what will be in next beta release
+git log $(git tag | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.b[0-9]+$' | sort -V | tail -1)..dev --oneline
+
+# Check what will be in next nightly release
+git log $(git tag | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.dev[0-9]+$' | sort -V | tail -1)..dev --oneline
+```
index 0927a22ccfe65f9e809f454ba76c0f62b91596ca..5649bb29c90ef638e0f04c2fb4356032dd30900c 100644 (file)
@@ -167,33 +167,73 @@ jobs:
           name: release-dists
           path: dist/
 
-      - name: Determine previous version tag
+      - name: Determine previous version tag and temporarily hide other channels
         id: prev_version
         run: |
           CHANNEL="${{ inputs.channel }}"
 
+          # Define patterns for each channel
+          case "$CHANNEL" in
+            stable)
+              KEEP_PATTERN='^[0-9]+\.[0-9]+\.[0-9]+$'
+              HIDE_PATTERN='\.(b|dev)[0-9]+'
+              ;;
+            beta)
+              KEEP_PATTERN='^[0-9]+\.[0-9]+\.[0-9]+\.b[0-9]+$'
+              HIDE_PATTERN='(^[0-9]+\.[0-9]+\.[0-9]+$|\.dev[0-9]+$)'
+              ;;
+            nightly)
+              KEEP_PATTERN='^[0-9]+\.[0-9]+\.[0-9]+\.dev[0-9]+$'
+              HIDE_PATTERN='(^[0-9]+\.[0-9]+\.[0-9]+$|\.b[0-9]+$)'
+              ;;
+          esac
+
+          echo "📋 Hiding releases from other channels for Release Drafter..."
+
+          # Get all releases and temporarily convert other channels to draft
+          gh release list --limit 100 --json tagName,isDraft,isPrerelease | jq -c '.[]' | while read -r release; do
+            TAG=$(echo "$release" | jq -r '.tagName')
+            IS_DRAFT=$(echo "$release" | jq -r '.isDraft')
+
+            # Skip if already a draft
+            if [ "$IS_DRAFT" = "true" ]; then
+              continue
+            fi
+
+            # Check if this release should be hidden (not matching current channel pattern)
+            if echo "$TAG" | grep -vE "$KEEP_PATTERN" > /dev/null 2>&1; then
+              echo "  Temporarily hiding: $TAG"
+              # Store this tag so we can restore it later
+              echo "$TAG" >> /tmp/hidden_releases.txt
+              # Mark as draft (makes it invisible to Release Drafter)
+              gh release edit "$TAG" --draft=true
+            fi
+          done
+
+          # Now find the previous tag of this channel
           case "$CHANNEL" in
             stable)
-              # For stable, find latest stable tag (no beta or dev suffix)
               PREV_TAG=$(git tag --sort=-version:refname | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1)
               ;;
             beta)
-              # For beta, find latest beta tag
               PREV_TAG=$(git tag --sort=-version:refname | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.b[0-9]+$' | head -n 1)
               ;;
             nightly)
-              # For nightly, find latest nightly tag
               PREV_TAG=$(git tag --sort=-version:refname | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.dev[0-9]+$' | head -n 1)
               ;;
           esac
 
           if [ -z "$PREV_TAG" ]; then
-            echo "No previous $CHANNEL release found, using all commits"
+            echo "⚠️  No previous $CHANNEL release found"
             echo "prev_tag=" >> $GITHUB_OUTPUT
+            echo "has_prev_tag=false" >> $GITHUB_OUTPUT
           else
-            echo "Previous $CHANNEL release: $PREV_TAG"
+            echo "✅ Previous $CHANNEL release: $PREV_TAG"
             echo "prev_tag=$PREV_TAG" >> $GITHUB_OUTPUT
+            echo "has_prev_tag=true" >> $GITHUB_OUTPUT
           fi
+        env:
+          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 
       - name: Create Release with Release Drafter
         id: create_release
@@ -207,6 +247,51 @@ jobs:
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 
+      - name: Restore hidden releases
+        if: always()
+        run: |
+          if [ -f /tmp/hidden_releases.txt ]; then
+            echo "📋 Restoring hidden releases..."
+            while read -r TAG; do
+              if [ -n "$TAG" ]; then
+                echo "  Restoring: $TAG"
+                gh release edit "$TAG" --draft=false
+              fi
+            done < /tmp/hidden_releases.txt
+            echo "✅ All releases restored"
+          else
+            echo "No releases to restore"
+          fi
+        env:
+          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Add channel context to release notes
+        if: steps.prev_version.outputs.has_prev_tag == 'true'
+        run: |
+          PREV_TAG="${{ steps.prev_version.outputs.prev_tag }}"
+          CHANNEL="${{ inputs.channel }}"
+          VERSION="${{ inputs.version }}"
+          REPO="${{ github.repository }}"
+
+          # Get current release notes from Release Drafter
+          gh release view "$VERSION" --json body --jq .body > /tmp/current_notes.md
+
+          # Prepend channel context
+          echo "## 📦 ${CHANNEL^} Release" > /tmp/new_notes.md
+          echo "" >> /tmp/new_notes.md
+          echo "_Changes since [$PREV_TAG](https://github.com/$REPO/releases/tag/$PREV_TAG)_" >> /tmp/new_notes.md
+          echo "" >> /tmp/new_notes.md
+          echo "___" >> /tmp/new_notes.md
+          echo "" >> /tmp/new_notes.md
+          cat /tmp/current_notes.md >> /tmp/new_notes.md
+
+          # Update the release
+          gh release edit "$VERSION" --notes-file /tmp/new_notes.md
+
+          echo "✅ Added channel context to release notes"
+        env:
+          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
       - name: Extract and append frontend changes to release notes
         id: update_notes
         env:
@@ -258,8 +343,13 @@ jobs:
               if [ -n "$pr_json" ]; then
                 BODY=$(echo "$pr_json" | jq -r '.body')
 
-                # Extract bullet points from the body, excluding section headers and contributors
-                echo "$BODY" | grep -E '^[[:space:]]*[•-]' | grep -v '🙇' | head -20 >> "$FRONTEND_FILE" || true
+                # Extract bullet points from the body, excluding:
+                # - Section headers (🙇)
+                # - Dependabot dependency lines (starting with "Chore(deps")
+                echo "$BODY" | grep -E '^[[:space:]]*[•-]' | \
+                  grep -v '🙇' | \
+                  grep -viE '^[[:space:]]*[•-][[:space:]]*Chore\(deps' | \
+                  head -20 >> "$FRONTEND_FILE" || true
 
                 # Extract contributors from frontend PR body
                 echo "$BODY" | grep -oP '@[a-zA-Z0-9_-]+' >> "$CONTRIBUTORS_FILE" || true