This guide will help you set up automated Android app deployment to Google Play Store via GitHub Actions.
- Google Play Console developer account ($25 one-time fee)
- Access to Google Cloud Console
- GitHub repository admin access
The keystore is used to sign your app releases. Keep it secure!
cd ~/
keytool -genkey -v \
-keystore photos-release-key.keystore \
-alias photos \
-keyalg RSA \
-keysize 2048 \
-validity 10000
# You'll be prompted for:
# - Keystore password (remember this!)
# - Key password (can be same as keystore password)
# - Your name, organization, etc.Important:
- Back up this keystore file securely (e.g., password manager, encrypted storage)
- If you lose it, you cannot update your app on Play Store!
- Never commit it to git
Convert keystore to base64 for GitHub secrets:
cat ~/photos-release-key.keystore | base64 | pbcopy # macOS
# or
cat ~/photos-release-key.keystore | base64 -w 0 # Linux- Go to Google Cloud Console
- Create new project: "Photos App Deployment"
- Enable Google Play Android Developer API:
- Search for "Google Play Android Developer API"
- Click "Enable"
- Go to IAM & Admin > Service Accounts
- Click Create Service Account
- Name:
github-actions-play-deploy - Description: "Service account for GitHub Actions to deploy to Play Store"
- Name:
- Click Create and Continue
- Skip granting additional roles (we'll do this in Play Console)
- Click Done
- Click on the service account you just created
- Go to Keys tab
- Click Add Key > Create new key
- Select JSON format
- Download the JSON file (save it securely!)
- Go to Google Play Console
- Navigate to Settings (gear icon) > API access
- Click Link next to your service account
- Grant permissions:
- Check Admin (all permissions) or at minimum:
- ✅ View app information and download bulk reports
- ✅ Create and edit draft apps
- ✅ Release to production, exclude devices, and use app signing
- ✅ Manage testing tracks
- Click Apply
Update apps/android/app/build.gradle:
Change the versionName from "1.0" to "1.0.0" and add signing configuration:
android {
namespace = "nl.thijsvtol.photos"
compileSdk = rootProject.ext.compileSdkVersion
defaultConfig {
applicationId "nl.thijsvtol.photos"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0.0" // ← Changed from "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
}
}
// ← Add this signingConfigs block
signingConfigs {
release {
if (System.getenv("RELEASE_KEYSTORE_FILE")) {
storeFile file(System.getenv("RELEASE_KEYSTORE_FILE"))
storePassword System.getenv("RELEASE_KEYSTORE_PASSWORD")
keyAlias System.getenv("RELEASE_KEY_ALIAS")
keyPassword System.getenv("RELEASE_KEY_PASSWORD")
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release // ← Add this line
}
}
}Go to your GitHub repository: Settings > Secrets and variables > Actions > New repository secret
Add these secrets:
The base64-encoded keystore from Step 1
The password you used when creating the keystore
The alias you used (e.g., photos)
The key password (often same as keystore password)
The entire contents of the service account JSON file from Step 2.2 (Open the file and copy-paste all the JSON)
Before GitHub Actions can deploy, you need to manually upload the first version:
# Build web app
cd apps/web
npm run build
npx cap sync android
# Navigate to Android project
cd ../android
# Open in Android Studio
npx cap open androidIn Android Studio:
- Build > Generate Signed Bundle / APK
- Select Android App Bundle
- Use your keystore from Step 1
- Build for release
- Upload the AAB to Play Console manually:
- Go to Play Console
- Create new app if needed
- Go to Production > Create new release
- Upload the AAB file
- Fill in release details
- Save as draft (don't publish yet)
- Go to your GitHub repository
- Click Actions tab
- Select Android - Build and Deploy to Play Store
- Click Run workflow
- Select:
- Track: internal (safest for testing)
- Bump version: true
- Click Run workflow
- Monitor the build
If successful, check Play Console for the new internal release!
- Go to GitHub Actions tab
- Run workflow with track: internal
- Test thoroughly
- Test in internal track
- Run workflow with track: beta
- Get feedback from beta testers
- Ensure beta testing is complete
- Run workflow with track: production
- App will be reviewed by Google (1-7 days)
When running the workflow, set "Bump version code" to true to automatically increment the build number.
cd apps/android/app
# Bump patch version (1.0.0 → 1.0.1)
../../../scripts/bump-version.sh patch
# Bump minor version (1.0.0 → 1.1.0)
../../../scripts/bump-version.sh minor
# Bump major version (1.0.0 → 2.0.0)
../../../scripts/bump-version.sh major
# Just bump version code
../../../scripts/bump-version.sh- Ensure you've manually uploaded the first version
- Check that package name matches:
nl.thijsvtol.photos
- Verify all keystore secrets are set correctly in GitHub
- Ensure ANDROID_KEYSTORE_BASE64 is valid base64
- Check Play Console API access settings
- Ensure service account has "Release to production" permission
- Check workflow logs in GitHub Actions
- Verify Node.js and Java versions
- Do not hardcode
org.gradle.java.hometo a local absolute path; use CIsetup-java/JAVA_HOME - Try building locally first
- Never commit keystore files to git
- Always back up your keystore securely
- Rotate service account keys periodically
- Use internal/alpha tracks for testing before production
- Monitor Play Console for automated security alerts
The following files have been created for Android deployment:
.github/workflows/android-deploy.yml- GitHub Actions workflowscripts/bump-version.sh- Version management script (executable)android-deployment.md- This setup guide
- ✅ Update build.gradle - Add signing configuration (see Step 3)
- Generate keystore - Follow Step 1
- Set up Google Play Console API - Follow Step 2
- Configure GitHub secrets - Follow Step 4
- Do first manual upload - Follow Step 5.1
- Test GitHub Action - Follow Step 5.2