android-cicd
v1.0.4
Published
AI skill: automated Android CI/CD pipeline to Google Play — supports TWA, React Native, Flutter, and native Android
Maintainers
Readme
android-cicd
AI skill: automated Android CI/CD pipeline to Google Play
Sets up a complete, multi-stage GitHub Actions pipeline to build a signed AAB and publish it to Google Play. Supports TWA (Bubblewrap), React Native, Flutter, and native Android.
Features
- Auto-detects your Android framework from the project structure
- Generates and manages your upload keystore (cross-platform: Windows + macOS/Linux)
- Configures all 5 required GitHub Secrets automatically via
ghCLI - Scaffolds a production-ready
.github/workflows/publish-android.yml - Auto-increments
versionCodeon every push tomain(commit with[skip ci]) - Multi-stage pipeline: different tracks per branch/tag
Multi-Stage Pipeline
| Git event | Google Play track |
|---|---|
| Push to main | internal |
| Tag v*-alpha (e.g. v1.2-alpha) | alpha |
| Tag v*-beta (e.g. v1.2-beta) | beta |
| Tag v* (e.g. v1.2.0) | production |
| Manual workflow_dispatch | Selectable |
Quick Start
npx android-cicdThe interactive wizard will:
- Auto-detect your Android framework (TWA / React Native / Flutter / native)
- Generate an upload keystore — or use an existing one
- Set all required GitHub Secrets via
ghCLI - Scaffold
.github/workflows/publish-android.yml
Prerequisites
- Node.js ≥ 18
- JDK 17 with
keytoolaccessible (JAVA_HOMEset, or installed via Eclipse Adoptium / Android Studio) - gh CLI installed and authenticated (
gh auth login) - App already created in Google Play Console — at least one manual AAB upload done
- App enrolled in Play App Signing
- Google Play Android Developer API enabled in Google Cloud Console
- Service account JSON key downloaded (see Google Play Setup)
Supported Frameworks
| Framework | Detected by | Version file |
|---|---|---|
| TWA (Bubblewrap) | android-root-app/build.gradle or twa-manifest.json | android-root-app/build.gradle |
| React Native | android/app/build.gradle + react-native in package.json | android/app/build.gradle |
| Flutter | pubspec.yaml with flutter: | pubspec.yaml (+N build number) |
| Native Android | app/build.gradle | app/build.gradle |
GitHub Secrets
The wizard sets these automatically. You can also set them manually in GitHub → Settings → Secrets and variables → Actions:
| Secret | Description |
|---|---|
| KEYSTORE_FILE | Base64-encoded upload keystore (.jks) |
| KEYSTORE_PASSWORD | Keystore password |
| KEY_ALIAS | Key alias (e.g. upload) |
| KEY_PASSWORD | Key password |
| GOOGLE_PLAY_SERVICE_ACCOUNT_JSON | Full JSON content of the service account key |
Google Play Setup
These steps cannot be automated — do them once before running the wizard:
1. Create a service account
- Google Cloud Console → your project → IAM & Admin → Service Accounts
- Create service account → name:
github-play-publisher→ Done (no project roles needed) - Click the service account → Keys tab → Add key → Create new key → JSON → download the file
2. Enable the Play API
APIs & Services → search Google Play Android Developer API → Enable
3. Grant permissions in Play Console
Play Console → Users and permissions → Invite new user
- Email:
[email protected] - Permissions (account level):
- ✅ Release apps to testing tracks
- ✅ Manage testing tracks and edit testers
Signing Configuration
TWA / React Native / Native Android
Add to your build.gradle (template at templates/gradle/signing.gradle):
android {
signingConfigs {
release {
storeFile file("keystore.jks")
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
}
}
buildTypes {
release {
minifyEnabled true
signingConfig signingConfigs.release
}
}
}Never set
org.gradle.java.homeingradle.properties— it breaks Linux CI runners.
Flutter
Add to android/app/build.gradle (the CI workflow creates android/key.properties at build time):
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}Add android/key.properties to .gitignore.
Releasing to Production
# 1. Bump version manually (CI won't auto-bump on tags)
# TWA/Native/RN — edit build.gradle: versionCode 8 versionName "1.2.0"
# Flutter — edit pubspec.yaml: version: 1.2.0+8
git add .
git commit -m "chore: bump version to 1.2.0"
# 2. Tag and push
git tag v1.2.0
git push origin main --tagsTroubleshooting
| Error | Cause | Fix |
|---|---|---|
| Java home supplied is invalid | org.gradle.java.home in gradle.properties | Remove that line |
| signed with the wrong key | Keystore in secret doesn't match Play's upload key | Update KEYSTORE_FILE secret |
| The caller does not have permission | Service account missing permissions or API not enabled | Re-check Google Play Setup steps 2–3 |
| Upload failed — wrong versionCode | versionCode not incremented before tagging | Increment manually before pushing the tag |
| shallow update not allowed | Shallow checkout blocks the push-back | Workflow uses fetch-depth: 0 — verify the checkout step |
| gh: command not found | gh CLI not installed | Install from https://cli.github.com |
| keytool not found | JDK not installed or not on PATH | Set JAVA_HOME or install JDK 17 |
Recovering a Lost Upload Keystore
If enrolled in Play App Signing:
- Generate a new keystore: run
npx android-cicd→ choose "I already have a keystore: No" - Export the PEM:
keytool -export -rfc -keystore upload.jks -alias ALIAS -storepass PASS -file cert.pem - Play Console → app → App integrity → Request upload key reset → "I forgot my password" → upload
cert.pem - Wait 1–2 business days
- Update the
KEYSTORE_FILEsecret by re-runningnpx android-cicd
Usage with AI Agents
This package ships a SKILL.md that AI coding agents (Claude, Cursor, Copilot, etc.) can read to gain full context for setting up and maintaining this pipeline. Point your agent at SKILL.md and ask it to run npx android-cicd in the target project.
License
MIT
