Every Android team has felt the sting of a broken release. The build that worked on a developer's machine fails in CI. A last-minute hotfix introduces a regression. Version codes collide, and the Play Store rejects the upload. These are not just annoyances; they erode team confidence and delay value delivery to users. This guide provides a step-by-step checklist that turns your commit-to-launch process into a repeatable, auditable pipeline. We'll walk through what you need before you start, the core workflow, tool choices, variations for different team sizes, and the pitfalls that trip up even experienced teams. By the end, you'll have a concrete plan to implement or refine your own Opolis pipeline.
Who Needs a Pipeline Checklist and What Goes Wrong Without One
Any Android team that releases an app to production benefits from a structured pipeline. If you are a solo developer, a checklist prevents you from skipping steps when you are in a hurry. If you are part of a larger team, it ensures that every member follows the same process, reducing the risk of human error. Without a checklist, teams often experience a cascade of issues: inconsistent build environments, missed code reviews, unversioned dependencies, and manual release steps that are easy to forget.
Consider a typical scenario: a team of five developers works on a social media app. They use Git for version control, but there is no enforced branch strategy. Developers commit directly to the main branch, and builds are triggered manually. One Friday afternoon, a developer merges a feature that inadvertently bumps the target SDK to an unsupported level. The CI server, which runs on a different Java version, fails to compile. The team spends hours debugging environment differences. Meanwhile, a critical bug fix is waiting for release, but no one remembers to update the version code. The release is delayed by two days.
This kind of chaos is avoidable. A pipeline checklist introduces discipline: every commit goes through a standardized build, test, and review process. Versioning is automated. Signing and distribution are handled by scripts, not by a single person's local keystore. The checklist becomes the single source of truth for how a release happens. It also makes onboarding new team members faster — they can read the checklist and understand the workflow without relying on tribal knowledge.
Another common problem is the lack of a rollback plan. Without a pipeline, rolling back a release often means reverting commits and rebuilding manually, which is error-prone. A good pipeline includes version tagging, automated rollback scripts, and a clear process for hotfixes. The checklist ensures that you have thought about these scenarios before you need them.
In short, if you have ever felt nervous before a release, or if you have spent more time debugging builds than writing features, you need a pipeline checklist. It is the difference between hoping everything works and knowing it will.
Who Should Use This Checklist
This checklist is designed for Android teams that use Git, have a CI/CD system (or plan to set one up), and release to Google Play or an enterprise app store. It assumes a basic understanding of Gradle, Android SDK tools, and version control. If you are new to these concepts, we recommend familiarizing yourself with them first, as the checklist builds on those foundations.
Prerequisites: What You Need Before You Start
Before you can implement a commit-to-launch pipeline, you need a few foundational elements in place. Skipping these will cause the pipeline to fail or behave unpredictably. Let's review them in order of importance.
Version Control with a Clear Branch Strategy
Git is the de facto standard for Android development. However, just having a repository is not enough. You need a branching strategy that defines where development happens, where releases are cut, and how hotfixes are handled. We recommend a simplified Git Flow or trunk-based development. The key is to have a main branch that always reflects production-ready code, and feature branches that are merged via pull requests with code review. Without this, your pipeline will struggle to know which branch to build and release from.
CI/CD Infrastructure
You need a continuous integration server that can run builds automatically on every push. Options include GitHub Actions, GitLab CI, Bitrise, Jenkins, or CircleCI. The choice depends on your team's size, budget, and ecosystem. At minimum, the CI should be able to check out code, install dependencies, run lint checks, execute unit tests, and produce an APK or AAB artifact. Many teams also use a separate continuous delivery step for release automation.
Gradle Configuration
Your Android project should be configured with Gradle build variants (debug, release) and signing configurations. The release variant should be signed with a keystore that is stored securely — not in the repository. Use environment variables or a secrets manager to inject signing credentials during CI. Also, set up version name and version code in your Gradle file, ideally automated via a script that increments the version code with each build.
Testing Infrastructure
Unit tests are essential, but you should also have integration tests and UI tests for critical flows. Your CI should run these tests on every commit to catch regressions early. For UI tests, you need an emulator or device farm. Services like Firebase Test Lab can run tests on multiple device configurations. Without tests, your pipeline is just a build machine — you won't know if the app actually works.
Release Management Tools
For Google Play releases, you need a Google Play Console account and a service account for API access. Tools like Gradle Play Publisher or Fastlane can automate uploading to Play Store tracks (internal, alpha, beta, production). For enterprise distribution, you might use MDM or a private app store. Decide on your distribution method early, as it affects the pipeline steps.
The Core Pipeline Workflow: Step by Step
With the prerequisites in place, you can build the pipeline. The following steps represent a generic but complete workflow. Adapt them to your specific tools and needs.
Step 1: Code Commit and Push
A developer finishes a feature or bug fix on a feature branch. They run local checks (lint, unit tests) and then commit with a descriptive message. The push to the remote repository triggers the CI pipeline. This is the moment automation takes over.
Step 2: CI Build and Static Analysis
The CI server checks out the branch, sets up the environment (JDK, Android SDK), and runs a Gradle build. The build includes lint checks (e.g., detekt, ktlint) and static analysis for code quality. If any check fails, the pipeline stops and notifies the developer. This ensures that only code meeting quality standards proceeds.
Step 3: Automated Testing
After a successful build, the CI runs unit tests. If they pass, it runs integration tests and UI tests on emulators or a device farm. Test results are published, and failures are reported immediately. This step catches regressions before they reach human testers.
Step 4: Code Review and Merge
The developer creates a pull request (PR) to the main branch. The CI automatically runs the pipeline on the PR branch. Team members review the code, and the PR is merged only after all checks pass and at least one approval. This step enforces quality and knowledge sharing.
Step 5: Release Branch Creation and Versioning
When the team decides to release, a release branch is cut from main. The version name and version code are updated automatically by a script (e.g., using Git tags or a version file). The CI builds a signed release APK/AAB and runs a full test suite on the release branch. If tests pass, the artifact is stored as a release candidate.
Step 6: Manual QA and Sign-off
Even with automated tests, manual QA is valuable. The release candidate is distributed to testers via an internal track. QA runs exploratory tests and verifies critical flows. Any issues are fixed on the release branch, and the build is repeated. Once QA signs off, the release is ready for production.
Step 7: Production Release and Monitoring
The signed artifact is uploaded to the production track of Google Play. The pipeline can automate this using Fastlane or Gradle Play Publisher. After release, monitoring tools (Crashlytics, Play Console) track crashes and performance. If a critical issue is found, the team can roll back or trigger a hotfix pipeline.
Step 8: Post-Release Cleanup
The release branch is merged back to main if not already done. Version tags are pushed. The pipeline updates any changelog or release notes. Finally, the team reviews the release process for improvements.
Tools, Setup, and Environment Realities
Choosing the right tools is crucial for a smooth pipeline. Here we discuss popular options and their trade-offs.
CI/CD Platforms
GitHub Actions is a strong choice for teams already on GitHub. It offers tight integration, a large marketplace of actions, and free minutes for public repositories. For private repos, costs scale with usage. GitLab CI is excellent for end-to-end DevOps, with built-in container registry and Kubernetes integration. Bitrise is mobile-focused, with pre-built workflows for Android and iOS, but can be expensive for large teams. Jenkins is self-hosted and highly customizable, but requires maintenance. We recommend GitHub Actions or GitLab CI for most teams due to their balance of features and cost.
Build and Signing
Gradle is mandatory for Android builds. Use the signingReport task to verify your signing configuration. Store the keystore file in a secure location like a password manager or CI secrets vault. Never commit it to the repository. For automated versioning, consider the gradle-git-version plugin or a custom script that reads Git tags.
Testing Tools
JUnit and Mockito for unit tests; Espresso and Compose UI Test for UI tests. For device testing, Firebase Test Lab provides a wide range of devices. Alternatively, you can use Sauce Labs or BrowserStack. For linting, detekt and ktlint are popular. Integrate these as Gradle tasks so they run as part of the build.
Release Automation
Fastlane is the most mature tool for automating Android releases. It handles screenshots, metadata, and upload to Play Store via the supply action. Gradle Play Publisher is a Gradle plugin that integrates directly with Play Console. It is simpler but less flexible than Fastlane. We prefer Fastlane for its ecosystem and community support.
Environment Consistency
Use Docker or a CI image with pinned SDK versions to ensure consistency between local and CI environments. Specify exact JDK, Gradle, and Android SDK versions in your CI configuration. This prevents "works on my machine" issues.
Variations for Different Constraints
Not every team has the same resources or requirements. Here are variations of the pipeline for common scenarios.
Solo Developer or Small Team (1-3 People)
With limited time, you can simplify: use trunk-based development with short-lived feature branches. Skip the release branch; instead, tag commits on main for releases. Automate versioning with a simple script. Use GitHub Actions free tier for CI. Manual QA can be minimal if you have good test coverage. Focus on automating the build and upload steps to save time.
Medium Team (4-10 People)
Implement a full Git Flow with release branches. Use a dedicated CI plan (e.g., GitHub Actions paid or Bitrise). Integrate code quality checks and require PR approvals. Use Fastlane for release automation. Set up internal testing tracks for QA. This balances speed and quality.
Large Team (10+ People) or Multiple Apps
Introduce monorepo management (if using a single repo) or multi-repo orchestration. Use Jenkins or GitLab CI for complex pipelines. Implement feature flags to decouple deployment from release. Use a release train model with fixed cadences (e.g., weekly). Automate everything, including rollback scripts. Invest in comprehensive UI testing and device farms.
Enterprise or Regulated Environments
If you need audit trails, compliance, or manual approval gates, add steps for signing certificates, code signing, and security scans. Use a CI that supports approval workflows (e.g., GitLab CI with manual jobs). Store secrets in a vault (HashiCorp Vault, AWS Secrets Manager). Generate signed manifests and store build logs for compliance.
Pitfalls, Debugging, and What to Check When It Fails
Even a well-designed pipeline can fail. Here are common issues and how to fix them.
Build Failures Due to Environment Mismatch
Symptom: Build works locally but fails in CI. Check CI environment variables, SDK versions, and Gradle cache. Use the same JDK version (specify in CI config). Clear cache and rebuild. Consider using a Docker image that mirrors your local setup.
Signing Errors
Symptom: APK is unsigned or signed with wrong key. Verify that the keystore file is accessible to CI and that the signing config in Gradle references the correct store. Check that environment variables for passwords are set. Run ./gradlew signingReport to debug.
Version Code Collisions
Symptom: Play Store rejects upload because version code already exists. Automate version code increments using Git tags or a monotonically increasing counter. Never manually set version codes. Use a script that reads the latest tag and increments by one.
Test Flakiness
Symptom: UI tests fail intermittently. Use retry mechanisms (e.g., FlakyTest annotation or rerun in CI). Stabilize tests by adding waits, using idling resources, and running on consistent emulator images. Isolate tests that depend on network or external services.
Slow Pipeline
Symptom: Build takes too long. Optimize by caching Gradle dependencies, using parallel execution, and running only relevant tests (e.g., affected modules). Consider using a build cache service like Gradle Enterprise.
Rollback Difficulties
Symptom: Need to revert a release but cannot easily rebuild the previous version. Tag every release commit with a version tag. Keep release artifacts in a storage bucket. Write a rollback script that rebuilds from the tag and uploads to the previous track.
Frequently Asked Questions
Q: Should I use a single pipeline for debug and release builds?
A: Yes, but separate the steps. Debug builds can skip signing and run faster. Release builds should go through full checks. Use Gradle build variants to differentiate.
Q: How do I handle hotfixes?
A: Create a hotfix branch from the release tag, fix the issue, merge back to main and release branch. Run the full pipeline on the hotfix branch. Automate version bump for hotfixes (e.g., increment patch version).
Q: What if my team uses multiple app stores (e.g., Google Play and Amazon)?
A: Extend the pipeline with parallel release steps. Use Fastlane to upload to multiple stores. Maintain separate signing configurations if needed.
Q: Is it worth investing in UI testing early?
A: Yes, even a small set of critical path UI tests can catch regressions that unit tests miss. Start with login, purchase, and main navigation flows.
Q: How do I manage feature flags in the pipeline?
A: Use a feature flag service (e.g., LaunchDarkly, Firebase Remote Config). The pipeline does not need to manage flags; they are toggled at runtime. However, ensure that flags are cleanly removed after rollout.
What to Do Next: Specific Actions
You now have the blueprint. Here are concrete next steps to implement your Opolis pipeline:
- Audit your current workflow: list every manual step from commit to launch. Identify pain points and bottlenecks.
- Set up a CI/CD system if you don't have one. Start with a simple workflow that builds and runs unit tests on every push.
- Define your branching strategy and enforce it with branch protection rules (require PR, status checks).
- Automate versioning: write a script that increments version code on each release branch and tags commits.
- Integrate code quality tools (lint, detekt) into the build pipeline and fail the build on violations.
- Set up automated UI tests on a device farm for critical flows. Start with one or two tests.
- Automate release upload using Fastlane or Gradle Play Publisher. Test with an internal track first.
- Document the pipeline as a checklist and share it with the team. Review it after each release and iterate.
Remember, the pipeline is a living process. As your team grows and your app evolves, revisit the checklist every quarter. The goal is not perfection but predictability. Start small, measure the time saved, and expand from there.
Comments (0)
Please sign in to post a comment.
Don't have an account? Create one
No comments yet. Be the first to comment!