Android Build Automation Setup: CI/CD, Signing, and Caching Guide
We often see developers complaining about slow builds in CI: a project with 15+ modules, Gradle running single-threaded, cold build 4–7 minutes, incremental 90 seconds. In a team of 10 people, that turns into a queue of builds blocking reviews. Our experience shows that proper build automation is not a silver bullet, but systematic work with Gradle configs, CI pipeline, and caching. We set everything up so that the build runs stably on any machine without manual steps.
Main Pain Points in Android Build Automation
How to sign APK/AAB safely in CI?
The most common problem. Developers store keystore in the repository (bad) or pass via command-line arguments in plain text (worse). The correct scheme: encode keystore in Base64, put it in a CI environment variable, decode to a temporary file before build, and delete after build. In build.gradle.kts, configure via environment variables:
android { signingConfigs { create("release") { storeFile = file(System.getenv("KEYSTORE_PATH") ?: "debug.keystore") storePassword = System.getenv("KEYSTORE_PASSWORD") ?: "android" keyAlias = System.getenv("KEY_ALIAS") ?: "androiddebugkey" keyPassword = System.getenv("KEY_PASSWORD") ?: "android" } } buildTypes { release { signingConfig = signingConfigs.getByName("release") isMinifyEnabled = true proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } } Branch-based build configuration
Second pain point. main → release AAB for Play Store, develop → debug APK with test endpoints, release/* → staging APK for QA. Implement via a combination of buildFlavors + conditions in CI script. No need to create separate build.gradle files—one configuration with flavorDimensions is enough.
Why is Gradle caching important?
Without cache, CI downloads 200–400 MB of dependencies on every run. With proper caching of ~/.gradle/caches and ~/.gradle/wrapper, the first build after a build.gradle change takes full time; subsequent builds are incremental. On average, we save ~60% of build time after the first build. We use remote build cache (via S3) for distributed teams.
How We Set It Up
Base stack: Gradle 8.x + AGP 8.x + GitHub Actions / GitLab CI / Bitrise. We use Fastlane for tasks Gradle cannot handle out of the box: uploading to Google Play via supply, sending notifications, managing tracks (internal → alpha → production).
Structure of a typical CI pipeline (GitHub Actions):
# .github/workflows/android-release.yml jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' - name: Cache Gradle uses: actions/cache@v4 with: path: | ~/.gradle/caches ~/.gradle/wrapper key: gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - name: Decode Keystore run: echo "$KEYSTORE_BASE64" | base64 -d > app/release.keystore env: KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} - name: Build Release AAB run: ./gradlew bundleRelease env: KEYSTORE_PATH: release.keystore KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} KEY_ALIAS: ${{ secrets.KEY_ALIAS }} KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: release-aab path: app/build/outputs/bundle/release/app-release.aab We also configure gradle.properties for CI: org.gradle.daemon=false (daemon is not needed in CI), org.gradle.parallel=true, org.gradle.configureondemand=true. On projects with multiple modules, this reduces configuration time by 30–40%.
Parallel Execution and Optimization
If the project is monolithic, parallelization gives almost no effect. But with a modular architecture (:core, :feature-auth, :feature-feed, :app), Gradle builds a dependency graph and compiles independent modules in parallel. ./gradlew assembleDebug --parallel on an 8-core agent yields a 2–3x speedup compared to sequential builds. This makes our optimized setup 2–3 times faster than a standard configuration.
For large teams, we integrate Gradle Build Cache—either via Gradle Enterprise (paid) or an open-source solution with an S3 backend.
| Build Type | Without Optimization | With Optimization (cache + parallel) |
|---|---|---|
| Cold (all modules) | 5–7 min | 2–3 min |
| Incremental | 90 sec | 20–30 sec |
The Gradle User Manual recommends combining both approaches.
CI Platform Comparison for Android
| CI Platform | Setup Features | Average Build Time After Cache |
|---|---|---|
| GitHub Actions | Simple integration, large ecosystem | ~2 min |
| GitLab CI | Built-in Docker, excellent cache | ~1.5 min |
| Bitrise | Optimized for mobile, many ready steps | ~2.5 min |
Common missteps when configuring CI
- Incorrect keystore encoding (Base64 with line breaks) leads to decoding errors.
- Missing cache between runs: without using
actions/cachewith a proper key, each build re-downloads dependencies. - Using debug signing in a release AAB—Google Play will reject such file.
- Forgetting to disable Gradle Daemon in CI, causing instability.
What’s Included in Our Work
- Audit of the current
build.gradle(Groovy → Kotlin DSL, plugin versions, suboptimal configs) - Signing config via CI environment variables
- CI pipeline for your platform (GitHub Actions, GitLab CI, Bitrise)
- Gradle caching (local and remote)
- Branch-based configuration using build flavors
- Comprehensive documentation for the team, including setup guides and troubleshooting
- Developer training session (up to 2 hours) to ensure smooth adoption
- Access to our example repositories and templates
- Post-delivery support for 2 weeks to address any issues
- Stability guarantee—everything works without manual adjustments after delivery
Our Process
- Initial consultation and analysis of the current build.
- Migration to modern Gradle + Kotlin DSL (if needed).
- Signing config via CI secrets.
- CI configuration with caching and parallelism.
- Testing on several branches (main, develop, release/).
- Documentation and handover to the team.
Cost is calculated individually after requirement analysis. Typical investment starts at $1,500 for a single-module project and ranges up to $3,500 for complex multi-module setups. Timeline: 2–3 days for a single-module project, up to 5 days for multi-module. Contact us for a project assessment—we’ll help implement build automation end-to-end. Request a consultation to get exact deadlines and pricing for your project.
We have over 5 years of experience in Android development and have set up pipelines for 30+ projects—from startups to enterprise apps. Our engineers stay up-to-date with the latest Gradle and AGP versions, so you get a modern configuration without outdated practices.







