Setting up CI/CD for an iOS application via Fastlane

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Setting up CI/CD for an iOS application via Fastlane
Medium
~2-3 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

CI/CD Setup for iOS Applications via Fastlane

Fastlane is the de facto standard for iOS build automation outside the Apple ecosystem. It runs on any CI: GitHub Actions, GitLab CI, Jenkins, Bitrise. Main advantage over Xcode Cloud—complete control over each step and the ability to run the same command locally that CI will execute.

Why Code Signing Is the Main Problem

iOS requires a valid provisioning profile and certificate for any build not in simulator. On local machines they exist in Keychain. On CI server—they do not. Without proper fastlane setup, each build fails with Code Signing Error: No profiles for bundle ID found.

fastlane match solves this: all certificates and profiles are stored encrypted in a separate Git repository (or S3/Google Cloud). On CI—one command fastlane match adhoc downloads and installs the needed profile. Passphrase to match—a secret CI variable.

match workflow:

Git repository (encrypted) ←→ fastlane match ←→ Apple Developer Portal
                                        ↓
                                CI Keychain (temporary)

For teams of 5+ developers, match in readonly mode on CI and normal mode on development machines—standard configuration.

Fastfile Structure

default_platform(:ios)

platform :ios do
  before_all do
    setup_ci if ENV['CI']  # Creates temporary Keychain on CI
  end

  lane :test do
    run_tests(
      scheme: "MyApp",
      devices: ["iPhone 15", "iPhone SE (3rd generation)"],
      code_coverage: true
    )
  end

  lane :beta do
    match(type: "adhoc", readonly: true)
    increment_build_number(
      build_number: ENV["CI_PIPELINE_ID"] || Time.now.to_i.to_s
    )
    build_ios_app(
      scheme: "MyApp",
      configuration: "Release",
      export_method: "ad-hoc"
    )
    firebase_app_distribution(
      app: ENV["FIREBASE_APP_ID"],
      groups: "qa-team",
      release_notes: changelog_from_git_commits(commits_count: 5)
    )
  end

  lane :release do
    match(type: "appstore", readonly: true)
    increment_build_number(build_number: latest_testflight_build_number + 1)
    build_ios_app(scheme: "MyApp", configuration: "Release", export_method: "app-store")
    upload_to_testflight(skip_waiting_for_build_processing: true)
    slack(message: "New build uploaded to TestFlight!", channel: "#releases")
  end
end

setup_ci creates a temporary Keychain within the CI job. Without this, fastlane attempts to open the user Keychain, which is inaccessible on headless CI.

Build Number Management

increment_build_number without arguments reads the current number from Info.plist and increments by 1. But with parallel CI jobs, collisions are possible—two PRs build simultaneously and both get the same number. Solution: use CI_PIPELINE_ID (GitLab) or github.run_number (GitHub Actions) as build number. This guarantees uniqueness.

GitHub Actions Integration

- name: Run Fastlane Beta
  env:
    MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
    MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_AUTH }}
    FIREBASE_APP_ID: ${{ secrets.FIREBASE_APP_ID }}
    FIREBASE_TOKEN: ${{ secrets.FIREBASE_CLI_TOKEN }}
  run: bundle exec fastlane beta

Runner must be macOS (runs-on: macos-14). Linux runners are not suitable for iOS builds—Xcode runs only on macOS.

Dependency Caching

The longest step—pod install or swift package resolve. On GitHub Actions cache:

- name: Cache CocoaPods
  uses: actions/cache@v4
  with:
    path: Pods
    key: ${{ runner.os }}-pods-${{ hashFiles('Podfile.lock') }}

Saves 3–8 minutes per run when Podfile.lock is unchanged.

Timeline

Basic Fastlane setup with match, test, and beta lanes on GitHub Actions: 3–5 days. Full configuration with release lane, changelog, Slack notifications, caching, multi-scheme support: 1–2 weeks. Cost calculated individually.