From 596bd752ad2ecea287be13e154a1879df974b0de Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Thu, 23 Oct 2025 03:50:30 +0200 Subject: [PATCH] Tweak release action --- .github/workflows/RELEASE_NOTES_GENERATION.md | 169 ++++++++++++++++++ .github/workflows/release.yml | 106 ++++++++++- 2 files changed, 267 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/RELEASE_NOTES_GENERATION.md diff --git a/.github/workflows/RELEASE_NOTES_GENERATION.md b/.github/workflows/RELEASE_NOTES_GENERATION.md new file mode 100644 index 00000000..de219de4 --- /dev/null +++ b/.github/workflows/RELEASE_NOTES_GENERATION.md @@ -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 +``` diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0927a22c..5649bb29 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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 -- 2.34.1