Mobile CI/CD
Automate iOS and Android build, test, and release pipelines with Fastlane, Xcode Cloud, and GitHub Actions for consistent, reliable delivery.
Mobile CI/CD automates the build, test, and release pipeline for iOS and Android apps. Without automation, releasing requires manual code signing, device registration, and upload steps-error-prone and slow. With CI/CD, a merged PR can trigger a TestFlight build and automated test run without human intervention.
Automate everything that can be automated: signing, versioning, testing, uploading. Use Fastlane for orchestration-it has plugins for every step. Test on simulators in CI; test on physical devices with Xcode Cloud or Firebase Test Lab.
Workflow
- Set up Fastlane for iOSFastlane unifies code signing, build, test, and deployment into reproducible lanes.
- Automate code signing with Fastlane MatchManual certificate management across team members causes "certificate expired" outages; Match syncs certificates via Git.
- Configure GitHub Actions for mobile CIGitHub Actions runs on macOS runners needed for iOS builds and integrates with the PR workflow.
- Automate Android builds and Play Store uploadPlay Store upload requires signing keystore, version management, and API credentials - all automatable.
- Implement versioning and release automationManual version bumping causes forgotten increments or version conflicts.
Output Format
Fastlane lanes for test/beta/release, Match for code signing, GitHub Actions workflow for iOS and Android, automated versioning, TestFlight and Play Store upload.
Examples
Fastfile beta lane: `lane :beta do increment_build_number; match(type: "appstore", readonly: true); gym(scheme: "MyApp"); pilot(notify_external_testers: false) end`GitHub Actions iOS: `- uses: actions/cache@v4
with:
path: vendor/bundle
key: gems-${{ hashFiles("Gemfile.lock") }}
- run: bundle install
- run: bundle exec fastlane test`Android signing in CI: `echo "$KEYSTORE_BASE64" | base64 --decode > android/keystore.jks && ./gradlew bundleRelease -PKEYSTORE_PATH=keystore.jks -PKEYSTORE_PASSWORD=$KEY_PASS`Edge Cases & Gotchas
- Xcode version drift: pin Xcode version in CI with `xcodes select 16.2` or `xcode-select -s /Applications/Xcode_16.2.app`; mismatched versions break builds silently
- Match conflicts: two CI jobs running simultaneously can cause Match conflicts when both try to generate certs; use readonly mode in CI, generate locally
- APNs certificates in CI: push notification certificates are separate from signing certs; manage via App Store Connect API Keys, not Match
When to Break These Rules
- Xcode Cloud (Apple's built-in CI) is simpler for small iOS teams and integrates directly with TestFlight without Match configuration - worth considering before setting up custom GitHub Actions runners.
Reference Files
Fastlane docs: https://docs.fastlane.tools/Fastlane Match: https://docs.fastlane.tools/actions/match/Xcode Cloud: https://developer.apple.com/xcode-cloud/GitHub Actions macOS: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners