You can distribute builds to testers using
[fastlane](https://fastlane.tools/), an open source platform that
automates building and releasing iOS and Android apps. This guide follows
instructions defined in a `Fastfile`. After you set up fastlane and your
`Fastfile`, you can integrate App Distribution with your fastlane
configuration.

## Before you begin

1. If you haven't already, [add Firebase to your Apple
   project](https://firebase.google.com/docs/ios/setup).

   If you aren't using any other Firebase products, you only have to create a
   project and register your app. However, if you decide to use additional
   products in the future, be sure to complete all of the steps on the page
   linked above.
2. Open the [App Distribution page](https://console.firebase.google.com/project/_/appdistribution) of the
   Firebase console. Select your Firebase project when prompted, select
   your app using the app switcher, and click **Get started**.

## Step 1. Set up fastlane

1. [Install and set up fastlane](https://docs.fastlane.tools/getting-started/ios/setup/).

2. To add App Distribution to your fastlane configuration, run the following
   command from the root of your iOS project:

   ```
   fastlane add_plugin firebase_app_distribution
   ```

   If the command prompts you with an option, select `Option 3: RubyGems.org`.

## Step 2. Authenticate with Firebase

Before you can use the fastlane plugin, you must first authenticate with your
Firebase project in one of the following ways. By default, the fastlane plugin
looks for credentials from the Firebase CLI if no other authentication
method is used.

<br />

### Use Firebase service account credentials

<br />

Authenticating with a service account allows you to flexibly use the plugin with
your continuous integration (CI) system. There are two ways to provide service
account credentials:

- Pass your service account key file to the `firebase_app_distribution` action. You might find this method convenient if you already have your service account key file in your build environment.
- Set the environment variable `GOOGLE_APPLICATION_CREDENTIALS` to point to your service account key file. You might prefer this method if you already have [Application Default Credentials (ADC)](https://cloud.google.com/docs/authentication/application-default-credentials) configured for another Google service (e.g., Google Cloud).

1. On the [Google Cloud console,](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts) select your project and create a new service account.
2. Add the **Firebase App Distribution Admin** role.
3. Create a private json key and move the key to a location accessible to your build environment. *Be sure to keep this file somewhere safe* , as it grants administrator access to App Distribution in your Firebase project.
4. Skip this step if you created your app after September 20, 2019: In the Google APIs console, enable the [Firebase App Distribution API.](https://console.developers.google.com/apis/api/firebaseappdistribution.googleapis.com/overview?project=_) When prompted, select the project with the same name as your Firebase project.
5. Provide or locate your service account credentials:

   1. To pass your service account key to your lane's `firebase_app_distribution` action, set the `service_credentials_file` parameter with the path to your private key JSON file
   2. To locate your credentials with ADC, set the environment variable
      `GOOGLE_APPLICATION_CREDENTIALS` to the path for the private key JSON
      file. For example:

      ```
       export GOOGLE_APPLICATION_CREDENTIALS=/absolute/path/to/credentials/file.json
      ```

      <br />

      For more information on authenticating with ADC, read [Providing credentials to your
      application.](https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application)

<br />

<br />

<br />

### Sign in using the Firebase CLI

<br />

See [Log in with the Firebase CLI](https://firebase.google.com/docs/cli.md.txt#sign-in-test-cli)
for instructions on how to authenticate your project.

<br />

<br />

## Step 3. Set up your Fastfile and distribute your app

1. In a `./fastlane/Fastfile` lane, add a `firebase_app_distribution` block. Use the following parameters to configure the distribution:

   | firebase_app_distribution parameters ||
   |---|---|
   | `app` | **Required only if your app does not contain a Firebase config file (`GoogleService-Info.plist`)** : Your app's Firebase App ID. You can find the App ID in the Firebase console, on the [General Settings page](https://console.firebase.google.com/project/_/settings/general/). ``` app: "1:1234567890:ios:0a1b2c3d4e5f67890" ``` |
   | `googleservice_info_plist_path` | The path to your `GoogleService-Info.plist` file, relative to the archived product path. Set to `GoogleService-Info.plist` by default. The file is used to get your app's Firebase App ID if the `app` parameter is unspecified. |
   | `firebase_cli_token` | A refresh token that's printed when you authenticate your CI environment with the Firebase CLI (read [Use the CLI with CI systems](https://firebase.google.com/docs/cli.md.txt#cli-ci-systems) for more information). |
   | `service_credentials_file` | The path to your Google service account json file. See above for how to [authenticate using service account credentials](https://firebase.google.com/docs/app-distribution/ios/distribute-fastlane.md.txt#service-acc-fastlane). |
   | `ipa_path` | Replaces `apk_path` (deprecated). Absolute path to the IPA file you want to upload. If unspecified, fastlane determines the file's location from the lane in which the file was generated. |
   | `release_notes` `release_notes_file` | Release notes for this build. You can either specify the release notes directly: ``` release_notes: "Text of release notes" ``` Or, specify the path to a plain text file: ``` release_notes_file: "/path/to/release-notes.txt" ``` |
   | `testers` `testers_file` | The email addresses of the testers you want to invite. You can specify the testers as a comma-separated list of email addresses: ``` testers: "ali@example.com, bri@example.com, cal@example.com" ``` Or, you can specify the path to a plain text file containing a comma-separated list of email addresses: ``` testers_file: "/path/to/testers.txt" ``` |
   | `groups` `groups_file` | The tester groups you want to invite (refer to [Manage testers](https://firebase.google.com/docs/app-distribution/manage-testers)). Groups are specified using group aliases, which you can look up in the Firebase console. You can specify the groups as a comma-separated list: ``` groups: "qa-team, trusted-testers" ``` Or, you can specify the path to a plain text file containing a comma-separated list of group names: ``` groups_file: "/path/to/groups.txt" ``` |
   | `test_devices` `test_devices_file` | The test devices you want to run [App Testing agent](https://firebase.google.com/docs/app-distribution/app-testing-agent) tests on. You can specify the test devices as a semicolon-separated list of device specifications: ``` test_devices: "model=shiba,version=34,locale=en,orientation=portrait" ``` Or, you can specify the path to a plain text file containing a semicolon-separated list of test devices: ``` test_devices_file: "/path/to/test-devices.txt" ``` |
   | `test_username` | The username for automatic login to be used during [App Testing agent](https://firebase.google.com/docs/app-distribution/app-testing-agent) tests. |
   | `test_password` `test_password_file` | The password for automatic login to be used during [App Testing agent](https://firebase.google.com/docs/app-distribution/app-testing-agent) tests. Or, you can specify the path to a plain text file containing a password: ``` test_password_file: "/path/to/test-password.txt" ``` |
   | `test_username_resource` | Resource name for the username field for automatic login to be used during [App Testing agent](https://firebase.google.com/docs/app-distribution/app-testing-agent) tests. |
   | `test_password_resource` | Resource name for the password field for automatic login to be used during [App Testing agent](https://firebase.google.com/docs/app-distribution/app-testing-agent) tests. |
   | `test_non_blocking` | If set when running [App Testing agent](https://firebase.google.com/docs/app-distribution/app-testing-agent) tests, the command will start the tests and then return immediately instead of waiting for them to complete. To see the test results, visit the Firebase console. If this flag is not set, the command will block until the tests are complete, and exit with a failure code if any of the tests fail. |
   | `debug` | A boolean flag. You can set this to `true` to print verbose debug output. |

For example:

```ruby
platform :ios do
    desc "My awesome app"
    lane :distribute do
        build_ios_app(...)
        # build_ios_app is a built-in fastlane action.

        release = firebase_app_distribution(
            app: "1:123456789:ios:abcd1234",
            testers: "tester1@company.com, tester2@company.com",
            release_notes: "Lots of amazing new features to test out!"
        )

    end
end
```

To make the build available to testers, run your lane:

```
fastlane <lane>
```

<br />

The return value of the action is a hash representing the uploaded release. This
hash is also available using
`lane_context[SharedValues::FIREBASE_APP_DISTRO_RELEASE]`. For more information
about the available fields in this hash, see the [REST API
documentation](https://firebase.google.com/docs/reference/app-distribution/rest/v1/projects.apps.releases#resource:-release).

The fastlane plugin outputs the following links after the release upload. These
links help you manage binaries and ensure that testers and other developers
have the right release:

- A link to the Firebase console displaying a single release. You can share this link with other developers in your org.
- A link to the release in the tester experience (iOS web clip) that lets testers view release notes and install the app onto their device. The tester needs access to the release in order to use the link.
- A signed link that directly downloads and installs the app binary (IPA file). The link expires after one hour.

After you distribute your build, it is available in the
App Distribution dashboard of the Firebase console for 150 days.
When the build is 30 days from expiring, an expiration notice appears in
the console and in the tester's list of builds on their test device.

Testers who weren't previously invited to test the app receive email
invitations to get started. Existing testers receive email notifications
that a new build is ready to test. To learn how to install the test
app, see [Get set up as a tester](https://firebase.google.com/docs/app-distribution/get-set-up-as-a-tester.md.txt?platform=ios).
You can monitor
the status of each tester to determine whether they accepted the
invitation and whether they downloaded the app in the
Firebase console.

> [!NOTE]
> **Note:** Testers have 30 days to accept an invitation to test the app before the invitation expires. When an invitation is 5 days from expiring, an expiration notice appears in the Firebase console next to the tester on a release. You can resend an invitation using the drop-down menu on the tester row.

(Optional) To automatically increment your build number every time you create
a new release in App Distribution, you can use the
`firebase_app_distribution_get_latest_release` action and the
[`increment_build_number` action](https://docs.fastlane.tools/actions/increment_build_number/).
The following code provides an example of how to automatically increment your
build number:

```ruby
lane :increment_version do
  latest_release = firebase_app_distribution_get_latest_release(
    app: "<your Firebase app ID>"
  )
  increment_build_number({ build_number: latest_release[:buildVersion].to_i + 1 })
end
```

To learn more about this fastlane plugin feature, see
[Get information about your app's latest release](https://firebase.google.com/docs/app-distribution/ios/distribute-fastlane.md.txt#get-latest-release).

## Step 4 (Optional). Manage testers for the distribution

You can add and remove testers from your project or group using your `Fastfile`
file or by directly running fastlane actions. Running actions directly
overrides the values set in your `Fastfile`.

Once a tester is added to your Firebase project, you can add them to
individual releases. Testers who are removed from your Firebase project no
longer have access to releases in your project, but they might retain access
to your releases for a window of time.

If you have a large number of testers you should consider using groups.

#### Use `Fastfile`

```
# Use lanes to add or remove testers from a project.
lane(:add_testers) do
  firebase_app_distribution_add_testers(
    emails: "foo@google.com,bar@google.com"
    # or file: "/path/to/testers.txt"
    group_alias: "qa-team" # (Optional) add testers to this group
  )
end

lane(:remove_testers) do
  firebase_app_distribution_remove_testers(
    emails: "foo@google.com,bar@google.com"
    # or file: "/path/to/testers.txt"
    group_alias: "qa-team" # (Optional) remove testers from this group only
  )
end
```

```
# Add or remove testers with the terminal
$ fastlane add_testers
$ fastlane remove_testers
```

#### Run fastlane actions

    fastlane run firebase_app_distribution_create_group display_name:"QA Team" alias:"qa-team"
    fastlane run firebase_app_distribution_add_testers group_alias:"qa-team" emails:"foo@google.com,bar@google.com"
    fastlane run firebase_app_distribution_remove_testers group_alias:"qa-team" emails:"foo@google.com,bar@google.com"
    fastlane run firebase_app_distribution_delete_group alias:"qa-team"

You can also specify testers using `--file="/path/to/testers.txt` instead of
`--emails`.

The `firebase_app_distribution_add_testers` and
`firebase_app_distribution_remove_testers` tasks also accept the following
arguments:

- `project_number`: Your Firebase project number.
- `group_alias` (optional): If specified, the testers are added to (or removed from) specified group.
- `service_credentials_file`: The path to your Google service credentials file.
- `firebase_cli_token`: Auth token for Firebase CLI.

The `service_credentials_file` and the `firebase_cli_token` are the same
arguments used by the upload action.

## Step 5 (Optional). Get information about your app's latest release

You can use the `firebase_app_distribution_get_latest_release` action
to fetch information about your app's latest release in App Distribution,
including app version information, release notes, and creation time. Use cases
include automatically increasing the version and carrying over the release
notes from the previous release.

The return value of the action is a hash representing the latest release. This
hash is also available using
`lane_context[SharedValues::FIREBASE_APP_DISTRO_LATEST_RELEASE]`. For more
information about the available fields in this hash, see the [REST API
documentation](https://firebase.google.com/docs/reference/app-distribution/rest/v1/projects.apps.releases#resource:-release).

### Parameters

| firebase_app_distribution_get_latest_release parameters ||
|---|---|
| `app` | **Required only if your app does not contain a Firebase config file (`GoogleService-Info.plist`)** : Your app's Firebase App ID. You can find the App ID in the Firebase console, on the [General Settings page](https://console.firebase.google.com/project/_/settings/general/). ``` app: "1:1234567890:ios:0a1b2c3d4e5f67890" ``` |
| `googleservice_info_plist_path` | The path to your `GoogleService-Info.plist` file, relative to the archived product path. Set to `GoogleService-Info.plist` by default. The file is used to get your app's Firebase App ID if the `app` parameter is unspecified. |
| `firebase_cli_token` | A refresh token that's printed when you authenticate your CI environment with the Firebase CLI (read [Use the CLI with CI systems](https://firebase.google.com/docs/cli.md.txt#cli-ci-systems) for more information). |
| `service_credentials_file` | The path to your Google service account json file. See earlier documentation for how to [authenticate using service account credentials](https://firebase.google.com/docs/app-distribution/ios/distribute-fastlane.md.txt#service-acc-fastlane). |
| `service_credentials_json_data` | Google service account json file content. See earlier documentation for how to [authenticate using service account credentials](https://firebase.google.com/docs/app-distribution/ios/distribute-fastlane.md.txt#service-acc-fastlane). |
| `debug` | A boolean flag. You can set this to `true` to print verbose debug output. |

## Next steps

- To register more devices manually or programmatically, see
  [Register additional iOS devices](https://firebase.google.com/docs/app-distribution/register-additional-devices.md.txt).

- Learn best practices for [distributing Apple apps to QA testers using CI/CD and fastlane](https://firebase.google.com/docs/app-distribution/best-practices-distributing-apple-apps-to-qa-testers-with-ci-cd-fastlane.md.txt).