From a96ee381f3c2560a09979293c1d4d6b7b6f770fc Mon Sep 17 00:00:00 2001 From: Gray Zhang Date: Fri, 19 Sep 2025 00:07:11 +0800 Subject: [PATCH 1/3] feat: improve release notes generation with categorization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Categorize commits into Features, Bug Fixes, Improvements, and Performance - Clean commit messages by removing PR numbers and prefixes - Format release notes with emojis and proper sections - Apply same categorization to both GitHub and Google Play release notes - Capitalize first letter of each changelog entry for better readability 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .github/workflows/release.yml | 324 ++++++++++++++++++++++++++++++---- 1 file changed, 290 insertions(+), 34 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b06f360c..d4942697 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -348,13 +348,50 @@ jobs: id: changelog env: GH_TOKEN: ${{ github.token }} + GITHUB_REPOSITORY: ${{ github.repository }} run: | - echo "## What's Changed" > CHANGELOG.md - echo "" >> CHANGELOG.md - # Get commits since last tag LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") - + CURRENT_TAG="${{ needs.prepare.outputs.version }}" + + # Function to categorize commit message + categorize_commit() { + local msg="$1" + local category="" + local cleaned_msg="" + + if [[ "$msg" =~ ^fix(\(.*\))?:\ (.*)$ ]] || [[ "$msg" =~ ^fix\ (.*)$ ]]; then + category="bug" + cleaned_msg="${BASH_REMATCH[-1]}" + elif [[ "$msg" =~ ^feat(\(.*\))?:\ (.*)$ ]] || [[ "$msg" =~ ^feat\ (.*)$ ]]; then + category="feature" + cleaned_msg="${BASH_REMATCH[-1]}" + elif [[ "$msg" =~ ^perf(\(.*\))?:\ (.*)$ ]]; then + category="performance" + cleaned_msg="${BASH_REMATCH[2]}" + elif [[ "$msg" =~ ^refactor(\(.*\))?:\ (.*)$ ]]; then + category="improvement" + cleaned_msg="${BASH_REMATCH[2]}" + elif [[ "$msg" =~ ^chore(\(.*\))?:\ (.*)$ ]]; then + category="maintenance" + cleaned_msg="${BASH_REMATCH[2]}" + elif [[ "$msg" =~ ^docs(\(.*\))?:\ (.*)$ ]]; then + category="documentation" + cleaned_msg="${BASH_REMATCH[2]}" + else + category="other" + cleaned_msg="$msg" + fi + + # Remove PR numbers from the end + cleaned_msg=$(echo "$cleaned_msg" | sed 's/ (#[0-9]*)//') + + # Capitalize first letter + cleaned_msg="$(echo "${cleaned_msg:0:1}" | tr '[:lower:]' '[:upper:]')${cleaned_msg:1}" + + echo "$category:$cleaned_msg" + } + # Function to get GitHub username from commit get_github_username() { local commit_sha="$1" @@ -385,23 +422,111 @@ jobs: fi fi } - - # Generate changelog with GitHub usernames + + # Collect commits and categorize them + declare -A features + declare -A bugs + declare -A improvements + declare -A performance + declare -A maintenance + if [ -n "$LAST_TAG" ]; then - while IFS= read -r commit_sha; do - commit_msg=$(git show -s --format='%s' $commit_sha) - author=$(get_github_username $commit_sha) - echo "* $commit_msg by $author" >> CHANGELOG.md - done < <(git rev-list "$LAST_TAG"..HEAD) + RANGE="$LAST_TAG..HEAD" else - while IFS= read -r commit_sha; do - commit_msg=$(git show -s --format='%s' $commit_sha) - author=$(get_github_username $commit_sha) - echo "* $commit_msg by $author" >> CHANGELOG.md - done < <(git rev-list HEAD -10) + RANGE="HEAD" fi - + + # Process commits + while IFS= read -r line; do + sha=$(echo "$line" | cut -d' ' -f1) + msg=$(echo "$line" | cut -d' ' -f2-) + + # Skip version bump and merge commits + if [[ "$msg" =~ "bump version" ]] || [[ "$msg" =~ "Merge pull request" ]] || [[ "$msg" =~ "Merge branch" ]]; then + continue + fi + + categorized=$(categorize_commit "$msg") + category=$(echo "$categorized" | cut -d':' -f1) + clean_msg=$(echo "$categorized" | cut -d':' -f2-) + author=$(get_github_username "$sha") + + # Store in associative arrays + case "$category" in + feature) + features["$clean_msg"]="$author" + ;; + bug) + bugs["$clean_msg"]="$author" + ;; + improvement) + improvements["$clean_msg"]="$author" + ;; + performance) + performance["$clean_msg"]="$author" + ;; + maintenance) + maintenance["$clean_msg"]="$author" + ;; + esac + done < <(git log --oneline --no-merges $RANGE) + + # Generate GitHub Release Notes + echo "## What's Changed" > CHANGELOG.md echo "" >> CHANGELOG.md + + if [ ${#features[@]} -gt 0 ]; then + echo "### 🚀 New Features" >> CHANGELOG.md + for msg in "${!features[@]}"; do + author="${features[$msg]}" + if [ -n "$author" ]; then + echo "* $msg by $author" >> CHANGELOG.md + else + echo "* $msg" >> CHANGELOG.md + fi + done + echo "" >> CHANGELOG.md + fi + + if [ ${#bugs[@]} -gt 0 ]; then + echo "### 🐛 Bug Fixes" >> CHANGELOG.md + for msg in "${!bugs[@]}"; do + author="${bugs[$msg]}" + if [ -n "$author" ]; then + echo "* $msg by $author" >> CHANGELOG.md + else + echo "* $msg" >> CHANGELOG.md + fi + done + echo "" >> CHANGELOG.md + fi + + if [ ${#improvements[@]} -gt 0 ]; then + echo "### 💪 Improvements" >> CHANGELOG.md + for msg in "${!improvements[@]}"; do + author="${improvements[$msg]}" + if [ -n "$author" ]; then + echo "* $msg by $author" >> CHANGELOG.md + else + echo "* $msg" >> CHANGELOG.md + fi + done + echo "" >> CHANGELOG.md + fi + + if [ ${#performance[@]} -gt 0 ]; then + echo "### ⚡ Performance" >> CHANGELOG.md + for msg in "${!performance[@]}"; do + author="${performance[$msg]}" + if [ -n "$author" ]; then + echo "* $msg by $author" >> CHANGELOG.md + else + echo "* $msg" >> CHANGELOG.md + fi + done + echo "" >> CHANGELOG.md + fi + echo "" >> CHANGELOG.md echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${LAST_TAG}...${{ needs.prepare.outputs.version }}" >> CHANGELOG.md @@ -477,27 +602,158 @@ jobs: run: | mkdir -p whatsnew - # Generate release notes for public test track - echo "V2er Beta Release ${{ needs.prepare.outputs.version }}" > whatsnew/whatsnew-en-US - echo "" >> whatsnew/whatsnew-en-US - echo "What's new in this beta:" >> whatsnew/whatsnew-en-US - echo "" >> whatsnew/whatsnew-en-US + # Get commits since last tag for categorization + LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") - # Get recent commits formatted for users - git log --pretty=format:"• %s" -5 | sed 's/^• fix:/• Fixed:/g' | sed 's/^• feat:/• New:/g' | sed 's/^• chore:/• Updated:/g' >> whatsnew/whatsnew-en-US - echo "" >> whatsnew/whatsnew-en-US + # Function to categorize commit message (same as above) + categorize_commit() { + local msg="$1" + local category="" + local cleaned_msg="" + + if [[ "$msg" =~ ^fix(\(.*\))?:\ (.*)$ ]] || [[ "$msg" =~ ^fix\ (.*)$ ]]; then + category="bug" + cleaned_msg="${BASH_REMATCH[-1]}" + elif [[ "$msg" =~ ^feat(\(.*\))?:\ (.*)$ ]] || [[ "$msg" =~ ^feat\ (.*)$ ]]; then + category="feature" + cleaned_msg="${BASH_REMATCH[-1]}" + elif [[ "$msg" =~ ^perf(\(.*\))?:\ (.*)$ ]]; then + category="performance" + cleaned_msg="${BASH_REMATCH[2]}" + elif [[ "$msg" =~ ^refactor(\(.*\))?:\ (.*)$ ]]; then + category="improvement" + cleaned_msg="${BASH_REMATCH[2]}" + else + category="other" + cleaned_msg="$msg" + fi + + # Remove PR numbers from the end + cleaned_msg=$(echo "$cleaned_msg" | sed 's/ (#[0-9]*)//') + + # Capitalize first letter + cleaned_msg="$(echo "${cleaned_msg:0:1}" | tr '[:lower:]' '[:upper:]')${cleaned_msg:1}" + + echo "$category:$cleaned_msg" + } + + # Collect and categorize commits + declare -A features + declare -A bugs + declare -A improvements + declare -A performance + + if [ -n "$LAST_TAG" ]; then + RANGE="$LAST_TAG..HEAD" + else + RANGE="HEAD~5..HEAD" + fi + + # Process commits + while IFS= read -r line; do + sha=$(echo "$line" | cut -d' ' -f1) + msg=$(echo "$line" | cut -d' ' -f2-) + + # Skip version bump and merge commits + if [[ "$msg" =~ "bump version" ]] || [[ "$msg" =~ "Merge pull request" ]] || [[ "$msg" =~ "Merge branch" ]]; then + continue + fi + + categorized=$(categorize_commit "$msg") + category=$(echo "$categorized" | cut -d':' -f1) + clean_msg=$(echo "$categorized" | cut -d':' -f2-) + + case "$category" in + feature) + features["$clean_msg"]="1" + ;; + bug) + bugs["$clean_msg"]="1" + ;; + improvement) + improvements["$clean_msg"]="1" + ;; + performance) + performance["$clean_msg"]="1" + ;; + esac + done < <(git log --oneline --no-merges $RANGE) + + # Generate English release notes + echo "V2er ${{ needs.prepare.outputs.version }}" > whatsnew/whatsnew-en-US echo "" >> whatsnew/whatsnew-en-US - echo "Thank you for testing! Please report any issues on GitHub." >> whatsnew/whatsnew-en-US - # Chinese version - echo "V2er 测试版 ${{ needs.prepare.outputs.version }}" > whatsnew/whatsnew-zh-CN - echo "" >> whatsnew/whatsnew-zh-CN - echo "此测试版的新内容:" >> whatsnew/whatsnew-zh-CN - echo "" >> whatsnew/whatsnew-zh-CN - git log --pretty=format:"• %s" -5 | sed 's/^• fix:/• 修复:/g' | sed 's/^• feat:/• 新增:/g' | sed 's/^• chore:/• 更新:/g' >> whatsnew/whatsnew-zh-CN - echo "" >> whatsnew/whatsnew-zh-CN + if [ ${#features[@]} -gt 0 ]; then + echo "🚀 New Features:" >> whatsnew/whatsnew-en-US + for msg in "${!features[@]}"; do + echo "• $msg" >> whatsnew/whatsnew-en-US + done + echo "" >> whatsnew/whatsnew-en-US + fi + + if [ ${#bugs[@]} -gt 0 ]; then + echo "🐛 Bug Fixes:" >> whatsnew/whatsnew-en-US + for msg in "${!bugs[@]}"; do + echo "• $msg" >> whatsnew/whatsnew-en-US + done + echo "" >> whatsnew/whatsnew-en-US + fi + + if [ ${#improvements[@]} -gt 0 ]; then + echo "💪 Improvements:" >> whatsnew/whatsnew-en-US + for msg in "${!improvements[@]}"; do + echo "• $msg" >> whatsnew/whatsnew-en-US + done + echo "" >> whatsnew/whatsnew-en-US + fi + + if [ ${#performance[@]} -gt 0 ]; then + echo "⚡ Performance:" >> whatsnew/whatsnew-en-US + for msg in "${!performance[@]}"; do + echo "• $msg" >> whatsnew/whatsnew-en-US + done + echo "" >> whatsnew/whatsnew-en-US + fi + + echo "Thank you for using V2er! Please report any issues on GitHub." >> whatsnew/whatsnew-en-US + + # Generate Chinese release notes + echo "V2er ${{ needs.prepare.outputs.version }}" > whatsnew/whatsnew-zh-CN echo "" >> whatsnew/whatsnew-zh-CN - echo "感谢您的测试!如遇问题请在GitHub上反馈。" >> whatsnew/whatsnew-zh-CN + + if [ ${#features[@]} -gt 0 ]; then + echo "🚀 新功能:" >> whatsnew/whatsnew-zh-CN + for msg in "${!features[@]}"; do + echo "• $msg" >> whatsnew/whatsnew-zh-CN + done + echo "" >> whatsnew/whatsnew-zh-CN + fi + + if [ ${#bugs[@]} -gt 0 ]; then + echo "🐛 问题修复:" >> whatsnew/whatsnew-zh-CN + for msg in "${!bugs[@]}"; do + echo "• $msg" >> whatsnew/whatsnew-zh-CN + done + echo "" >> whatsnew/whatsnew-zh-CN + fi + + if [ ${#improvements[@]} -gt 0 ]; then + echo "💪 改进优化:" >> whatsnew/whatsnew-zh-CN + for msg in "${!improvements[@]}"; do + echo "• $msg" >> whatsnew/whatsnew-zh-CN + done + echo "" >> whatsnew/whatsnew-zh-CN + fi + + if [ ${#performance[@]} -gt 0 ]; then + echo "⚡ 性能优化:" >> whatsnew/whatsnew-zh-CN + for msg in "${!performance[@]}"; do + echo "• $msg" >> whatsnew/whatsnew-zh-CN + done + echo "" >> whatsnew/whatsnew-zh-CN + fi + + echo "感谢您使用 V2er!如遇问题请在 GitHub 上反馈。" >> whatsnew/whatsnew-zh-CN - name: Upload to Play Store (with debug symbols) if: steps.find-files.outputs.symbols_path != '' From a165ee7b8b20fe9d7780349ebf9a1361a5b21611 Mon Sep 17 00:00:00 2001 From: Gray Zhang Date: Fri, 19 Sep 2025 00:13:22 +0800 Subject: [PATCH 2/3] feat: add contributor mentions in release notes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Include GitHub usernames (@username) for each change - Add contributors section showing all contributors in the release - Apply to both English and Chinese release notes for Google Play - Maintain author attribution throughout the pipeline 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .github/workflows/release.yml | 113 ++++++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d4942697..4b707301 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -599,6 +599,9 @@ jobs: echo "Deploying to track: $TRACK with status: $STATUS" - name: Create whatsnew directory + env: + GH_TOKEN: ${{ github.token }} + GITHUB_REPOSITORY: ${{ github.repository }} run: | mkdir -p whatsnew @@ -637,11 +640,39 @@ jobs: echo "$category:$cleaned_msg" } + # Function to get GitHub username from commit (reuse from above) + get_github_username() { + local commit_sha="$1" + local username=$(gh api "repos/${{ github.repository }}/commits/${commit_sha}" --jq '.author.login // empty' 2>/dev/null || echo "") + if [ -n "$username" ]; then + echo "@$username" + else + local committer=$(gh api "repos/${{ github.repository }}/commits/${commit_sha}" --jq '.committer.login // empty' 2>/dev/null || echo "") + if [ -n "$committer" ]; then + echo "@$committer" + else + local git_author=$(git show -s --format='%an' $commit_sha) + case "$git_author" in + "Gray Zhang" | "gray" | "Gray") + echo "@graycreate" + ;; + "github-actions[bot]") + echo "@github-actions[bot]" + ;; + *) + echo "" + ;; + esac + fi + fi + } + # Collect and categorize commits declare -A features declare -A bugs declare -A improvements declare -A performance + declare -A contributors if [ -n "$LAST_TAG" ]; then RANGE="$LAST_TAG..HEAD" @@ -663,18 +694,24 @@ jobs: category=$(echo "$categorized" | cut -d':' -f1) clean_msg=$(echo "$categorized" | cut -d':' -f2-) + # Get author for this commit + author=$(get_github_username "$sha") + if [ -n "$author" ]; then + contributors["$author"]="1" + fi + case "$category" in feature) - features["$clean_msg"]="1" + features["$clean_msg"]="$author" ;; bug) - bugs["$clean_msg"]="1" + bugs["$clean_msg"]="$author" ;; improvement) - improvements["$clean_msg"]="1" + improvements["$clean_msg"]="$author" ;; performance) - performance["$clean_msg"]="1" + performance["$clean_msg"]="$author" ;; esac done < <(git log --oneline --no-merges $RANGE) @@ -686,7 +723,12 @@ jobs: if [ ${#features[@]} -gt 0 ]; then echo "🚀 New Features:" >> whatsnew/whatsnew-en-US for msg in "${!features[@]}"; do - echo "• $msg" >> whatsnew/whatsnew-en-US + author="${features[$msg]}" + if [ -n "$author" ]; then + echo "• $msg (by $author)" >> whatsnew/whatsnew-en-US + else + echo "• $msg" >> whatsnew/whatsnew-en-US + fi done echo "" >> whatsnew/whatsnew-en-US fi @@ -694,7 +736,12 @@ jobs: if [ ${#bugs[@]} -gt 0 ]; then echo "🐛 Bug Fixes:" >> whatsnew/whatsnew-en-US for msg in "${!bugs[@]}"; do - echo "• $msg" >> whatsnew/whatsnew-en-US + author="${bugs[$msg]}" + if [ -n "$author" ]; then + echo "• $msg (by $author)" >> whatsnew/whatsnew-en-US + else + echo "• $msg" >> whatsnew/whatsnew-en-US + fi done echo "" >> whatsnew/whatsnew-en-US fi @@ -702,7 +749,12 @@ jobs: if [ ${#improvements[@]} -gt 0 ]; then echo "💪 Improvements:" >> whatsnew/whatsnew-en-US for msg in "${!improvements[@]}"; do - echo "• $msg" >> whatsnew/whatsnew-en-US + author="${improvements[$msg]}" + if [ -n "$author" ]; then + echo "• $msg (by $author)" >> whatsnew/whatsnew-en-US + else + echo "• $msg" >> whatsnew/whatsnew-en-US + fi done echo "" >> whatsnew/whatsnew-en-US fi @@ -710,11 +762,22 @@ jobs: if [ ${#performance[@]} -gt 0 ]; then echo "⚡ Performance:" >> whatsnew/whatsnew-en-US for msg in "${!performance[@]}"; do - echo "• $msg" >> whatsnew/whatsnew-en-US + author="${performance[$msg]}" + if [ -n "$author" ]; then + echo "• $msg (by $author)" >> whatsnew/whatsnew-en-US + else + echo "• $msg" >> whatsnew/whatsnew-en-US + fi done echo "" >> whatsnew/whatsnew-en-US fi + # Add contributors section if there are any + if [ ${#contributors[@]} -gt 0 ]; then + echo "👥 Contributors: ${!contributors[@]}" >> whatsnew/whatsnew-en-US + echo "" >> whatsnew/whatsnew-en-US + fi + echo "Thank you for using V2er! Please report any issues on GitHub." >> whatsnew/whatsnew-en-US # Generate Chinese release notes @@ -724,7 +787,12 @@ jobs: if [ ${#features[@]} -gt 0 ]; then echo "🚀 新功能:" >> whatsnew/whatsnew-zh-CN for msg in "${!features[@]}"; do - echo "• $msg" >> whatsnew/whatsnew-zh-CN + author="${features[$msg]}" + if [ -n "$author" ]; then + echo "• $msg (贡献者 $author)" >> whatsnew/whatsnew-zh-CN + else + echo "• $msg" >> whatsnew/whatsnew-zh-CN + fi done echo "" >> whatsnew/whatsnew-zh-CN fi @@ -732,7 +800,12 @@ jobs: if [ ${#bugs[@]} -gt 0 ]; then echo "🐛 问题修复:" >> whatsnew/whatsnew-zh-CN for msg in "${!bugs[@]}"; do - echo "• $msg" >> whatsnew/whatsnew-zh-CN + author="${bugs[$msg]}" + if [ -n "$author" ]; then + echo "• $msg (贡献者 $author)" >> whatsnew/whatsnew-zh-CN + else + echo "• $msg" >> whatsnew/whatsnew-zh-CN + fi done echo "" >> whatsnew/whatsnew-zh-CN fi @@ -740,7 +813,12 @@ jobs: if [ ${#improvements[@]} -gt 0 ]; then echo "💪 改进优化:" >> whatsnew/whatsnew-zh-CN for msg in "${!improvements[@]}"; do - echo "• $msg" >> whatsnew/whatsnew-zh-CN + author="${improvements[$msg]}" + if [ -n "$author" ]; then + echo "• $msg (贡献者 $author)" >> whatsnew/whatsnew-zh-CN + else + echo "• $msg" >> whatsnew/whatsnew-zh-CN + fi done echo "" >> whatsnew/whatsnew-zh-CN fi @@ -748,11 +826,22 @@ jobs: if [ ${#performance[@]} -gt 0 ]; then echo "⚡ 性能优化:" >> whatsnew/whatsnew-zh-CN for msg in "${!performance[@]}"; do - echo "• $msg" >> whatsnew/whatsnew-zh-CN + author="${performance[$msg]}" + if [ -n "$author" ]; then + echo "• $msg (贡献者 $author)" >> whatsnew/whatsnew-zh-CN + else + echo "• $msg" >> whatsnew/whatsnew-zh-CN + fi done echo "" >> whatsnew/whatsnew-zh-CN fi + # Add contributors section if there are any + if [ ${#contributors[@]} -gt 0 ]; then + echo "👥 贡献者:${!contributors[@]}" >> whatsnew/whatsnew-zh-CN + echo "" >> whatsnew/whatsnew-zh-CN + fi + echo "感谢您使用 V2er!如遇问题请在 GitHub 上反馈。" >> whatsnew/whatsnew-zh-CN - name: Upload to Play Store (with debug symbols) From 60d418d696c312b00448959f0eb88f365bc9ec69 Mon Sep 17 00:00:00 2001 From: Gray Zhang Date: Fri, 19 Sep 2025 09:32:59 +0800 Subject: [PATCH 3/3] fix: address Copilot review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Eliminate duplicate categorize_commit function definitions - Create shared functions file at /tmp/release_functions.sh - Ensure consistent categorization across GitHub and Google Play notes - Fix variable scoping for GITHUB_REPOSITORY in functions - Include all commit types (chore, docs) in both sections 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .github/workflows/release.yml | 81 +++++++---------------------------- 1 file changed, 16 insertions(+), 65 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4b707301..177b20dc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -350,10 +350,8 @@ jobs: GH_TOKEN: ${{ github.token }} GITHUB_REPOSITORY: ${{ github.repository }} run: | - # Get commits since last tag - LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") - CURRENT_TAG="${{ needs.prepare.outputs.version }}" - + # Define shared functions that will be used in both changelog generation steps + cat > /tmp/release_functions.sh << 'FUNCTIONS_EOF' # Function to categorize commit message categorize_commit() { local msg="$1" @@ -395,13 +393,14 @@ jobs: # Function to get GitHub username from commit get_github_username() { local commit_sha="$1" + local github_repo="${GITHUB_REPOSITORY}" # Try to get the GitHub username from the commit using gh api - local username=$(gh api "repos/${{ github.repository }}/commits/${commit_sha}" --jq '.author.login // empty' 2>/dev/null || echo "") + local username=$(gh api "repos/${github_repo}/commits/${commit_sha}" --jq '.author.login // empty' 2>/dev/null || echo "") if [ -n "$username" ]; then echo "@$username" else # Fallback: try to get committer login if author login is not available - local committer=$(gh api "repos/${{ github.repository }}/commits/${commit_sha}" --jq '.committer.login // empty' 2>/dev/null || echo "") + local committer=$(gh api "repos/${github_repo}/commits/${commit_sha}" --jq '.committer.login // empty' 2>/dev/null || echo "") if [ -n "$committer" ]; then echo "@$committer" else @@ -422,6 +421,14 @@ jobs: fi fi } + FUNCTIONS_EOF + + # Source the functions + source /tmp/release_functions.sh + + # Get commits since last tag + LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") + CURRENT_TAG="${{ needs.prepare.outputs.version }}" # Collect commits and categorize them declare -A features @@ -605,68 +612,12 @@ jobs: run: | mkdir -p whatsnew + # Source the shared functions defined earlier + source /tmp/release_functions.sh + # Get commits since last tag for categorization LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") - # Function to categorize commit message (same as above) - categorize_commit() { - local msg="$1" - local category="" - local cleaned_msg="" - - if [[ "$msg" =~ ^fix(\(.*\))?:\ (.*)$ ]] || [[ "$msg" =~ ^fix\ (.*)$ ]]; then - category="bug" - cleaned_msg="${BASH_REMATCH[-1]}" - elif [[ "$msg" =~ ^feat(\(.*\))?:\ (.*)$ ]] || [[ "$msg" =~ ^feat\ (.*)$ ]]; then - category="feature" - cleaned_msg="${BASH_REMATCH[-1]}" - elif [[ "$msg" =~ ^perf(\(.*\))?:\ (.*)$ ]]; then - category="performance" - cleaned_msg="${BASH_REMATCH[2]}" - elif [[ "$msg" =~ ^refactor(\(.*\))?:\ (.*)$ ]]; then - category="improvement" - cleaned_msg="${BASH_REMATCH[2]}" - else - category="other" - cleaned_msg="$msg" - fi - - # Remove PR numbers from the end - cleaned_msg=$(echo "$cleaned_msg" | sed 's/ (#[0-9]*)//') - - # Capitalize first letter - cleaned_msg="$(echo "${cleaned_msg:0:1}" | tr '[:lower:]' '[:upper:]')${cleaned_msg:1}" - - echo "$category:$cleaned_msg" - } - - # Function to get GitHub username from commit (reuse from above) - get_github_username() { - local commit_sha="$1" - local username=$(gh api "repos/${{ github.repository }}/commits/${commit_sha}" --jq '.author.login // empty' 2>/dev/null || echo "") - if [ -n "$username" ]; then - echo "@$username" - else - local committer=$(gh api "repos/${{ github.repository }}/commits/${commit_sha}" --jq '.committer.login // empty' 2>/dev/null || echo "") - if [ -n "$committer" ]; then - echo "@$committer" - else - local git_author=$(git show -s --format='%an' $commit_sha) - case "$git_author" in - "Gray Zhang" | "gray" | "Gray") - echo "@graycreate" - ;; - "github-actions[bot]") - echo "@github-actions[bot]" - ;; - *) - echo "" - ;; - esac - fi - fi - } - # Collect and categorize commits declare -A features declare -A bugs