Start Building for Free
CircleCI.comAcademyBlogCommunitySupport

Deploy iOS applications

1 month ago7 min read
Cloud
On This Page

In this how-to guide, you will learn how to to configure Fastlane to automatically deploy iOS apps from CircleCI to a distribution service.

Introduction

Using Fastlane, CircleCI can automatically deploy iOS apps to various services. This helps remove the manual steps required to ship a beta or release version of an iOS app to its intended audience.

Deployment lanes can be combined with testing lanes so that the app is automatically deployed upon a successful build and test.

Best practices

Use Git branches

It is advisable to only run your release lane on a specific branch of your git repository, for example, a dedicated release/beta branch. This will allow releases on only successful merges into the specified branch, and prevent a release every time a push is committed during your development phase. In turn this will also reduce job completion time, as uploading to an external service may take some time depending on the size of the iOS app binary. For information on how to set up a workflow to achieve this, refer to the Branch-Level Job Execution page.

Set the build number

When uploading to a deployment service, it is important to consider the build number of the iOS app binary. Commonly this is set in the .xcproject and has to be updated manually to ensure it is unique. If the build number is not updated before each run of the deployment lane, you may find that the receiving service rejects the binary due to a build number conflict.

Fastlane provides an increment_build_number action which allows the build number to be modified during the lane execution. As an example, if you want to tie the build number to a particular CircleCI job, consider using the $CIRCLE_BUILD_NUM environment variable:

increment_build_number(
  build_number: "$CIRCLE_BUILD_NUM"
)

CircleCI configuration for Fastlane integration

All the examples on this page use Fastlane to configure deployment. For each example the following example .circleci/config.yml configuration can be used to integrate your Fastlane setup with CircleCI. This is an example config which should be edited to fit the needs of your project:

# .circleci/config.yml
version: 2.1
jobs:
  build-and-test:
    macos:
      xcode: 14.2.0
    environment:
      FL_OUTPUT_DIR: output
      FASTLANE_LANE: test
    steps:
      - checkout
      - run: bundle install
      - run:
          name: Fastlane
          command: bundle exec fastlane $FASTLANE_LANE
      - store_artifacts:
          path: output
      - store_test_results:
          path: output/scan

  adhoc:
    macos:
      xcode: 14.2.0
    environment:
      FL_OUTPUT_DIR: output
      FASTLANE_LANE: adhoc
    steps:
      - checkout
      - run: bundle install
      - run:
          name: Fastlane
          command: bundle exec fastlane $FASTLANE_LANE
      - store_artifacts:
          path: output

workflows:
  build-test-adhoc:
    jobs:
      - build-and-test
      - adhoc:
          filters:
            branches:
              only: development
          requires:
            - build-and-test

In this example, upon pushing to a development branch, the adhoc job enables producing a development build, or upload to Testflight.

Set up with App Store Connect

To set up Fastlane to automatically upload iOS binaries to App Store Connect and/or TestFlight, a few steps need to be followed to allow Fastlane access to your App Store Connect account.

The recommended way to set this up is to generate and use an App Store Connect API key. This prevents issues occurring with 2FA, which is now mandatory for Apple IDs, and is the most reliable way of interacting with the service.

To create an API Key, follow the steps outlined in the Apple Developer Documentation. Once you have the resulting .p8 file, make a note of the Issuer ID and Key ID which can be found on the App Store Connect API Keys page.

Next, a few environment variables need to be set. In your CircleCI project, navigate to Build Settings -> Environment Variables and set the following:

  • APP_STORE_CONNECT_API_KEY_ISSUER_ID to the Issuer ID
    • Example: 6053b7fe-68a8-4acb-89be-165aa6465141
  • APP_STORE_CONNECT_API_KEY_KEY_ID to your Key ID
    • Example: D383SF739
  • APP_STORE_CONNECT_API_KEY_KEY to the contents of your .p8 file
    • Example: -----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHknlhdlYdLu\n-----END PRIVATE KEY-----

Finally, Fastlane requires some information from us in order to know which Apple ID to use and which application we are targeting. The Apple ID and application bundle identifier can be set in the fastlane/Appfile as follows:

# fastlane/Appfile
apple_id "ci@yourcompany.com"
app_identifier "com.example.HelloWorld"

If you need to use different credentials for App Store Connect and the Apple Developer Portal, check the Fastlane Appfile documentation for more details.

