Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions .github/workflows/fastlane-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: Fastlane Deploy

on:
workflow_dispatch:
inputs:
track:
description: 'Deployment track'
required: true
type: choice
default: 'internal'
options:
- internal
- alpha
- beta
- production
release_status:
description: 'Release status'
required: false
type: choice
default: 'draft'
options:
- draft
- completed

jobs:
deploy:
name: Deploy with Fastlane
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: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Decode Keystore
env:
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
run: |
echo "$KEYSTORE_BASE64" | base64 --decode > ${{ github.workspace }}/keystore.jks
echo "KEYSTORE_PATH=${{ github.workspace }}/keystore.jks" >> $GITHUB_ENV

- name: Setup Play Store credentials
env:
PLAY_STORE_SERVICE_ACCOUNT_JSON: ${{ secrets.PLAY_STORE_SERVICE_ACCOUNT_JSON }}
run: |
echo "$PLAY_STORE_SERVICE_ACCOUNT_JSON" > ${{ github.workspace }}/fastlane/play-store-key.json
echo "PLAY_STORE_JSON_KEY_PATH=${{ github.workspace }}/fastlane/play-store-key.json" >> $GITHUB_ENV

- name: Install Fastlane
run: |
bundle install
bundle exec fastlane --version

- name: Deploy to Play Store
env:
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
SUPPLY_RELEASE_STATUS: ${{ github.event.inputs.release_status }}
run: |
case "${{ github.event.inputs.track }}" in
internal)
bundle exec fastlane android deploy_internal
;;
alpha)
bundle exec fastlane android deploy_alpha
;;
beta)
bundle exec fastlane android deploy_beta
;;
production)
bundle exec fastlane android deploy_production
;;
esac

- name: Clean up sensitive files
if: always()
run: |
rm -f ${{ github.workspace }}/keystore.jks
rm -f ${{ github.workspace }}/fastlane/play-store-key.json

- name: Deployment Summary
if: success()
run: |
echo "## Fastlane Deployment Complete :rocket:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Track**: ${{ github.event.inputs.track }}" >> $GITHUB_STEP_SUMMARY
echo "- **Status**: ${{ github.event.inputs.release_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)" >> $GITHUB_STEP_SUMMARY
140 changes: 118 additions & 22 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@ on:
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
Expand Down Expand Up @@ -67,19 +85,18 @@ jobs:
echo "Key alias configured: ${{ secrets.KEY_ALIAS != '' && 'Yes' || 'No' }}"

- name: Build release APK
env:
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEYSTORE_PATH: ${{ vars.ENABLE_SIGNING == 'true' && 'keystore.jks' || '' }}
run: |
if [ "${{ vars.ENABLE_SIGNING }}" = "true" ] && [ -f "app/keystore.jks" ]; then
echo "Building signed release APK"
echo "Using key alias: ${KEY_ALIAS:-ghui}"
./gradlew assembleRelease --stacktrace
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 || ./gradlew assembleDebug --stacktrace
./gradlew assembleRelease --stacktrace
fi

- name: Clean up keystore
Expand Down Expand Up @@ -136,19 +153,26 @@ jobs:
echo "$KEYSTORE_BASE64" | base64 --decode > app/keystore.jks

- name: Build release bundle
env:
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEYSTORE_PATH: ${{ vars.ENABLE_SIGNING == 'true' && 'keystore.jks' || '' }}
run: |
if [ "${{ vars.ENABLE_SIGNING }}" = "true" ] && [ -f "app/keystore.jks" ]; then
echo "Building signed release bundle"
./gradlew bundleRelease --stacktrace
./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: |
Expand Down Expand Up @@ -242,24 +266,96 @@ jobs:
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 AAB file
id: find-aab
- 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

- name: Upload to Play Store
# 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
Comment on lines +316 to +322
Copy link

Copilot AI Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using git commit messages directly in Play Store release notes is problematic because they may contain technical details inappropriate for end users and could exceed Play Store's 500-character limit. Consider using predefined release notes or filtering commit messages for user-facing content.

Copilot uses AI. Check for mistakes.

- 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/
changesNotSentForReview: true
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.SERVICE_ACCOUNT_JSON }}
serviceAccountJsonPlainText: ${{ secrets.PLAY_STORE_SERVICE_ACCOUNT_JSON }}
Comment on lines +339 to +343
Copy link

Copilot AI Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using serviceAccountJsonPlainText exposes the service account JSON in workflow logs. Consider using serviceAccountJson with a file path or ensure the workflow logs are properly secured and access is restricted.

Copilot uses AI. Check for mistakes.
packageName: me.ghui.v2er
releaseFiles: ${{ steps.find-aab.outputs.aab_path }}
track: internal
status: completed
whatsNewDirectory: whatsnew/
releaseFiles: ${{ steps.find-files.outputs.aab_path }}
track: ${{ steps.release-config.outputs.track }}
status: ${{ steps.release-config.outputs.status }}
whatsNewDirectory: whatsnew/
changesNotSentForReview: true

- 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
16 changes: 15 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,18 @@
*.keystore
*.base64.txt
keystore.jks
app/keystore.jks
app/keystore.jks

# Fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
fastlane/play-store-key.json
fastlane/*.json

# Bundle
vendor/bundle/
.bundle/
Gemfile.lock
26 changes: 26 additions & 0 deletions .gitignore.fastlane
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Fastlane specific
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
fastlane/play-store-key.json
fastlane/*.json

# Bundle
vendor/bundle/
.bundle/

# Ruby
*.gem
*.rbc
/.config
/coverage/
/InstalledFiles
/pkg/
/spec/reports/
/spec/examples.txt
/test/tmp/
/test/version_tmp/
/tmp/
Gemfile.lock
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source "https://rubygems.org"

gem "fastlane"
gem "fastlane-plugin-firebase_app_distribution", "~> 0.7.0" # Optional: for Firebase distribution
Loading
Loading