Skip to content
Back to Blog

Automating Mobile Beta Deployment with Fastlane

BetaDrop Team
Updated
11 min read
automate beta deploymentfastlane tutorialcicd for mobilecontinuous delivery ios
How to Automate Beta Deployment with Fastlane

Reviewed by Kaushal Rola

Founder, Immersive Mobile Designs — we build the OTA tooling this post describes.

Share:

Manually archiving, signing, and uploading apps is a waste of developer time. In 2026, if you aren't automating your mobile release pipeline, you're doing it wrong.

This guide shows you how to use Fastlane to automate your beta deployment from "git push" to "ready for testers".

What is Fastlane?

Fastlane is a collection of tools (actions) that handle specific mobile development tasks. You define "lanes" (workflows) in a Fastfile (Ruby script).

Key Components

  • scan - Automates running tests.
  • match - Automates certificates and profiles (syncing them via Git/Cloud).
  • gym - Builds and archives your iOS app into an .ipa (Android uses the gradle action).
  • pilot - Uploads to TestFlight.
  • supply - Uploads metadata and binaries to Google Play.

Step 1: Installation

If you have Ruby installed:

gem install fastlane

On macOS you can also use Homebrew (brew install fastlane). For CI, the most reproducible option is to pin the version in a Gemfile and run everything through Bundler:

# Gemfile
source "https://rubygems.org"
gem "fastlane"

# then
bundle install
bundle exec fastlane init

fastlane init creates a fastlane/ folder containing your Fastfile and Appfile. Commit both so every teammate and CI runner shares the same lanes.

Step 2: Defining a Beta Lane

Here is a typical Fastfile setup for distributing an iOS beta to TestFlight:

default_platform(:ios)

platform :ios do
  desc "Push a new beta build to TestFlight"
  lane :beta do
    # 0. On CI: a temporary keychain for match, and API key auth
    #    instead of Apple ID prompts
    setup_ci
    app_store_connect_api_key(
      key_id: ENV["ASC_KEY_ID"],
      issuer_id: ENV["ASC_ISSUER_ID"],
      key_content: ENV["ASC_KEY_CONTENT"]
    )

    # 1. Ensure clean git status
    ensure_git_status_clean

    # 2. Increment build number
    increment_build_number(xcodeproj: "MyApp.xcodeproj")

    # 3. Sync certificates (Codesigning)
    match(type: "appstore", readonly: true)

    # 4. Build the app
    gym(scheme: "MyApp")

    # 5. Upload to TestFlight
    pilot(skip_waiting_for_build_processing: true)
    
    # 6. Notify team on Slack
    slack(
      message: "New Beta Build Uploaded! 🚀",
      slack_url: "https://hooks.slack.com/..."
    )
  end
end

Alternative: Ad Hoc OTA Distribution Lane

If you want to skip the App Store review wait entirely (e.g., using BetaDrop), swap pilot for an over-the-air upload. Build an ad-hoc IPA with gym, then push it straight to testers from a sh step using the BetaDrop CLI:

lane :adhoc do
  match(type: "adhoc")
  # Xcode 15.4 renamed "ad-hoc" to "release-testing"; current Xcode still
  # accepts the old name as deprecated. gym only accepts the old names and
  # fails on "release-testing", so to use the new name, export with
  # xcodebuild -exportArchive and an ExportOptions.plist instead.
  gym(scheme: "MyApp", export_method: "ad-hoc")

  # Push an OTA install link + QR code with the BetaDrop CLI.
  # Needs BETADROP_TOKEN (Settings → Developer → API tokens) in the env.
  sh "npm i -g @betadrop/cli"
  # sh runs inside ./fastlane, so take the .ipa path from gym
  sh("betadrop", "publish", lane_context[SharedValues::IPA_OUTPUT_PATH], "--ci")
end

The CLI returns an OTA install link and a QR code. Testers open the link in Safari on their iPhone and install directly — no cables, no TestFlight, and no tester accounts. Ad Hoc builds need no extra step on the device; only enterprise-signed builds ask testers to trust the certificate under Settings → General → VPN & Device Management (see fixing the untrusted developer error). You can also do the upload by hand at the IPA upload page. Ad-hoc builds only install on devices whose UDID is in the provisioning profile, so collect tester UDIDs before you ship.

