What does a real mobile CI/CD pipeline look like — Fastlane, GitHub Actions, Bitrise?
A signed build only ships after static analysis, unit tests, instrumented UI tests, and a beta ring — and even the store release itself rolls out in stages, not one switch.
LEARN BY DOINGPut your intuition to work3 steps
What does a real mobile CI/CD pipeline look like — Fastlane, GitHub Actions, Bitrise?
Use the lesson’s examples and explanation to check your idea.
Personal reflection. Nothing is sent to an AI service.#What "a real pipeline" means beyond a green checkmark
A junior answer describes a single CI job that runs ./gradlew test on push. A senior answer describes a pipeline with distinct, gated stages — static analysis, unit tests, a signed build, instrumented UI tests, beta distribution, and a store release — where each stage can fail independently and later stages never run against an artifact that hasn't passed the ones before it. The specific tools differ (Fastlane, GitHub Actions, Bitrise), but the shape of the pipeline is close to universal across serious mobile teams.
#The stages, in order
Every commit or pull request triggers static analysis first — ktlint/detekt on Android, SwiftLint on iOS — because it's the cheapest signal and should fail fast before spending CI minutes on anything else. Unit tests run next against the JVM directly (no emulator needed) or via xcodebuild test against a simulator for pure-logic Swift tests, and only after both pass does the pipeline build a real artifact. Feature branches and pull requests typically stop at an unsigned debug build so the PR gets a status check quickly; merges to main or a release branch go further and produce a signed release build, because signing keys should never be exposed to arbitrary fork pull requests.
#Fastlane is the glue, not the CI system itself
Fastlane doesn't replace GitHub Actions or Bitrise — it's the tool that turns a dozen fragile shell commands into a named, versioned lane that both a human and CI can run identically. A Fastfile typically exposes lanes like test, beta, and release, and each one composes smaller actions underneath: one action builds and signs an iOS app, another manages certificates and provisioning profiles by syncing them from an encrypted git repository so no developer ever clicks through Xcode's signing UI by hand, another drives an Android Gradle build, another uploads to Google Play at a specific rollout percentage, and others upload to TestFlight and App Store Connect respectively. The single biggest win of naming Fastlane in an interview answer is naming the certificate-syncing action specifically — signing is where most first-time mobile CI setups die.
#GitHub Actions vs. Bitrise — different tradeoffs, not a strict upgrade
GitHub Actions is generic CI: you write the workflow yourself, you choose the runner (a macOS runner is required for any iOS build step, and is billed at a materially higher rate than Linux), and you own caching Gradle, CocoaPods, or Swift Package Manager dependencies yourself for reasonable build times. Bitrise is mobile-native CI: certificate and provisioning-profile management, an Apple Developer Portal integration, and device-farm access are closer to first-class citizens there, at the cost of a SaaS bill and less flexibility outside the mobile-shaped box it was built for. Plenty of serious teams run both — GitHub Actions gating pull requests with fast unit-test feedback, Bitrise (or a self-hosted macOS runner pool) owning the heavier signed-build-and-distribute lanes.
#Beta distribution is a real gate, not an afterthought
A signed build that passes instrumented UI tests — Espresso/Compose on a headless or cloud device-farm emulator, XCUITest on a simulator or a physical device farm — goes to internal testers before it ever reaches a store: Firebase App Distribution or the Play Console's internal track on Android, TestFlight on iOS. This is a deliberate gate, not red tape: crash and ANR signals from real testers on real devices catch what a CI emulator run structurally cannot, and skipping this step is exactly how a broken build reaches production users instead of a QA channel first.
#The store release itself is staged, not a switch
Both stores support — and mature teams enforce — a staged or phased rollout: a small percentage of users first, ramping up over days while watching crash-free rate and ANR rate in the store's own analytics, with the ability to halt or roll back before the rollout reaches everyone. Automating that percentage ramp-up through Fastlane or the App Store Connect API, gated on a health check rather than a fixed timer, is the detail that separates "we ship to the store" from "we ship safely."