Merge pull request #90 from v2er-app/bugfix/google-play-upload-fix #11
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |