testflight
Alias for the upload_to_testflight
action
The best way to manage your TestFlight testers and builds from your terminal
pilot makes it easier to manage your app on Apple’s TestFlight. You can:
- Upload & distribute builds
- Add & remove testers
- Retrieve information about testers & devices
- Import/export all available testers
pilot uses spaceship.airforce to interact with App Store Connect 🚀
pilot is part of fastlane: The easiest way to automate beta deployments and releases for your iOS and Android apps.
Usage
For all commands, you can either use an API Key or your Apple ID.
App Store Connect API Key
The App Store Connect API Key is the preferred authentication method (if you are able to use it).
- Uses official App Store Connect API
- No need for 2FA
- Better performance over Apple ID
Specify the API key using --api_key_path ./path/to/api_key_info.json
or --api_key "{\"key_id\": \"D83848D23\", \"issuer_id\": \"227b0bbf-ada8-458c-9d62-3d8022b7d07f\", \"key_filepath\": \"D83848D23.p8\"}"
Go to Using App Store Connect API for information on obtaining an API key, the fastlane api_key_info.json
format, and other API key usage.
Apple ID
Specify the Apple ID to use using -u felix@krausefx.com
. If you execute pilot in a project already using fastlane the username and app identifier will automatically be determined.
Uploading builds
To upload a new build, just run
fastlane pilot upload
This will automatically look for an ipa
in your current directory and tries to fetch the login credentials from your fastlane setup.
You'll be asked for any missing information. Additionally, you can pass all kinds of parameters:
fastlane action pilot
You can pass a changelog using
fastlane pilot upload --changelog "Something that is new here"
You can also skip the submission of the binary, which means, the ipa
file will only be uploaded and not distributed to testers:
fastlane pilot upload --skip_submission
pilot does all kinds of magic for you:
- Automatically detects the bundle identifier from your
ipa
file - Automatically fetch the AppID of your app based on the bundle identifier
pilot uses spaceship to submit the build metadata and the iTunes Transporter to upload the binary. Because iTunes Transporter's upload capability is only supported on OS X, pilot upload
does not work on Linux, as described in this issue
List builds
To list all builds for specific application use
fastlane pilot builds
The result lists all active builds and processing builds:
+-----------+---------+----------+
| Great App Builds |
+-----------+---------+----------+
| Version # | Build # | Installs |
+-----------+---------+----------+
| 0.9.13 | 1 | 0 |
| 0.9.13 | 2 | 0 |
| 0.9.20 | 3 | 0 |
| 0.9.20 | 4 | 3 |
+-----------+---------+----------+
Managing beta testers
List of Testers
This command will list all your testers, both internal and external.
fastlane pilot list
The output will look like this:
+--------+--------+--------------------------+-----------+
| Internal Testers |
+--------+--------+--------------------------+-----------+
| First | Last | Email | # Devices |
+--------+--------+--------------------------+-----------+
| Felix | Krause | felix@krausefx.com | 2 |
+--------+--------+--------------------------+-----------+
+-----------+---------+----------------------------+-----------+
| External Testers |
+-----------+---------+----------------------------+-----------+
| First | Last | Email | # Devices |
+-----------+---------+----------------------------+-----------+
| Max | Manfred | email@email.com | 0 |
| Detlef | Müller | detlef@krausefx.com | 1 |
+-----------+---------+----------------------------+-----------+
Add a new tester
To add a new tester to your App Store Connect account and to associate it to at least one testing group of your app, use the pilot add
command. This will create a new tester (if necessary) or add an existing tester to the app to test.
fastlane pilot add email@invite.com -g group-1,group-2
Additionally you can specify the app identifier (if necessary):
fastlane pilot add email@email.com -a com.krausefx.app -g group-1,group-2
Find a tester
To find a specific tester use
fastlane pilot find felix@krausefx.com
The resulting output will look like this:
+---------------------+---------------------+
| felix@krausefx.com |
+---------------------+---------------------+
| First name | Felix |
| Last name | Krause |
| Email | felix@krausefx.com |
| Latest Version | 0.9.14 (23 |
| Latest Install Date | 03/28/15 19:00 |
| 2 Devices | • iPhone 6, iOS 8.3 |
| | • iPhone 5, iOS 7.0 |
+---------------------+---------------------+
Remove a tester
This command will remove beta tester from app (from all internal and external groups)
fastlane pilot remove felix@krausefx.com
You can also use groups
option to remove the tester from the groups specified:
fastlane pilot remove felix@krausefx.com -g group-1,group-2
Export testers
To export all external testers to a CSV file. Useful if you need to import tester info to another system or a new account.
fastlane pilot export
Import testers
Add external testers from a CSV file. Create a file (ex: testers.csv
) and fill it with the following format:
John,Appleseed,appleseed_john@mac.com,group-1;group-2
fastlane pilot import
You can also specify the directory using
fastlane pilot export -c ~/Desktop/testers.csv
fastlane pilot import -c ~/Desktop/testers.csv
Tips
Debug information
If you run into any issues you can use the verbose
mode to get a more detailed output:
fastlane pilot upload --verbose
Firewall Issues
pilot uses the iTunes Transporter to upload metadata and binaries. In case you are behind a firewall, you can specify a different transporter protocol from the command line using
DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS="-t DAV" pilot ...
If you are using pilot via the fastlane action, add the following to your Fastfile
ENV["DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS"] = "-t DAV"
pilot...
Note, however, that Apple recommends you don’t specify the -t transport
and instead allow Transporter to use automatic transport discovery to determine the best transport mode for your packages. For this reason, if the t
option is passed, we will raise a warning.
Also note that -t
is not the only additional parameter that can be used. The string specified in the DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS
environment variable will be forwarded to Transporter. For all the available options, check Apple's Transporter User Guide.
Credentials Issues
If your password contains special characters, pilot may throw a confusing error saying your "Your Apple ID or password was entered incorrectly". The easiest way to fix this error is to change your password to something that does not contains special characters.
How is my password stored?
pilot uses the CredentialsManager from fastlane.
Provider Short Name
If you are on multiple App Store Connect teams, iTunes Transporter may need a provider short name to know where to upload your binary. pilot will try to use the long name of the selected team to detect the provider short name. To override the detected value with an explicit one, use the itc_provider
option.
Use an Application Specific Password to upload
pilot/upload_to_testflight
can use an Application Specific Password via the FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD
environment variable to upload a binary if both the skip_waiting_for_build_processing
and apple_id
options are set. (If any of those are not set, it will use the normal Apple login process that might require 2FA authentication.)
Role for App Store Connect User
pilot/upload_to_testflight
updates build information and testers after the build has finished processing. App Store Connect requires the "App Manager" or "Admin" role for your Apple account to update this information. The "Developer" role will allow builds to be uploaded but will not allow updating of build information and testers.
testflight | |
---|---|
Supported platforms | ios, mac |
Author | @KrauseFx |
7 Examples
upload_to_testflight
testflight # alias for "upload_to_testflight"
pilot # alias for "upload_to_testflight"
upload_to_testflight(skip_submission: true) # to only upload the build
upload_to_testflight(
username: "felix@krausefx.com",
app_identifier: "com.krausefx.app",
itc_provider: "abcde12345" # pass a specific value to the iTMSTransporter -itc_provider option
)
upload_to_testflight(
beta_app_feedback_email: "email@email.com",
beta_app_description: "This is a description of my app",
demo_account_required: true,
notify_external_testers: false,
changelog: "This is my changelog of things that have changed in a log"
)
upload_to_testflight(
beta_app_review_info: {
contact_email: "email@email.com",
contact_first_name: "Connect",
contact_last_name: "API",
contact_phone: "5558675309",
demo_account_name: "demo@email.com",
demo_account_password: "connectapi",
notes: "this is review note for the reviewer <3 thank you for reviewing"
},
localized_app_info: {
"default": {
feedback_email: "default@email.com",
marketing_url: "https://example.com/marketing-default",
privacy_policy_url: "https://example.com/privacy-default",
description: "Default description",
},
"en-GB": {
feedback_email: "en-gb@email.com",
marketing_url: "https://example.com/marketing-en-gb",
privacy_policy_url: "https://example.com/privacy-en-gb",
description: "en-gb description",
}
},
localized_build_info: {
"default": {
whats_new: "Default changelog",
},
"en-GB": {
whats_new: "en-gb changelog",
}
}
)
Parameters
Key | Description | Default |
---|---|---|
api_key_path |
Path to your App Store Connect API Key JSON file (https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-json-file) | |
api_key |
Your App Store Connect API Key information (https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-hash-option) | |
username |
Your Apple ID Username | * |
app_identifier |
The bundle identifier of the app to upload or manage testers (optional) | * |
app_platform |
The platform to use (optional) | |
apple_id |
Apple ID property in the App Information section in App Store Connect | * |
ipa |
Path to the ipa file to upload | * |
pkg |
Path to your pkg file | * |
demo_account_required |
Do you need a demo account when Apple does review? | |
beta_app_review_info |
Beta app review information for contact info and demo account | |
localized_app_info |
Localized beta app test info for description, feedback email, marketing url, and privacy policy | |
beta_app_description |
Provide the 'Beta App Description' when uploading a new build | |
beta_app_feedback_email |
Provide the beta app email when uploading a new build | |
localized_build_info |
Localized beta app test info for what's new | |
changelog |
Provide the 'What to Test' text when uploading a new build | |
skip_submission |
Skip the distributing action of pilot and only upload the ipa file | false |
skip_waiting_for_build_processing |
If set to true, the distribute_external option won't work and no build will be distributed to testers. (You might want to use this option if you are using this action on CI and have to pay for 'minutes used' on your CI plan). If set to true and a changelog is provided, it will partially wait for the build to appear on AppStore Connect so the changelog can be set, and skip the remaining processing steps |
false |
update_build_info_on_upload |
DEPRECATED! Update build info immediately after validation. This is deprecated and will be removed in a future release. App Store Connect no longer supports setting build info until after build processing has completed, which is when build info is updated by default | false |
distribute_only |
Distribute a previously uploaded build (equivalent to the fastlane pilot distribute command) |
false |
uses_non_exempt_encryption |
Provide the 'Uses Non-Exempt Encryption' for export compliance. This is used if there is 'ITSAppUsesNonExemptEncryption' is not set in the Info.plist | false |
distribute_external |
Should the build be distributed to external testers? If set to true, use of groups option is required |
false |
notify_external_testers |
Should notify external testers? (Not setting a value will use App Store Connect's default which is to notify) | |
app_version |
The version number of the application build to distribute. If the version number is not specified, then the most recent build uploaded to TestFlight will be distributed. If specified, the most recent build for the version number will be distributed | |
build_number |
The build number of the application build to distribute. If the build number is not specified, the most recent build is distributed | |
expire_previous_builds |
Should expire previous builds? | false |
first_name |
The tester's first name | |
last_name |
The tester's last name | |
email |
The tester's email | |
testers_file_path |
Path to a CSV file of testers | ./testers.csv |
groups |
Associate tester to one group or more by group name / group id. E.g. -g "Team 1","Team 2" This is required when distribute_external option is set to true or when we want to add a tester to one or more external testing groups |
|
team_id |
The ID of your App Store Connect team if you're in multiple teams | * |
team_name |
The name of your App Store Connect team if you're in multiple teams | * |
dev_portal_team_id |
The short ID of your team in the developer portal, if you're in multiple teams. Different from your iTC team ID! | * |
itc_provider |
The provider short name to be used with the iTMSTransporter to identify your team. This value will override the automatically detected provider short name. To get provider short name run pathToXcode.app/Contents/Applications/Application\ Loader.app/Contents/itms/bin/iTMSTransporter -m provider -u 'USERNAME' -p 'PASSWORD' -account_type itunes_connect -v off . The short names of providers should be listed in the second column |
|
wait_processing_interval |
Interval in seconds to wait for App Store Connect processing | 30 |
wait_processing_timeout_duration |
Timeout duration in seconds to wait for App Store Connect processing. If set, after exceeding timeout duration, this will force stop to wait for App Store Connect processing and exit with exception |
|
wait_for_uploaded_build |
DEPRECATED! No longer needed with the transition over to the App Store Connect API - Use version info from uploaded ipa file to determine what build to use for distribution. If set to false, latest processing or any latest build will be used | false |
reject_build_waiting_for_review |
Expire previous if it's 'waiting for review' | false |
submit_beta_review |
Send the build for a beta review | true |
* = default value is dependent on the user's system
Documentation
To show the documentation in your terminal, run
fastlane action testflight
CLI
It is recommended to add the above action into your Fastfile
, however sometimes you might want to run one-offs. To do so, you can run the following command from your terminal
fastlane run testflight
To pass parameters, make use of the :
symbol, for example
fastlane run testflight parameter1:"value1" parameter2:"value2"
It's important to note that the CLI supports primitive types like integers, floats, booleans, and strings. Arrays can be passed as a comma delimited string (e.g. param:"1,2,3"
). Hashes are not currently supported.
It is recommended to add all fastlane actions you use to your Fastfile
.
Source code
This action, just like the rest of fastlane, is fully open source, view the source code on GitHub