Once this is configured, you just need to call app_store_connect_api_key in your lane before calling any actions that interact with App Store Connect (such as pilot and deliver).

1. Deploy to the App Store

The example below shows a basic lane to build, sign and upload a binary to App Store Connect. The deliver action provided by Fastlane is a powerful tool that automates the App Store submission process.

Deliver also allows various options such as automatic uploading of metadata and screenshots (which can be generated with the snapshot and frameit actions). For further configuration, refer to the Fastlane documentation for deliver.

# fastlane/Fastfile
default_platform :ios

platform :ios do
  before_all do
    setup_circle_ci
  end

  desc "Upload Release to App Store"
  lane :upload_release do
    # Get the version number from the project and check against
    # the latest build already available on App Store Connect, then
    # increase the build number by 1. If no build is available
    # for that version, then start at 1
    increment_build_number(
      build_number: app_store_build_number(
        initial_build_number: 1,
        version: get_version_number(xcodeproj: "HelloCircle.xcodeproj"),
        live: false
      ) + 1,
    )
    # Set up Distribution code signing and build the app
    match(type: "appstore")
    gym(scheme: "HelloCircle")
    # Upload the binary to App Store Connect
    app_store_connect_api_key
    deliver(
      submit_for_review: false,
      force: true
    )
  end
end

2. Deploy to TestFlight

TestFlight is Apple’s beta distribution service which is tied into App Store Connect. Fastlane provides the pilot action to make managing TestFlight distribution simple.

The example below shows how Fastlane can be configured to automatically build, sign and upload an iOS binary. Pilot has lots of customization options to help deliver apps to TestFlight, so it is highly recommended to check out the pilot documentation for further information.

# fastlane/Fastfile
default_platform :ios

platform :ios do
  before_all do
    setup_circle_ci
  end

  desc "Upload to Testflight"
  lane :upload_testflight do
    # Get the version number from the project and check against
    # the latest build already available on TestFlight, then
    # increase the build number by 1. If no build is available
    # for that version, then start at 1
    increment_build_number(
      build_number: latest_testflight_build_number(
        initial_build_number: 1,
        version: get_version_number(xcodeproj: "HelloWorld.xcodeproj")
      ) + 1,
    )
    # Set up Distribution code signing and build the app
    match(type: "appstore")
    gym(scheme: "HelloWorld")
    # Upload the binary to TestFlight and automatically publish
    # to the configured beta testing group
    app_store_connect_api_key
    pilot(
      distribute_external: true,
      notify_external_testers: true,
      groups: ["HelloWorld Beta Testers"],
      changelog: "This is another new build from CircleCI!"
    )
  end
end

Deploy to Firebase

Firebase is a distribution service from Google. Deploying to Firebase is simplified by installing the Firebase app distribution plugin.

1. Fastlane Plugin Setup

To set up the plugin for your project, on your local machine, open your project directory in Terminal and run the following command:

fastlane add_plugin firebase_app_distribution

This will install the plugin and add the required information to fastlane/Pluginfile and your Gemfile.

2. Generate a CLI Token

Firebase requires a token to used during authentication. To generate the token, we need to use the Firebase CLI and a browser - as CircleCI is a headless environment, we will need to generate this token locally, rather than at runtime, then add it to CircleCI as an environment variable.

  1. Download and install the Firebase CLI locally with the command curl -sL https://firebase.tools | bash.
  2. Trigger a login by using the command firebase login:ci.
  3. Complete the sign in via the browser window, then copy the token provided in the Terminal output.
  4. Go to your project settings in CircleCI and create a new environment variable named FIREBASE_TOKEN with the value of the token.

3. Fastlane configuration

The Firebase plugin requires minimal configuration to upload an iOS binary to Firebase. The main parameter is app which will require the App ID set by Firebase. To find this, go to your project in the Firebase Console, then go to Project Settings -> General. Under Your apps, you will see the list of apps that are part of the project and their information, including the App ID (generally in the format of 1:123456789012:ios:abcd1234abcd1234567890).

For more configuration options, see the Firebase Fastlane plugin documentation.

# Fastlane/fastfile
default_platform :ios

platform :ios do
  before_all do
    setup_circle_ci
  end

  desc "Upload to Firebase"
  lane :upload_firebase do
    increment_build_number(
      build_number: "$CIRCLE_BUILD_NUM"
    )
    match(type: "adhoc")
    gym(scheme: "HelloWorld")
    firebase_app_distribution(
      app: "1:123456789012:ios:abcd1234abcd1234567890",
      release_notes: "This is a test release!"
    )
  end
