Skip to content

Merge pull request #90 from v2er-app/bugfix/google-play-upload-fix #10

Merge pull request #90 from v2er-app/bugfix/google-play-upload-fix

Merge pull request #90 from v2er-app/bugfix/google-play-upload-fix #10

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., v1.0.0)'
required: true
type: string
track:
description: 'Play Store release track'
required: false
type: choice
default: 'internal'
options:
- internal
- alpha
- beta
- production
status:
description: 'Play Store release status'
required: false
type: choice
default: 'draft'
options:
- draft
- completed
permissions:
contents: write
jobs:
prepare:
name: Prepare Release
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Determine version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.version }}"
else
VERSION="${{ github.ref_name }}"
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Version: $VERSION"
build-apk:
name: Build Release APK
needs: prepare
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Decode Keystore
if: ${{ vars.ENABLE_SIGNING == 'true' && env.KEYSTORE_BASE64 != '' }}
env:
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
run: |
echo "$KEYSTORE_BASE64" | base64 --decode > app/keystore.jks
- name: Debug keystore info
if: ${{ vars.ENABLE_SIGNING == 'true' }}
run: |
echo "Keystore file exists: $([ -f app/keystore.jks ] && echo 'Yes' || echo 'No')"
echo "Keystore size: $([ -f app/keystore.jks ] && ls -la app/keystore.jks | awk '{print $5}' || echo 'N/A')"
echo "Key alias configured: ${{ secrets.KEY_ALIAS != '' && 'Yes' || 'No' }}"
- name: Build release APK
run: |
if [ "${{ vars.ENABLE_SIGNING }}" = "true" ] && [ -f "app/keystore.jks" ]; then
echo "Building signed release APK"
echo "Using key alias: ${{ secrets.KEY_ALIAS }}"
./gradlew assembleRelease \
-Pandroid.injected.signing.store.file=${{ github.workspace }}/app/keystore.jks \
-Pandroid.injected.signing.store.password=${{ secrets.KEYSTORE_PASSWORD }} \
-Pandroid.injected.signing.key.alias=${{ secrets.KEY_ALIAS }} \
-Pandroid.injected.signing.key.password=${{ secrets.KEY_PASSWORD }}
else
echo "Building unsigned release APK"
./gradlew assembleRelease --stacktrace
fi
- name: Clean up keystore
if: always()
run: |
rm -f app/keystore.jks
- name: Upload release APK
uses: actions/upload-artifact@v4
with:
name: release-apk
path: app/build/outputs/apk/**/*.apk
retention-days: 30
- name: APK Summary
run: |
echo "## APK Build Results :package:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
APK_PATH=$(find app/build/outputs/apk -name "*.apk" | grep -E "release" | head -1)
if [ -f "$APK_PATH" ]; then
APK_SIZE=$(du -h "$APK_PATH" | cut -f1)
echo "- APK Size: $APK_SIZE" >> $GITHUB_STEP_SUMMARY
echo "- APK Name: \`$(basename "$APK_PATH")\`" >> $GITHUB_STEP_SUMMARY
echo "- Signed: ${{ vars.ENABLE_SIGNING == 'true' && 'Yes' || 'No' }}" >> $GITHUB_STEP_SUMMARY
else
echo "No APK found" >> $GITHUB_STEP_SUMMARY
fi
build-aab:
name: Build Release Bundle
needs: prepare
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Decode Keystore
if: ${{ vars.ENABLE_SIGNING == 'true' && env.KEYSTORE_BASE64 != '' }}
env:
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
run: |
echo "$KEYSTORE_BASE64" | base64 --decode > app/keystore.jks
- name: Build release bundle
run: |
if [ "${{ vars.ENABLE_SIGNING }}" = "true" ] && [ -f "app/keystore.jks" ]; then
echo "Building signed release bundle"
./gradlew bundleRelease \
-Pandroid.injected.signing.store.file=${{ github.workspace }}/app/keystore.jks \
-Pandroid.injected.signing.store.password=${{ secrets.KEYSTORE_PASSWORD }} \
-Pandroid.injected.signing.key.alias=${{ secrets.KEY_ALIAS }} \
-Pandroid.injected.signing.key.password=${{ secrets.KEY_PASSWORD }}
else
echo "Skipping bundle build - signing not configured"
fi
- name: Generate debug symbols
if: ${{ vars.ENABLE_SIGNING == 'true' }}
run: |
echo "Checking for debug symbols..."
find app/build/outputs -name "*.zip" -type f | grep -i debug || echo "No debug symbol zips found"
find app/build/outputs -name "*symbols*" -type f || echo "No symbol files found"
ls -la app/build/outputs/bundle/release/ || true
- name: Clean up keystore
if: always()
run: |
rm -f app/keystore.jks
- name: Upload release bundle
if: ${{ vars.ENABLE_SIGNING == 'true' }}
uses: actions/upload-artifact@v4
with:
name: release-bundle
path: app/build/outputs/bundle/**/*.aab
retention-days: 30
release:
name: Create GitHub Release
needs: [prepare, build-apk, build-aab]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download APK artifact
uses: actions/download-artifact@v4
with:
name: release-apk
path: release-artifacts/
- name: Download AAB artifact
if: ${{ vars.ENABLE_SIGNING == 'true' }}
uses: actions/download-artifact@v4
with:
name: release-bundle
path: release-artifacts/
continue-on-error: true
- name: Prepare release assets
id: assets
run: |
# Find APK
APK_PATH=$(find release-artifacts -name "*.apk" | grep -E "release" | head -1)
if [ -f "$APK_PATH" ]; then
APK_NAME="v2er-${{ needs.prepare.outputs.version }}.apk"
mv "$APK_PATH" "$APK_NAME"
echo "apk_path=$APK_NAME" >> $GITHUB_OUTPUT
fi
# Find AAB
AAB_PATH=$(find release-artifacts -name "*.aab" 2>/dev/null | head -1)
if [ -f "$AAB_PATH" ]; then
AAB_NAME="v2er-${{ needs.prepare.outputs.version }}.aab"
mv "$AAB_PATH" "$AAB_NAME"
echo "aab_path=$AAB_NAME" >> $GITHUB_OUTPUT
fi
- name: Generate changelog
id: changelog
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 "")
if [ -n "$LAST_TAG" ]; then
git log --pretty=format:"* %s by @%an" "$LAST_TAG"..HEAD >> CHANGELOG.md
else
git log --pretty=format:"* %s by @%an" -10 >> CHANGELOG.md
fi
echo "" >> CHANGELOG.md
echo "" >> CHANGELOG.md
echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${LAST_TAG}...${{ needs.prepare.outputs.version }}" >> CHANGELOG.md
- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.prepare.outputs.version }}
name: Release ${{ needs.prepare.outputs.version }}
body_path: CHANGELOG.md
draft: false
prerelease: false
files: |
${{ steps.assets.outputs.apk_path }}
${{ steps.assets.outputs.aab_path }}
fail_on_unmatched_files: false
play-store-upload:
name: Upload to Play Store
needs: [prepare, build-aab]
if: ${{ vars.ENABLE_PLAY_STORE_UPLOAD == 'true' && vars.ENABLE_SIGNING == 'true' }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download AAB artifact
uses: actions/download-artifact@v4
with:
name: release-bundle
path: release-artifacts/
- name: Find bundle and symbols
id: find-files
run: |
AAB_PATH=$(find release-artifacts -name "*.aab" | head -1)
echo "aab_path=$AAB_PATH" >> $GITHUB_OUTPUT
# Look for debug symbols
SYMBOLS_PATH=$(find release-artifacts -name "native-debug-symbols.zip" 2>/dev/null | head -1)
if [ -n "$SYMBOLS_PATH" ]; then
echo "symbols_path=$SYMBOLS_PATH" >> $GITHUB_OUTPUT
echo "Found debug symbols at: $SYMBOLS_PATH"
else
echo "No debug symbols found"
fi
- name: Determine release track and status
id: release-config
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TRACK="${{ github.event.inputs.track }}"
STATUS="${{ github.event.inputs.status }}"
else
# Default for tag pushes
TRACK="internal"
STATUS="draft"
fi
echo "track=$TRACK" >> $GITHUB_OUTPUT
echo "status=$STATUS" >> $GITHUB_OUTPUT
echo "Deploying to track: $TRACK with status: $STATUS"
- name: Create whatsnew directory
run: |
mkdir -p whatsnew
# Generate release notes
echo "Release ${{ needs.prepare.outputs.version }}" > whatsnew/whatsnew-en-US
echo "" >> whatsnew/whatsnew-en-US
# Get recent commits
git log --pretty=format:"• %s" -5 >> whatsnew/whatsnew-en-US
# Chinese version
echo "版本 ${{ needs.prepare.outputs.version }}" > whatsnew/whatsnew-zh-CN
echo "" >> whatsnew/whatsnew-zh-CN
git log --pretty=format:"• %s" -5 >> whatsnew/whatsnew-zh-CN
- name: Upload to Play Store (with debug symbols)
if: steps.find-files.outputs.symbols_path != ''
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.PLAY_STORE_SERVICE_ACCOUNT_JSON }}
packageName: me.ghui.v2er
releaseFiles: ${{ steps.find-files.outputs.aab_path }}
track: ${{ steps.release-config.outputs.track }}
status: ${{ steps.release-config.outputs.status }}
debugSymbols: ${{ steps.find-files.outputs.symbols_path }}
whatsNewDirectory: whatsnew/
continue-on-error: true
id: upload-with-symbols
- name: Upload to Play Store (without debug symbols)
if: steps.find-files.outputs.symbols_path == '' || steps.upload-with-symbols.outcome == 'failure'
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.PLAY_STORE_SERVICE_ACCOUNT_JSON }}
packageName: me.ghui.v2er
releaseFiles: ${{ steps.find-files.outputs.aab_path }}
track: ${{ steps.release-config.outputs.track }}
status: ${{ steps.release-config.outputs.status }}
whatsNewDirectory: whatsnew/
- name: Play Store Upload Summary
if: success()
run: |
echo "## Play Store Upload Complete :rocket:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Version**: ${{ needs.prepare.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "- **Track**: ${{ steps.release-config.outputs.track }}" >> $GITHUB_STEP_SUMMARY
echo "- **Status**: ${{ steps.release-config.outputs.status }}" >> $GITHUB_STEP_SUMMARY
echo "- **Package**: me.ghui.v2er" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "[View in Play Console](https://play.google.com/console/u/0/app/me.ghui.v2er)" >> $GITHUB_STEP_SUMMARY