-
Notifications
You must be signed in to change notification settings - Fork 45
feat: include past 3 versions in Google Play release notes #181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Add feedback header at the top of release notes - Collect commits from current version and past 2 tagged versions - Combine with version separators (--- vX.Y.Z ---) - Respect Google Play's 500 character limit per language - Automatically truncate if content exceeds limit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR enhances the Google Play release notes generation in the GitHub Actions workflow to include the current version plus up to 2 previous versions, with a feedback header and 500-character limit enforcement per Google Play's requirements.
Key Changes:
- Adds feedback header URLs for both English and Chinese release notes
- Implements multi-version commit collection using git tag ranges
- Enforces Google Play's 500-character limit per language
- Refactors release notes generation from emoji-based sections with contributors to compact bullet-point format
| CURRENT_LEN=$(wc -c < whatsnew/whatsnew-en-US) | ||
| for notes in "${version_notes_en[@]}"; do | ||
| NOTES_LEN=${#notes} | ||
| if [ $((CURRENT_LEN + NOTES_LEN + 2)) -lt $MAX_CHARS ]; then | ||
| echo "$notes" >> whatsnew/whatsnew-en-US | ||
| CURRENT_LEN=$((CURRENT_LEN + NOTES_LEN + 2)) |
Copilot
AI
Dec 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The character counting logic is incorrect. wc -c counts bytes, not characters. For multi-byte UTF-8 characters (like Chinese characters in the feedback header "唯一问题反馈渠道"), this will count multiple bytes per character. However, ${#notes} counts characters correctly. This mismatch means the character limit enforcement may be inaccurate - the initial length calculation uses byte count while the subsequent additions use character count.
| CURRENT_LEN=$(wc -c < whatsnew/whatsnew-zh-CN) | ||
| for notes in "${version_notes_zh[@]}"; do | ||
| NOTES_LEN=${#notes} | ||
| if [ $((CURRENT_LEN + NOTES_LEN + 2)) -lt $MAX_CHARS ]; then | ||
| echo "$notes" >> whatsnew/whatsnew-zh-CN | ||
| CURRENT_LEN=$((CURRENT_LEN + NOTES_LEN + 2)) |
Copilot
AI
Dec 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The character counting logic is incorrect. wc -c counts bytes, not characters. For multi-byte UTF-8 characters (like Chinese characters in the feedback header "唯一问题反馈渠道"), this will count multiple bytes per character. However, ${#notes} counts characters correctly. This mismatch means the character limit enforcement may be inaccurate - the initial length calculation uses byte count while the subsequent additions use character count.
| declare -A prev_features prev_bugs prev_improvements prev_performance | ||
| collect_version_commits "${TAGS[$((i+1))]}..${TAGS[$i]}" prev_features prev_bugs prev_improvements prev_performance |
Copilot
AI
Dec 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The associative arrays are redeclared inside the loop without being cleared between iterations. In bash, when you declare -A an existing associative array, it doesn't clear its contents. This means commits from previous iterations will accumulate in the arrays, leading to duplicate entries in the release notes for version i=1.
| declare -A prev_features prev_bugs prev_improvements prev_performance | ||
| collect_version_commits "${TAGS[$i]}~5..${TAGS[$i]}" prev_features prev_bugs prev_improvements prev_performance |
Copilot
AI
Dec 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The associative arrays are redeclared inside the loop without being cleared between iterations. In bash, when you declare -A an existing associative array, it doesn't clear its contents. This means commits from previous iterations will accumulate in the arrays, leading to duplicate entries in the release notes for version i=1.
| if [ $((CURRENT_LEN + NOTES_LEN + 2)) -lt $MAX_CHARS ]; then | ||
| echo "$notes" >> whatsnew/whatsnew-en-US | ||
| CURRENT_LEN=$((CURRENT_LEN + NOTES_LEN + 2)) |
Copilot
AI
Dec 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The character limit check adds 2 to account for newlines, but this is inconsistent. When writing to the file with echo "$notes", bash adds a single newline character (1 byte), not 2. This will cause the actual file size to be smaller than the calculated CURRENT_LEN, leading to inaccurate character limit enforcement.
| if [ $((CURRENT_LEN + NOTES_LEN + 2)) -lt $MAX_CHARS ]; then | ||
| echo "$notes" >> whatsnew/whatsnew-zh-CN | ||
| CURRENT_LEN=$((CURRENT_LEN + NOTES_LEN + 2)) |
Copilot
AI
Dec 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The character limit check adds 2 to account for newlines, but this is inconsistent. When writing to the file with echo "$notes", bash adds a single newline character (1 byte), not 2. This will cause the actual file size to be smaller than the calculated CURRENT_LEN, leading to inaccurate character limit enforcement.
| local -n bugs=$2 | ||
| local -n improve=$3 | ||
| local -n perf=$4 | ||
| local output="" | ||
| # Skip version bump and merge commits | ||
| if [[ "$msg" =~ "bump version" ]] || [[ "$msg" =~ "Merge pull request" ]] || [[ "$msg" =~ "Merge branch" ]]; then | ||
| continue | ||
| if [ ${#feat[@]} -gt 0 ]; then | ||
| for msg in "${!feat[@]}"; do | ||
| output+="• $msg"$'\n' | ||
| done | ||
| fi | ||
| categorized=$(categorize_commit "$msg") | ||
| 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" | ||
| if [ ${#bugs[@]} -gt 0 ]; then | ||
| for msg in "${!bugs[@]}"; do | ||
| output+="• $msg"$'\n' | ||
| done | ||
| fi |
Copilot
AI
Dec 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable naming is inconsistent. In generate_version_notes, the parameter references use bugs (line 692) but in the function body it's referenced as ${#bugs[@]} (line 702). The array is passed as bug_ref in collect_version_commits (line 662) and assigned from curr_bugs, prev_bugs, etc. The naming should be consistent - either use bugs everywhere or bug everywhere to match the pattern of feat/improve/perf.
| output+="• $msg"$'\n' | ||
| done | ||
| fi | ||
| echo "$output" |
Copilot
AI
Dec 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The output variable in generate_version_notes accumulates strings with newlines embedded using $'\n'. However, when echoed at the end, this will produce the correct multi-line output. But there's a subtle issue: if all arrays are empty, the function will echo an empty string which is fine, but the logic doesn't explicitly handle this case, making the function's behavior less clear.
| echo "$output" | |
| if [ -z "$output" ]; then | |
| # Explicitly handle the case where there are no version notes | |
| echo "" | |
| else | |
| echo "$output" | |
| fi |
| # Last tag - get commits before it | ||
| declare -A prev_features prev_bugs prev_improvements prev_performance | ||
| collect_version_commits "${TAGS[$i]}~5..${TAGS[$i]}" prev_features prev_bugs prev_improvements prev_performance |
Copilot
AI
Dec 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The loop logic for handling the last tag (when i+1 >= number of tags) uses ${TAGS[$i]}~5..${TAGS[$i]} which gets commits leading up to the tag, not commits between tags. This will show the wrong commits for the oldest version in the release notes. The range should be from the previous tag (or an appropriate earlier reference) to ${TAGS[$i]}.
| # Last tag - get commits before it | |
| declare -A prev_features prev_bugs prev_improvements prev_performance | |
| collect_version_commits "${TAGS[$i]}~5..${TAGS[$i]}" prev_features prev_bugs prev_improvements prev_performance | |
| # Last tag - get commits from repository root to this tag | |
| declare -A prev_features prev_bugs prev_improvements prev_performance | |
| collect_version_commits "$(git rev-list --max-parents=0 ${TAGS[$i]})..${TAGS[$i]}" prev_features prev_bugs prev_improvements prev_performance |
| for i in 0 1; do | ||
| if [ $i -lt ${#TAGS[@]} ] && [ $((i+1)) -lt ${#TAGS[@]} ]; then | ||
| declare -A prev_features prev_bugs prev_improvements prev_performance | ||
| collect_version_commits "${TAGS[$((i+1))]}..${TAGS[$i]}" prev_features prev_bugs prev_improvements prev_performance | ||
| PREV_NOTES=$(generate_version_notes prev_features prev_bugs prev_improvements prev_performance) | ||
| if [ -n "$PREV_NOTES" ]; then | ||
| version_notes_en+=("--- ${TAGS[$i]} ---"$'\n'"$PREV_NOTES") | ||
| version_notes_zh+=("--- ${TAGS[$i]} ---"$'\n'"$PREV_NOTES") | ||
| fi | ||
| done | ||
| echo "" >> whatsnew/whatsnew-zh-CN | ||
| fi | ||
| if [ ${#bugs[@]} -gt 0 ]; then | ||
| echo "🐛 问题修复:" >> whatsnew/whatsnew-zh-CN | ||
| for msg in "${!bugs[@]}"; do | ||
| author="${bugs[$msg]}" | ||
| if [ -n "$author" ]; then | ||
| echo "• $msg (贡献者 $author)" >> whatsnew/whatsnew-zh-CN | ||
| else | ||
| echo "• $msg" >> whatsnew/whatsnew-zh-CN | ||
| unset prev_features prev_bugs prev_improvements prev_performance | ||
| elif [ $i -lt ${#TAGS[@]} ] && [ $((i+1)) -ge ${#TAGS[@]} ]; then | ||
| # Last tag - get commits before it | ||
| declare -A prev_features prev_bugs prev_improvements prev_performance | ||
| collect_version_commits "${TAGS[$i]}~5..${TAGS[$i]}" prev_features prev_bugs prev_improvements prev_performance | ||
| PREV_NOTES=$(generate_version_notes prev_features prev_bugs prev_improvements prev_performance) | ||
| if [ -n "$PREV_NOTES" ]; then | ||
| version_notes_en+=("--- ${TAGS[$i]} ---"$'\n'"$PREV_NOTES") | ||
| version_notes_zh+=("--- ${TAGS[$i]} ---"$'\n'"$PREV_NOTES") | ||
| fi | ||
| done | ||
| echo "" >> whatsnew/whatsnew-zh-CN | ||
| fi | ||
| unset prev_features prev_bugs prev_improvements prev_performance | ||
| fi | ||
| done |
Copilot
AI
Dec 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The loop iterates over indices 0 and 1 to collect previous versions, but the condition checks if i < ${#TAGS[@]} which may cause issues. When TAGS has only 1 element (index 0), the loop will try to access TAGS[1] in the first condition branch, which doesn't exist. The loop should handle the case where there are fewer than 3 tags more carefully.
Summary
唯一问题反馈渠道:https://v2er.app/help--- vX.Y.Z ---headersExample Output
Changes
Test plan
🤖 Generated with Claude Code