end

To use the Firebase Fastlane plugin, the Firebase CLI must be installed as part of the job via the curl -sL https://firebase.tools | bash command:

version: 2.1
jobs:
  adhoc:
    macos:
      xcode: "12.5.1"
    environment:
      FL_OUTPUT_DIR: output
    steps:
      - checkout
      - run: echo 'chruby ruby-2.6' >> ~/.bash_profile
      - run: bundle install
      - run: curl -sL https://firebase.tools | bash
      - run: bundle exec fastlane upload_firebase

workflows:
  adhoc-build:
    jobs:
      - adhoc

Note: The Firebase plugin may cause errors when run with the macOS system Ruby. It is therefore advisable to switch to a different Ruby version.

Deploy to Visual Studio App Center

Visual Studio App Center (formally HockeyApp), is a distribution service from Microsoft. App Center integration with Fastlane is enabled by installing the App Center plugin.

1. Fastlane Plugin Setup

To set up the plugin for your project, on your local machine open your project directory in Terminal and run the following command:

fastlane add_plugin appcenter

This will install the plugin and add the required information to fastlane/Pluginfile and your Gemfile.

Note: It is important that both of these files are checked into your git repo so that this plugin can be installed by CircleCI during the job execution via a bundle install step.

2. App Center setup

First, the app needs to be created in VS App Center.

  1. Log in, or sign up, to Visual Studio App Center.
  2. At the top-right of the page, click on “Add New”, then select “Add New App”.
  3. Fill out the required information in the form as required.

Once this is complete you will need to generate an API token to allow Fastlane to upload to App Center.

  1. Go to the API Tokens section in Settings.
  2. Click on “New API Token”.
  3. Enter a description for the token, then set the access to “Full Access”.
  4. When the token is generated, make sure to copy it somewhere safe.
  5. Go to your project settings in CircleCI and create a new environment variable named VS_API_TOKEN with the value of the API Key.

3. Fastlane configuration

Below is an example of a lane that distributes beta app builds to Visual Studio App Center. Both the username of your App Center account and an API Token with “Full Access” is required to upload the binary to App Center.

# Fastlane/fastfile
default_platform :ios

platform :ios do
  before_all do
    setup_circle_ci
  end

desc "Upload to VS App Center"
  lane :upload_appcenter do
    # Here we are using the CircleCI job number
    # for the build number
    increment_build_number(
      build_number: "$CIRCLE_BUILD_NUM"
    )
    # Set up Adhoc code signing and build  the app
    match(type: "adhoc")
    gym(scheme: "HelloWorld")
    # Set up the required information to upload the
    # app binary to VS App Center
    appcenter_upload(
      api_token: ENV[VS_API_TOKEN],
      owner_name: "YOUR_VS_APPCENTER_USERNAME",
      owner_type: "user",
      app_name: "HelloWorld"
    )
  end
end

Upload to TestFairy

TestFairy is another popular Enterprise App distribution and testing service. Fastlane has built-in support for TestFairy, making it quick and easy to upload new builds to the service.

TestFairy preferences image

  1. On the TestFairy dashboard, navigate to the Preferences page.
  2. On the Preferences page, go to the API Key section and copy your API Key.
  3. Go to your project settings in CircleCI and create a new environment variable named TESTFAIRY_API_KEY with the value of the API Key

Fastlane configuration

To configure uploading to TestFairy within Fastlane, see the following example:

# Fastlane/fastfile
default_platform :ios

platform :ios do
  before_all do
    setup_circle_ci
  end

desc "Upload to TestFairy"
  lane :upload_testfairy do
    # Here we are using the CircleCI job number
    # for the build number
    increment_build_number(
      build_number: "$CIRCLE_BUILD_NUM"
    )
    # Set up Adhoc code signing and build  the app
    match(type: "adhoc")
    gym(scheme: "HelloWorld")
    # Set up the required information to upload the
    # app binary to VS App Center
    testfairy(
      api_key: ENV[TESTFAIRY_API_KEY],
      ipa: 'path/to/ipafile.ipa',
      comment: ENV[CIRCLE_BUILD_URL]
    )
  end
end

Suggest an edit to this page

Make a contribution
Learn how to contribute