Skip to content

Commit a8b6695

Browse files
committed
ci(deploy): add Google Play API deployment workflow
Bypasses the recurring Play Console UI loop bug that prevents submitting production releases for review by uploading the AAB directly via the Google Play Developer Publishing API (r0adkll/upload-google-play action). Triggered manually via workflow_dispatch with configurable track, rollout percentage and release status. Reuses existing signing secrets (KEYSTORE_BASE64, KEYSTORE_PASSWORD, KEY_PASSWORD, KEY_ALIAS) and adds GOOGLE_PLAY_SERVICE_ACCOUNT_JSON for API authentication.
1 parent 26ee48e commit a8b6695

1 file changed

Lines changed: 127 additions & 0 deletions

File tree

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
name: Deploy to Google Play
2+
3+
# Bypasses broken Google Play Console UI by using the Developer API directly.
4+
# Requires a Google Play service account JSON added as repository secret
5+
# GOOGLE_PLAY_SERVICE_ACCOUNT_JSON (see setup instructions below).
6+
#
7+
# Setup:
8+
# 1. Play Console → Setup → API access → Link Google Cloud project
9+
# 2. Create service account → Grant "Release Manager" role in Play Console
10+
# 3. Download JSON key → add as GitHub secret GOOGLE_PLAY_SERVICE_ACCOUNT_JSON
11+
12+
on:
13+
workflow_dispatch:
14+
inputs:
15+
track:
16+
description: 'Release track'
17+
required: true
18+
default: 'internal'
19+
type: choice
20+
options:
21+
- internal
22+
- alpha
23+
- beta
24+
- production
25+
rollout_percentage:
26+
description: 'Rollout % for production track (1-100, ignored for other tracks)'
27+
required: false
28+
default: '10'
29+
status:
30+
description: 'Release status'
31+
required: true
32+
default: 'completed'
33+
type: choice
34+
options:
35+
- completed
36+
- draft
37+
38+
permissions:
39+
contents: read
40+
41+
jobs:
42+
deploy:
43+
name: Build AAB & Deploy (${{ inputs.track }})
44+
runs-on: ubuntu-latest
45+
46+
steps:
47+
- name: Checkout code
48+
uses: actions/checkout@v4
49+
50+
- name: Setup Java
51+
uses: actions/setup-java@v4
52+
with:
53+
distribution: 'temurin'
54+
java-version: '17'
55+
56+
- name: Setup Gradle
57+
uses: gradle/actions/setup-gradle@v4
58+
59+
- name: Extract version info
60+
id: version
61+
run: |
62+
VERSION_NAME=$(grep 'versionName = ' android/app/build.gradle.kts | sed 's/.*versionName = "\(.*\)".*/\1/')
63+
VERSION_CODE=$(grep 'versionCode = ' android/app/build.gradle.kts | sed 's/.*versionCode = \([0-9]*\).*/\1/')
64+
echo "VERSION_NAME=$VERSION_NAME" >> $GITHUB_OUTPUT
65+
echo "VERSION_CODE=$VERSION_CODE" >> $GITHUB_OUTPUT
66+
echo "Building v$VERSION_NAME (Code: $VERSION_CODE) → track: ${{ inputs.track }}"
67+
68+
- name: Calculate rollout fraction (production only)
69+
id: rollout
70+
run: |
71+
if [ "${{ inputs.track }}" = "production" ]; then
72+
FRACTION=$(echo "scale=4; ${{ inputs.rollout_percentage }} / 100" | bc)
73+
echo "USER_FRACTION=$FRACTION" >> $GITHUB_OUTPUT
74+
echo "Production rollout: ${{ inputs.rollout_percentage }}% → fraction $FRACTION"
75+
else
76+
echo "USER_FRACTION=" >> $GITHUB_OUTPUT
77+
echo "Non-production track: no rollout fraction"
78+
fi
79+
80+
- name: Configure Android signing
81+
run: |
82+
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > android/app/simple-notes-release.jks
83+
echo "storePassword=${{ secrets.KEYSTORE_PASSWORD }}" > android/key.properties
84+
echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> android/key.properties
85+
echo "keyAlias=${{ secrets.KEY_ALIAS }}" >> android/key.properties
86+
echo "storeFile=simple-notes-release.jks" >> android/key.properties
87+
88+
- name: Build release AAB (standard flavor)
89+
run: |
90+
cd android
91+
./gradlew bundleStandardRelease --no-daemon --stacktrace
92+
93+
- name: Locate AAB
94+
id: aab
95+
run: |
96+
AAB_PATH=$(find android/app/build/outputs/bundle/standardRelease -name "*.aab" | head -1)
97+
echo "AAB_PATH=$AAB_PATH" >> $GITHUB_OUTPUT
98+
echo "Found AAB: $AAB_PATH ($(du -sh "$AAB_PATH" | cut -f1))"
99+
100+
- name: Upload to Google Play
101+
uses: r0adkll/upload-google-play@v1
102+
with:
103+
serviceAccountJsonPlainText: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
104+
packageName: dev.dettmer.simplenotes
105+
releaseFiles: ${{ steps.aab.outputs.AAB_PATH }}
106+
track: ${{ inputs.track }}
107+
status: ${{ inputs.status }}
108+
inAppUpdatePriority: 0
109+
userFraction: ${{ steps.rollout.outputs.USER_FRACTION }}
110+
whatsNewDirectory: fastlane/metadata/android
111+
mappingFile: android/app/build/outputs/mapping/standardRelease/mapping.txt
112+
113+
- name: Summary
114+
run: |
115+
{
116+
echo "### Deployment successful"
117+
echo ""
118+
echo "| | |"
119+
echo "|---|---|"
120+
echo "| Package | \`dev.dettmer.simplenotes\` |"
121+
echo "| Version | ${{ steps.version.outputs.VERSION_NAME }} (Code ${{ steps.version.outputs.VERSION_CODE }}) |"
122+
echo "| Track | ${{ inputs.track }} |"
123+
echo "| Status | ${{ inputs.status }} |"
124+
if [ "${{ inputs.track }}" = "production" ]; then
125+
echo "| Rollout | ${{ inputs.rollout_percentage }}% |"
126+
fi
127+
} >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)