mobile5 min read

Tutorial: Learn Mobile CI/CD from Scratch (2026)

Tutorial: Learn Mobile CI/CD from Scratch (2026)

Published:  |  Category: Mobile  |  Reading time: ~15 min
Tutorial: Learn Mobile CI/CD from Scratch (2026)

Mobile CI/CD automates the build, test, and deployment pipeline for iOS and Android apps. Before adopting CI/CD, my release process involved manual builds on a single developer's machine, last-minute certificate issues, and release notes written from memory. A proper mobile CI/CD pipeline eliminates these risks by automating everything from code commit to app store distribution. This tutorial focuses on practical pipelines using GitHub Actions for automation, Bitrise for managed mobile CI, Fastlane for build automation scripts, and the platform-specific distribution channels TestFlight and Play Console for delivering builds to testers and production.

The mobile CI/CD pipeline has unique challenges compared to web CI/CD. iOS builds require macOS runners, which are more expensive. Code signing for both platforms requires careful secret management. Mobile builds take longer due to asset compilation and packaging. App store review adds external latency. A mature pipeline includes multiple tracks: development builds for daily testing, beta builds for QA, release candidates for final verification, and production builds for app store submission. Each track has different signing configurations and testing requirements.

GitHub Actions for Mobile CI

GitHub Actions provides Windows, Linux, and macOS runners. For iOS, use macos-latest runners. For Android, use ubuntu-latest. Create a workflow file at .github/workflows/mobile_ci.yml. The workflow triggers on push/PR to main or develop. Set up Java for Android (actions/setup-java), Xcode for iOS (macOS runners include Xcode), and Ruby for Fastlane. Cache Gradle dependencies and CocoaPods to speed up subsequent runs. Use matrix builds to run Android and iOS jobs in parallel. Store secrets like signing certificates, API keys, and service account JSONs as GitHub Secrets. The Fastlane lanes handle the actual build and test logic.

name: Mobile CI
on: push: branches: [main]
jobs:
  android:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with: distribution: 'temurin' java-version: '17'
      - run: bundle exec fastlane android_beta

Bitrise for Managed Mobile CI/CD

Bitrise is a CI/CD platform designed specifically for mobile apps. It provides pre-configured workflows for iOS and Android, macOS runners, and integrations with Fastlane, Firebase, and app stores. Connect your Git repository, Bitrise scans your project and generates a workflow. The workflow editor is visual with steps like Git Clone, Certificate and Profile Installer, Xcode Build for Simulator, and Deploy to Bitrise. Bitrise manages code signing automatically with its Code Signing tab. Environment variables and secrets are encrypted. Bitrise's workflows can export to TestFlight, Google Play, and Firebase App Distribution. The free tier includes 90 minutes of build time per month.

# Bitrise export to TestFlight step
# Uses the Xcode Archive & Export for iOS step with TestFlight distribution method

Fastlane Lanes and Shared Configuration

Fastlane is the automation layer between CI and the app stores. Define lanes in the Fastfile for each track: beta (internal testing), release (app store), and enterprise (MDM distribution). Shared configuration in the Appfile and Matchfile ensures consistency. The Fastfile can call Gradle directly for Android or xcodebuild for iOS via Fastlane actions. Use lanes with parameters for flexibility: lane :deploy do |options| build_type = options[:type] end. Fastlane actions include increment_build_number, build_app, upload_to_testflight, upload_to_play_store, and slack for notifications. Run fastlane locally to debug before committing to CI.

platform :android do
  lane :beta do
    gradle(task: 'assembleRelease')
    upload_to_play_store(track: 'internal')
  end
end

Code Signing in CI

iOS code signing in CI requires distribution certificates and provisioning profiles. Fastlane match is the standard solution. Store the match encryption passphrase as a CI secret. For Android, sign with a keystore. Base64-encode the keystore file and store it as a secret. In the CI job, decode it to a file and reference it in build.gradle. For GitHub Actions, copy the keystore from secrets: echo "$KEYSTORE" | base64 --decode > keystore.jks. For iOS match, run bundle exec match appstore --readonly in CI (readonly prevents match from creating new certificates). Ensure certificates do not expire during the pipeline run.

# GitHub Actions keystore setup
- name: Decode keystore
  run: echo "$KEYSTORE_BASE64" | base64 --decode > app/keystore.jks
  shell: bash

Testing in the Pipeline

Integrate multiple testing stages in CI. Unit tests run first (fast, catch logic errors). Integration tests run next (slower, catch component interaction issues). UI tests run last (slowest, simulate real user flows). Fastlane scan runs iOS unit and UI tests. Gradle connectedCheck runs Android tests. For UI tests on CI, use hardware acceleration if available and set up emulators/simulators with the correct device configurations. Parallelize test execution where possible. Fail the build on test failures. For acceptance testing, deploy to Firebase Test Lab (Android) or Xcode Cloud's Test (iOS) with real devices. Track test coverage with Codecov or SonarQube.

lane :test do
  run_tests(scheme: 'MyApp', devices: ['iPhone 15', 'iPhone SE'])
  gradle(task: 'connectedReleaseAndroidTest')
end

Distribution: TestFlight and Play Console

TestFlight (iOS) and Play Console's Internal Testing (Android) are the primary distribution channels for beta builds. Fastlane actions upload_to_testflight and upload_to_play_store handle the upload. For TestFlight, configure the app in App Store Connect, manage testers in groups, and export compliance. For Play Console, create an Internal Testing track, add tester emails, and manage release notes. Both platforms support staged rollouts: release to 5% of users, monitor crashes and feedback, then increase to 100%. For enterprise distribution, use MDM or over-the-air (OTA) distribution. Automate release notes generation from Git commit messages between tags.

lane :release do
  increment_build_number
  build_app(scheme: 'MyApp')
  upload_to_testflight(skip_waiting_for_build_processing: false)
  upload_to_play_store(track: 'production', release_status: 'completed')
end

Frequently Asked Questions

What is the best CI/CD platform for mobile apps?

GitHub Actions is great if your code is on GitHub and you want a unified platform. Bitrise is purpose-built for mobile and handles signing and iOS complexities better. CircleCI offers fast macOS runners. Choose based on team size and budget.

How long does a mobile CI/CD pipeline take?

Android builds take 5-15 minutes. iOS builds take 10-30 minutes. UI tests add 5-20 minutes. Aim for total under 30 minutes. Use caching, parallelization, and tiered testing (fast tests first).

Do I need TestFlight for iOS beta testing?

Yes for external testing with up to 10,000 testers. For internal testing (up to 100 users), TestFlight is also the only official Apple distribution. Alternative platforms like Diawi or InstallOnAir allow ad-hoc distribution but have limitations.

How do I handle app store review in CI/CD?

Automate submission to app store review but monitor status manually (or via Fastlane's pilot action). Review takes 24-48 hours. Structure releases so that code freeze happens before submission. Use phased releases to limit blast radius.

Originally published on Ayodhyyya. Last updated June 1, 2026.