DevOps

CI/CD for Mobile Apps: How We Ship Faster Without Breaking Things

Back to Blog

Web teams have had CI/CD figured out for years. Push code, run tests, deploy. Mobile is different. You are dealing with code signing certificates, provisioning profiles, platform-specific build tools, app store review processes, and device fragmentation. A pipeline that works for a React app will not survive contact with Xcode.

At DEVSFLOW, every client project ships through an automated pipeline from day one. Here is the architecture we use and why each piece matters.

The Pipeline Overview

Our standard mobile CI/CD pipeline has five stages:

Every stage is automated except the final submission. We keep that manual because App Store review is not instant and timing matters for coordinated launches.

Code Signing: The Hardest Part

iOS code signing is the single biggest source of CI/CD failures in mobile. Certificates expire. Provisioning profiles get revoked. A developer's local keychain works but the CI machine's does not.

We solve this with Fastlane Match. All certificates and provisioning profiles live in an encrypted private Git repository. The CI machine pulls them fresh on every build. When a certificate expires, we regenerate it once and every pipeline picks it up automatically.

If your iOS builds work on one developer's machine but not another's, your code signing is not automated. Fix this before anything else.

For Android, we store the keystore file and signing credentials as encrypted CI secrets. Gradle reads them from environment variables at build time. The keystore never lives in the source repository.

Fastlane: The Backbone

Fastlane orchestrates everything between "code compiled" and "build distributed." Our standard Fastfile includes lanes for:

We version-lock Fastlane with Bundler and pin plugin versions. An uncontrolled Fastlane update has broken more CI pipelines than actual code bugs.

GitHub Actions: Our CI Platform

We run most pipelines on GitHub Actions with macOS runners for iOS and Linux runners for Android. The split matters: macOS runners cost 10x more per minute than Linux. Running Android builds on macOS is burning money for no reason.

Key optimizations we apply:

Testing in CI: What Actually Works

Unit tests in CI are straightforward. UI tests are not. Emulator-based tests on CI are slow and flaky. Simulator tests on macOS are better but still add 10-15 minutes to a pipeline.

Our approach: run unit tests on every PR. Run UI tests nightly against the main branch. This catches regressions without slowing down the development feedback loop. For critical flows (login, payment, onboarding), we run a small UI test suite on every merge to main.

We use XCTest for iOS and JUnit with Espresso for Android. For React Native projects, Jest handles the JavaScript layer and Detox runs end-to-end tests on simulators.

Distribution: Getting Builds to Testers

iOS: TestFlight is the standard. Every merge to the develop branch triggers a beta upload. Testers get a push notification. External testers require a brief Beta App Review, so we keep a standing external test group to avoid delays.

Android: Firebase App Distribution for internal builds, Google Play internal testing track for pre-release. Firebase is faster (no review), Play Console is better for staged rollouts.

Both platforms get build notes auto-generated from the Git commit log since the last release. Testers always know what changed.

Version Management

We automate version bumping with a simple convention: the CI reads the version from a single source of truth (a version file or the build config), increments the build number on every CI run, and tags the commit.

Marketing version (1.2.0) is bumped manually when a release is planned. Build number (142, 143, 144) increments automatically. This means every TestFlight and Firebase build has a unique identifier with zero manual work.

Monitoring After Deploy

The pipeline does not end at the App Store. We integrate Firebase Crashlytics into every project and set up Slack alerts for crash spikes. If the crash-free rate drops below 99.5% after a release, the team is notified within minutes.

For enterprise clients, we also monitor app size trends, startup time, and API error rates per app version. Regressions are caught before users report them.

If your mobile builds are still manual or your pipeline is held together with workarounds, let us set it up properly. We can have a production-grade pipeline running in your repo within a week.

Zawar Nadeem

Zawar Nadeem

Founder & Lead Android Engineer at DEVSFLOW Technologies