Overview
Fastlane combined with GitHub Actions is the Ascendion standard for mobile CI/CD (specified in ADR-MOB-003). Fastlane handles mobile-specific automation — code signing, building, testing, distribution, store submission. GitHub Actions orchestrates the workflow with matrix strategy for parallel Android and iOS builds.
Pipeline Stages
Stage 1: Validate (Every PR, ~8 minutes)
Lint (Detekt/SwiftLint), unit tests with coverage gate (Use Cases > 90%, ViewModels > 80%), snapshot test diff (zero pixel regressions), security scan (OWASP Dependency Check, GitLeaks). Runs on Linux runner for Android, macOS runner for iOS lint only (Swift compilation). Gate: block PR merge on any failure.
Stage 2: Build (Merge to Main, ~15 minutes)
Android: Gradle assembleRelease with R8 full mode. iOS: Xcode Archive with Release configuration. Parallel matrix: Android on ubuntu-latest, iOS on macos-latest. Post-build: code signing (Android Keystore decode from base64 secret; iOS fastlane match download from encrypted Git repo).
Stage 3: Test (Post-Build, ~10 minutes)
Integration tests with in-memory database. UI tests on emulator (Android) and simulator (iOS) for top 10 critical user journeys. Paparazzi/iOSSnapshotTestCase screenshot comparison. Runs after build to avoid blocking the main test loop.
Stage 4: Distribute (Post-Test, ~5 minutes)
Internal distribution: Firebase App Distribution for Android and iOS (both platforms). TestFlight for iOS internal testing. Automatic distribution to QA team. Deployment note generated from git log since last distribution.
Stage 5: QA Gate (Manual, ~24-48 hours)
GitHub Actions Environment Protection Rule on the Production environment requires QA Lead approval. QA tests on physical devices using the distributed build. No automated gate can replace human QA for the release candidate.
Stage 6: Release (Post-QA, ~10 minutes)
Android: fastlane supply uploads AAB to Google Play internal track, promotes to staged rollout (1% → 5% → 20% → 100% over 7 days). iOS: fastlane deliver uploads IPA to App Store Connect, submits for review. Automated release note generation from CHANGELOG.md.
Code Signing
iOS code signing is the most complex operational aspect of mobile CI/CD. fastlane Match solves it: all certificates and provisioning profiles stored encrypted in a dedicated Git repository. Every CI machine and developer clones them fresh using the Match passphrase (stored as MATCH_PASSWORD encrypted secret in GitHub). Certificate expiry handled automatically: Match regenerates certificates 30 days before expiry.
Android code signing: release Keystore encoded as base64 string stored as KEYSTORE_B64 encrypted secret. CI decodes to a temporary file, configures Gradle signingConfigs block reading credentials from environment variables, deletes the temporary file after signing. Enrolled in Google Play App Signing — Google manages the distribution key, protecting against Keystore loss.
Anti-Patterns to Avoid
⚠ 1. Manual Code Signing
Engineer manually downloading a Provisioning Profile from Apple Developer Portal, installing it, building locally, and uploading to TestFlight. Undocumented, unreproducible, fails when that engineer is unavailable.
Hover to see the fix ↻
↺ Correct Approach
fastlane Match. All signing materials in the encrypted repository. Any CI machine or developer with the passphrase can sign and release. Documented, reproducible, auditable.
⚠ 2. No QA Gate Before Production
Pipeline automatically promotes to production after passing automated tests.
Hover to see the fix ↻
↺ Correct Approach
GitHub Environment Protection Rule requiring QA Lead approval before any production release. Automated tests catch regressions; human QA catches usability, visual, and contextual issues automated tests miss.
Flowchart
%%{init:{'theme':'base','themeVariables':{'fontSize':'14px','fontFamily':'IBM Plex Sans, system-ui, sans-serif','primaryColor':'#DBEAFE','primaryTextColor':'#1e3a5f','primaryBorderColor':'#2563EB','lineColor':'#374151','clusterBkg':'#F9FAFB','clusterBorder':'#D1D5DB','edgeLabelBackground':'#FFFFFF'},'flowchart':{'curve':'orthogonal','padding':30,'nodeSpacing':65,'rankSpacing':75,'useMaxWidth':true}}}%%
flowchart LR
GIT["<b>git push</b><br/>to main"]
subgraph VAL["Validate · <8min"]
direction TB
L["Detekt · SwiftLint<br/>Zero violations"]
U["Unit Tests<br/>90% Use Cases<br/>80% ViewModels"]
S["Snapshot Diff<br/>Zero regressions"]
SEC2["CVE Scan<br/>Block P1/P2"]
end
subgraph BUILD["Parallel Build"]
direction TB
AND["Android<br/>ubuntu-latest<br/>Gradle · R8"]
IOS["iOS<br/>macos-latest<br/>Xcode Archive"]
end
subgraph SIGN["Sign"]
direction TB
KS["Android Keystore<br/>Base64 secret"]
FM["fastlane Match<br/>Encrypted Git repo"]
end
DIST["Distribute<br/>Firebase · TestFlight"]
QA{"QA Gate<br/>Manual approval"}
subgraph SHIP["Release"]
direction TB
PL["Google Play<br/>1%→5%→25%→50%→100%"]
AS["App Store<br/>Expedited review"]
end
GIT --> VAL --> BUILD --> SIGN --> DIST --> QA
QA -->|"Approved"| SHIP
QA -->|"Rejected"| GIT
style GIT fill:#1D4ED8,stroke:#1e3a5f,color:#ffffff
style VAL fill:#DCFCE7,stroke:#16A34A,stroke-width:2px
style BUILD fill:#DBEAFE,stroke:#2563EB,stroke-width:2px
style SIGN fill:#FEE2E2,stroke:#DC2626,stroke-width:2px
style DIST fill:#FEF9C3,stroke:#CA8A04,stroke-width:2px
style QA fill:#FEF3C7,stroke:#D97706,stroke-width:2px
style SHIP fill:#F3E8FF,stroke:#7C3AED,stroke-width:2px
style L fill:#BBF7D0,stroke:#16A34A,color:#14532D
style U fill:#BBF7D0,stroke:#16A34A,color:#14532D
style S fill:#BBF7D0,stroke:#16A34A,color:#14532D
style SEC2 fill:#BBF7D0,stroke:#16A34A,color:#14532D
style AND fill:#BFDBFE,stroke:#2563EB,color:#1e3a5f
style IOS fill:#BFDBFE,stroke:#2563EB,color:#1e3a5f
style KS fill:#FCA5A5,stroke:#DC2626,color:#7f1d1d
style FM fill:#FCA5A5,stroke:#DC2626,color:#7f1d1d
style PL fill:#E9D5FF,stroke:#7C3AED,color:#4C1D95
style AS fill:#E9D5FF,stroke:#7C3AED,color:#4C1D95
References
- Fastlane Documentation. docs.fastlane.tools
- GitHub Actions Documentation — Environments. docs.github.com/en/actions/deployment/targeting-different-environments
- Google — Play Console Staged Rollouts. support.google.com/googleplay/android-developer/answer/6346149
- Forsgren et al. — Accelerate. IT Revolution, 2018.
Mobile Engineering Reference
← Mobile Development