The Android equivalent builds an APK with gradle and uploads it the same way:

lane :adhoc_android do
  gradle(task: "assembleRelease")
  sh("betadrop", "publish", lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH], "--ci")
end

Integrating with CI/CD

Fastlane needs no UI, so it runs unattended on any CI runner. If you are still choosing a platform, see our comparison of GitHub Actions, GitLab CI, and Bitrise. For GitHub Actions, your valid workflow file might look like this:

name: Deploy Beta
on:
  push:
    branches: [ main ]
jobs:
  build:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.3"
          bundler-cache: true
      - name: Run Fastlane
        run: bundle exec fastlane beta
        env:
          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
          MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }}
          ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
          ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
          ASC_KEY_CONTENT: ${{ secrets.ASC_KEY_CONTENT }}

On CI, never sign in with an Apple ID and password — two-factor prompts will hang the job. Instead, create an App Store Connect API key (Users and Access → Integrations → App Store Connect API) and load it with the app_store_connect_api_key action at the top of your lane, after setup_ci, which gives match a temporary keychain so it never waits on a keychain prompt. The beta lane above does both. Store the match encryption passphrase and the API key contents as encrypted repository secrets, never in the Fastfile.

Push OTA links from CI with BetaDrop

The fastest feedback loop is a link waiting in Slack the moment a build turns green. The free BetaDrop CLI (npm i -g @betadrop/cli) drops into any Fastlane lane or CI job and returns an instant OTA install link and QR code for a fresh .ipa or .apk (up to 500 MB). Testers install straight from their phone browser, so you never wait on App Store review or manage tester accounts. Registered builds start at 3 days and can be extended to 7 days on a free account; anonymous guest links expire after 24 hours.

Fastlane transforms a 30-minute manual headache into a hands-off background process. Start simple with build automation, then add signing (Match) and deployment layers. For rapid internal testing, pair it with an over-the-air distribution flow so a push to main ends with an install link in your testers' hands. If the review queue or tester invites are the bottleneck, reaching for a TestFlight alternative takes that wait out of the loop entirely.

Frequently Asked Questions

What is Fastlane?

Fastlane is an open-source tool suite that automates tedious tasks for iOS and Android developers, such as generating screenshots, dealing with code signing, and releasing apps. You describe your workflows as lanes in a Ruby Fastfile and run them the same way locally or on CI.

Is Fastlane free?

Yes, Fastlane is completely free and open source under the MIT License. The only cost is the CI minutes or the Mac hardware you run it on, since iOS builds require macOS.

Does Fastlane run on CI/CD?

Yes, Fastlane requires no UI and is designed to run on CI services like GitHub Actions, CircleCI, Bitrise, and Jenkins. iOS lanes need a macOS runner (for example runs-on: macos-latest), while Android-only lanes run fine on a Linux runner.

Can Fastlane upload to TestFlight?

Yes, the pilot action uploads builds to TestFlight and manages testers. On CI, authenticate with an App Store Connect API key (app_store_connect_api_key) rather than an Apple ID so two-factor prompts do not stall the pipeline.

How do I distribute an iOS beta without TestFlight from a Fastlane lane?

Build an ad-hoc or development IPA with gym, then upload it to an over-the-air host from a sh step in your lane. With the BetaDrop CLI and a BETADROP_TOKEN in the environment, you run betadrop publish on the .ipa and get back an OTA install link plus a QR code that testers open directly in Safari, with no App Store review wait and no tester accounts to manage.

Can Fastlane build and distribute Android APKs the same way?

Yes. Use gradle(task: "bundleRelease") and supply to push an .aab to Google Play, and gradle(task: "assembleRelease") for an .apk you upload to an over-the-air host for quick internal testing. BetaDrop accepts both .ipa and .apk files up to 500 MB and returns an instant install link for each build.

Ready to Distribute Your App?

Upload your IPA or APK file and get a shareable install link in seconds. Your first upload needs no account. Completely free.