1. Project Overview & Quickstart (buger/requirements-to-freeze.txt)
requirements-to-freeze.txt
Open-source repository buger/requirements-to-freeze.txt
Repository Details
- Repository: buger/requirements-to-freeze.txt
- Primary Language: Code
Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.
2. Official Technical Reference & Guides (buger/docs)
File: README.md
fastlane docs
This repo contains all documentation for fastlane. You can find the .md files inside the docs folder.
To preview the updated documentation locally, just clone the repo, modify the file, and run
mkdocs serveThe live version is available on docs.fastlane.tools.
Why new docs?
You can find more information here
Deploy changes
Once a PR is merged into master, the latest version will automatically be deployed to docs.fastlane.tools by one of the hard working fastlane bots. No need to do anything manually. The resulting HTML files are stored in the gh-pages branch.
Installation of [mkdocs](http://www.mkdocs.org/)
brew install python # if you don't have pip already
[sudo] pip install -r requirements.txtAdding a Python dependency
Likely, to add a Markdown extension.
- Install with
pip install <some extension> - Add
to requirements-to-freeze.txt. - Run
pip freeze > requirements.txtto update the exact requirements.
Why requirements-to-freeze.txt?
Based on A Better Pip Workflow,requirements-to-freeze.txt and requirements.txt provide a similar experience
to Gemfile and Gemfile.lock, respectively.
requirements-to-freeze.txt lets you pick out the top level packages the
project depends on, while requirements.txt exactly specifies all of the
dependencies and subdependencies for repeatable builds.
File: docs/best-practices/continuous-integration.md
Continuous Integration
Best Practices
Two-step or Two-factor auth
If you want to upload builds to TestFlight/iTunes Connect from your CI machine, you need to generate an application specific password:
- Visit appleid.apple.com/account/manage
- Generate a new application specific password
- Provide the application specific password using the environment variable
FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD
Because your CI machine will not be able to prompt you for your two-step or two-factor auth information, you also need to generate a login session for your CI machine in advance. You can get this by running:
fastlane spaceauth -u [email protected]This will generate a token you can set using the FASTLANE_SESSION environment variable on your CI system.
Deploy Strategy
You should not deploy a new App Store update after every commit, since you still have to wait 1-2 days for the review. Instead it is recommended that you use Git Tags, or custom triggers to deploy a new update.
You can set up your own Release job, which is only triggered manually.
Jenkins Integration
Deploying from your own computer isn't cool. You know what's cool? Letting a remote server publish app updates for you.
fastlane automatically generates a JUnit report for you. This allows Continuous Integration systems, like Jenkins, access the results of your deployment.
Installation
The recommended way to install Jenkins is through homebrew:
brew update && brew install jenkinsFrom now on start Jenkins by running:
jenkinsTo store the password in the Keychain of your remote machine, it is recommended that you run match or deliver using ssh or remote desktop at least once.
Plugins
You'll find the following Jenkins plugins to be useful:
- HTML Publisher Plugin: Can be used to show the generated screenshots right inside Jenkins.
- AnsiColor Plugin: Used to show the coloured output of the fastlane tools. Donโt forget to enable
Color ANSI Console Outputin theBuild Environmentor your project. - Rebuild Plugin: This plugin will save you a lot of time.
- Keychains and Provisioning Profiles Plugin: Manages keychains across Jenkins installations.
Build Step
Use the following as your build step:
fastlane appstoreReplace appstore with the lane you want to use.
setup_jenkins
You can use setup_jenkins action which integrates well with the Keychains and Provisioning Profiles Plugin. Selected keychain will automatically unlocked and the selected code signing identity will be used. Also all build results, like IPA files, archives, dSYMs and result bundles will be stored in the ./output folder in the job workspace. In additions setup_jenkins will create separate derived data folder for each job (in the ./derivedData).
Under the hood setup_jenkins configures other actions like: gym, scan, xcodebuild, backup_xcarchive and clear_derived_data.
commit_version_bump || git_commit
You can use commit_version_bump or git_commit action to commit changes to your repository in your fastlane setup. When you are using webhooks to trigger your build on a push this will cause an infinite loop of triggering builds.
Gitlab
When you are using Gitlab you will need the GitLab Plugin. Inside the job you want to configure you go to Build Triggers > Build when a change is pushed to GitLab > Enable [ci-skip].
When you include [ci-skip] in your build this commit won't trigger the build in jenkins at all.
Example
build_number = increment_build_number
commit_version_bump(message:"[ci-skip] Version Bump to #{build_number}")
git_commit(path:"./CHANGELOG.md", message:"[ci-skip] Updated CHANGELOG for Build #{build_number}")
push_to_git_remoteTest Results and Screenshots
To show the deployment result right in Jenkins
- Add post-build action
- Publish JUnit test result report
- Test report XMLs:
fastlane/report.xml
To show the generated screenshots right in Jenkins
- Add post-build action
- Publish HTML reports
- HTML directory to archive:
fastlane/screenshots - Index page:
screenshots.html
Save and run. The result should look like this:
Circle Integration
To run fastlane on Circle as your CI, first create a Gemfile in the root of your project with the following content
source "https://rubygems.org"
gem "fastlane"and run
gem install bundler && bundle updateThis will create a Gemfile.lock, that defines all Ruby dependencies. Make sure to commit both files to version control.
Next, use the following circle.yml file
machine:
xcode:
version: "7.3"
dependencies:
override:
- bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3 --without development
cache_directories:
- vendor/bundle
test:
override:
- bundle exec fastlane testThis will automatically cache the installed gems on Circle, making your CI builds much faster!
Bamboo Integration
Repository setup
In bamboo under Linked Repositories (where you configure your git repo) under Advanced Settings is an option called Exclude changesets
This dialog will allow you to enter a regular expression that if a commit matches, a build will not be triggered.
For example, if your Fastfile is configured to make a commit message in the style of
Build Version bump by fastlane to Version [0.3] Build [8]Then you could use the following regex to ignore these commits
^.*Build Version bump by fastlane.*$Setting repository remote
By default bamboo will do an anonymous shallow clone of the repo. This will not preserve the git remote information nor the list of tags. If you are using bamboo to create commits you may want to use a code block similar to the following:
# In prep for eventually committing a version/build bump - set the git params
sh('git config user.name "<COMMITTER USERNAME>"')
sh('git config user.email <COMITTER EMAIL>')
# Bamboo does an anonymous checkout so in order to update the build versions must set the git repo URL
git_remote_cmd = 'git remote set-url origin ' + ENV['bamboo_repository_git_repositoryUrl']
sh(git_remote_cmd)Speeding up build times with carthage
Carthage is a wonderful dependency manager but once you are start using a large number of frameworks, things can start to slow down, especially if your CI server has to run carthage EVERY time you check in a small line of code.
One way to make build times faster is to break your work up into two separate build plans (this can get even more funky if you start having multiple branches)
The general idea is to make a build plan: Project - Artifacts that builds the Carthage directory and stores it as a shared artifact. Then you create a second build plan Project - Fastlane that pulls down the Carthage directory and runs fastlane.
Artifact Plan
Use a simple setup to create this build plan. First off you want to make sure this plan is manually triggered only - because you only need to run it whenever the Cartfile changes as opposed to after ever single commit. It could also be on a nightly build perhaps if you desire.
Stages / Jobs / Tasks
This plan consists of 1 Job, 1 Stage and 2 Tasks
- Task 1: Source Code Checkout
- Task 2: Script (
carthage update)
Artifact definitions
Create a shared artifact with the following info:
- Name: CarthageFolder
- Location: (leave blank)
- Copy Pattern: Carthage/Build/**
Optional: You may want to automatically make the fastlane plan trigger whenever this plan is built
_fastlane_ plan
When configuring fastlane to run in this setup you need to make sure that you are not calling either:
reset_git_repo(force: true)or
ensure_git_status_cleanas these calls will either fail the build or delete the Carthage directory. Additionally you want to remove any carthage tasks from inside your Fastfile as carthage is now happening externally to the build.
Build plan setup
What this build plan does is it checks out the source code, then it downloads the entire Carthage/Build/ directory into your local project - which is exactly what would be created from carthage bootstrap and then it runs fastlane
- Task 1: Source Code Checkout
- Task 2: Artifact Download
- Task 3: fastlane
GitLab CI Integration
Use GitLab CI Runner running on a macOS machine
to build using fastlane.
Repository setup
First create a Gemfile in the root of your project with the following content:
source "https://rubygems.org"
gem "fastlane"Add a .gitlab-ci.yml file to trigger fastlane.
stages:
- unit_tests
- test_flight
variables:
LC_ALL: "en_US.UTF-8"
LANG: "en_US.UTF-8"
before_script:
- gem install bundler
- bundle install
unit_tests:
dependencies: []
stage: unit_tests
artifacts:
paths:
- fastlane/screenshots
- fastlane/logs
script:
- fastlane tests
tags:
- ios
test_flight_build:
dependencies: []
stage: test_flight
artifacts:
paths:
- fastlane/screenshots
- fastlane/logs
script:
- fastlane beta
tags:
- ios
only:
- /^release-.*$/
- masterSee the ``.gitlab-ci.yml` documentation
for more information on how this file works.
Setting up the lanes
You should have a lane - in this example called beta - which should do the usual, match, gym, pilot, to distribute an updated Test Flight version, and one lane tests which calls scan to run UI Tests.
Auto-incremented build number.
To get an auto-incremented build number you can use something like the following lane:
lane :increment_build_number do
increment_build_number(build_number: ENV['CI_BUILD_ID'])
endThen the GitLab CI build ID (which iterates on each build) will be used.
File: docs/best-practices/keys.md
fastlane keys
This guide will show you the best ways to store and use your keys for services like Crashlytics, Slack, etc.
In your `Fastfile`
lane :beta do
crashlytics(api_token: "123abc", build_secret: "secret_key")
endor if you want to only define the keys once and use it multiple times
ENV["CRASHLYTICS_API_TOKEN"] = "123abc"
ENV["CRASHLYTICS_BUILD_SECRET"] = "secret_key"
lane :beta do
crashlytics
endThis is the most straight forward and easiest solution, but might cause a few issues:
- If you ever decide to open source your application you'll have to make sure to remove the keys from your git history
- If your keys got invalidated for whatever reason and you decide to rollback your code base to an earlier stage the keys will also be rolled back
To get the name of the available environment variables, run fastlane action [action_name].
Bash Profile
To not store your keys in git, you can pass all parameters of all actions using environment variables.
You can edit your ~/.bash_profile to include something like
export SLACK_URL="https://hooks.slack.com/services/T03NA19Q5/..."
export CRASHLYTICS_API_TOKEN="123abc"If you use a different shell (e.g. zshell) you'll need to edit ~/.zshrc instead.
After editing the .bash_profile you need to either re-open your terminal session or run source ~/.bash_profile.
Disadvantages
- Every terminal tool you run gets access to your environment variables.
- You have to edit your bash profile on every computer you want to run fastlane from
- The bash profile isn't automatically loaded by some CI-systems like Jenkins
To get the name of the available environment variables, run fastlane action [action_name].
[dotenv](https://github.com/bkeepers/dotenv)
dotenv is a system to store your environment in a file that is project specific. Basically you have a hidden file in your project containing all the environment variables for your project.
You can store a default configuration in .env.default which will be loaded by fastlane automatically.
SLACK_URL="https://hooks.slack.com/services/T03NA19Q5/..."
CRASHLYTICS_API_TOKEN="123abc"You might want different configurations depending on your environment.
fastlane beta --env developmentand store the configuration in .env.development with all keys for the development environment.
Install [sudo] gem install dotenv or add dotenv to your Gemfile. More information about the recommend way to install gems.
To get the name of the available environment variables, run fastlane action [action_name].
File: docs/best-practices/source-control.md
Source Control
It is recommended that you keep fastlane configuration files in the repository. You may want to add the following lines to the repository's .gitignore (Git) or .hgignore (Mercurial) file to exclude generated and temporary files:
# fastlane specific
fastlane/report.xml
# deliver temporary files
fastlane/Preview.html
# snapshot generated screenshots
fastlane/screenshots
# scan temporary files
fastlane/test_outputIt is also recommended that you avoid storing screenshots or other delivery artifacts in the repository. Instead, use fastlane to re-generate whenever needed.
File: docs/codesigning/common-issues.md
Common code signing issues
Xcode errors
Code Sign error: No matching provisioning profiles found: No provisioning profiles with a valid signing identity (i.e. certificate and private key pair) matching the bundle identifier "X" were found.
The provisioning profile for the given app identifier "X" is not available on the local machine. Make sure you have a valid provisioning profile for the correct distribution type (App Store, Development or Ad Hoc) on the Apple Developer Portal, download and install it, and select the profile in the Xcode settings (See Setting up your Xcode Project).
You might have the provisioning profile installed locally, but miss the private key or certificate for it.
No matching codesigning identity found: No codesigning identities (i.e. certificate and private key pairs) matching "iPhone Distribution: X" were found
The code signing identity you specified in the Xcode project can't be found in your local keychain. Make sure to transfer the certificate and private key from another Mac (or wherever you store the private key), or to update the project file to use the correct code signing identity.
Error Domain=IDEDistributionErrorDomain Code=1 "The operation couldnโt be completed. (IDEDistributionErrorDomain error 1.)"
This error can have a lot of reasons, some things you should try:
- Verify your Keychain is valid and you don't have an expired WWDR certificate using this guide
- Verify both your certificate and provisioning profile are valid in both your Keychain and on the Apple Developer Portal (Check out Debugging codesigning issues for more information)
- If you're using gym, try using the
use_legacy_build_apiflag to fallback to the Xcode 6 build API - Follow the other steps of Debugging codesigning issues
Provisioning profile does not match bundle identifier: The provisioning profile specified in your build settings ("X") has an AppID of "Y" which does not match your bundle identifier "Z"
Your project defines a provisioning profile that doesn't match the bundle identifier of your app. There is mismatch between the bundle identifiers, this might happen if you specify the wrong provisioning profile in your target.
Your build settings specify a provisioning profile with the UUID "X", however, no such provisioning profile was found.
Your project defines a provisioning profile which doesn't exist on your local machine. Check out Setting up your Xcode Project for more information how to properly specify a provisioning profile to avoid hard coded UUIDs in your project.
CodeSign Error: code signing is required for product type 'Application'...
Make sure to have a valid code signing identity defined in your project targets. This might happen when you select Don't Code Sign as Code Signing Identity.
fastlane errors
Could not find a matching code signing identity for type 'X'
There are no certificates available on the Apple Developer Portal. This could either mean someone revoked a certificate, or you don't have access to it.
File: docs/codesigning/getting-started.md
Codesigning concepts
If you are just starting a new project, it's important to think about how you want to handle code signing. This guide will help you choose the best approach for you.
For existing projects it might make sense to switch from a manual process to the match approach to make it easier for new team-members to onboard.
If you are new to code signing, check out the WWDC session that describes the fundamentals of code signing in Xcode.
Using [match](https://fastlane.tools/match)
The concept of match is described in the codesigning guide.
With match you store your private keys and certificates in a git repo to sync them across machines. This makes it easy to onboard new team-members and set up new Mac machines. This approach is secure and uses technology you already use.
Getting started with match requires you to revoke your existing certificates.
Make sure to follow Setting up your Xcode Project to set up your project properly.
Using [cert](https://fastlane.tools/cert) and [sigh](https://fastlane.tools/sigh)
If you don't want to revoke your existing certificates, but still want an automated setup, cert and sigh are for you.
- cert will make sure you have a valid certificate and its private key installed on the local machine
- sigh will make sure you have a valid provisioning profile installed locally, that matches the installed certificate
Add the following lines to your Fastfile
lane :beta do
cert
sigh
gym
endMake sure to follow Setting up your Xcode Project to set up your project properly.
Using Xcode's code signing feature
Occasionally the Automatic setting as the provisioning profile doesn't work reliably as it will just select the most recently updated provisioning profile, no matter if the certificate is installed.
That's why it is recommended to specify a specific provisioning profile somehow:
Xcode 7 and lower
You should avoid clicking the Fix Issue button (There is an Xcode plugin that disables the button), as it sometimes revokes existing certificates, and with it the provisioning profiles.
Unfortunately you can't specify the name of the provisioning profile in Xcode 7. Instead you can specify the UUID of the profile, which changes every time the profile gets re-generated (e.g. when you add a new device).
To work around this issue, check out Setting up your Xcode Project on how to pass a provisioning profile to Xcode when building your app.
Xcode 8 and up
Apple improved code signing a lot with the release of Xcode 8, the following has changed:
- No more
Fix Issuebutton, instead all code signing processes run in the background and show the log right in Xcode - You can now specify the provisioning profile by name, instead of the UUID (Check out Setting up your Xcode Project for more information)
- Improved error messages when something goes wrong. If you run into code signing errors you should always try building and signing with Xcode to get more detailed error information. (Check out Debugging codesigning issues for more information)
- Improved Automatic Provisioning that can create per-machine development private keys, certificates, and provisioning profiles. (Check out Setting up your Xcode Project for more information)
Manually
You can always manually create and manage your certificates and provisioning profiles using the Apple Developer Portal. Make sure to store the private key (.p12) of your certificates in a safe place, as they can't be restored if you lose them.
You can always download the certificate (.cer) and provisioning profile (.mobileprovision) from the Apple Developer Portal.
Where to go from here
- Setting up your Xcode Project
- Debugging codesigning issues
- Common code signing issues
- Upgrading to Xcode 8
File: docs/codesigning/troubleshooting.md
Debugging codesigning issues
This guide will help you resolve the most common code signing errors.
Error message
Make sure to find the exact error message in your build output. Many times the error message actually tells you how to resolve the issue.
To get even more details, try archiving using Xcode 8.
Different machine
Does code signing work on a different Mac, but not on yours? If so, chances are high you don't have the latest private key, the certificate or the provisioning profile. Also follow the Keychain part of this document to make sure you don't have any expired certificates installed.
Xcode project
Make sure to follow Setting up your Xcode Project to properly set up your project.
A check list on what you should verify on your Xcode project
- Make sure to have consistent code signing settings across your targets
- Don't set any code signing settings on your project level, just on the target level
- Make sure the bundle identifier matches the one of your provisioning profile
- Make sure the code signing identity is set to
iOS DistributionforReleasebuilds - Make sure to set a provisioning profile for all your targets, e.g. Watch, Today widget, ...
- Check your working copy in git - did you make any changes by mistake?
Developer Portal
If a certificate gets revoked, all connected provisioning profiles get invalidated. This however might not immediately show up in your local keychain.
- Open the Developer Portal
- Verify your certificates are valid, and didn't expire or get revoked
- Switch to the Provisioning Profiles and make sure the profiles you want to use are all still valid
- If your profile is invalid or expired, you can easily fix it:
- If you're using match, run match with
forceenabled
- If you're using sigh, run sigh with
forceenabled - If you're doing manual code signing, edit the provisioning profile, and click on
Generateon the bottom of the screen. Make sure to select the correct certificate, then download and open the new provisioning profile - If your profile is valid, but you still have issues make sure
- that the certificate matches the certificate you have installed locally. You can view the used certificate by editing the profile (Don't click
Generate, unless you want to re-generate the provisioning profile)
- that all devices you need are included (Development and Ad-Hoc only)
- that you are actually looking at the correct provisioning profile, that matches the bundle identifier of your app. You might have multiple provisioning profiles for the same app / certificate combination. By default Xcode will use the last modified one.
- that the certificate matches the certificate you have installed locally. You can view the used certificate by editing the profile (Don't click
Keychain
Run
security find-identity -v -p codesigningto get a list of locally installed code signing identities. Does yours show up?Open the
Keychain Accessapp, switch toCertificatesand find youriOS DeveloperoriOS Distributionentry and unfold the entry to verify the private key is locally installed:Make sure to have deleted all expired WWDR certificates, more information here. There might be 2 expired WWDR certificates, one in the
login, and one in thesystemkeychain
Have you tried turning it off and on again?
As funny as it sounds, sometimes restarting your Mac helps.
fastlane
Run fastlane in verbose mode to get even more debug information:
fastlane [lane] --verboseCommon Issues
Check out Common code signing issues for the most common code signing issues and how you can solve them.
File: docs/codesigning/xcode-project.md
Setting up your Xcode Project
Xcode 8 and up
With Xcode 8 you can set a provisioning profile name for each of your targets instead of a provisioning profile UUID. By doing so, Xcode automatically selects the latest provisioning profile matching its name. This way you don't have to update your Xcode project, every time you re-generate your provisioning profile (e.g. when adding a new device)
You can now specify which provisioning profile to use in the General tab after disabling Automatically manage signing.
Alternatively you can also specify the provisioning profile in the Build Settings tab.
If your provisioning profile is not listed in the drop down, there might be a few reasons:
- It doesn't match the bundle identifier of the target
- The associated certificate or its private key is not installed on the local machine
- The provisioning profile is not installed on the local machine
Check out Debugging codesigning issues for more information on how to debug signing issues.
Build settings
Previously you could specify the UUID of the provisioning profile using the PROVISIONING_PROFILE Xcode settings property, with Xcode 8 you specify it using the PROVISIONING_PROFILE_SPECIFIER instead:
DEVELOPMENT_TEAM = N8XAAASEU2;
PROVISIONING_PROFILE_SPECIFIER = "match AppStore me.themoji.app.release";It is recommended to select the provisioning profile in the General tab in your Xcode project, so Xcode will automatically set the values mentioned above for you.
Set using environment variable
You could pass the profile specifier via environment variables too (See Xcode 7 approach below), however in most cases it's enough to define it statically in your project, per target, since usually neither your Team ID, nor the provisioning profile change.
If you're using match the following environment variables are being set for you:
+---------------------+------------------------------------------------+--------------------------------------+
| Installed Provisioning Profile |
+---------------------+------------------------------------------------+--------------------------------------+
| Parameter | Environment Variable | Value |
+---------------------+------------------------------------------------+--------------------------------------+
| App Identifier | | me.themoji.release |
| Type | | appstore |
| Profile UUID | sigh_me.themoji.beta_appstore | 22a19b3a-7cf6-4997-95f2-9cbb4d33fe7e |
| Profile Name | sigh_me.themoji.beta_appstore_profile-name | match AppStore me.themoji.release |
| Development Team ID | sigh_me.themoji.beta_appstore_team-id | N8XAAASEU2 |
+---------------------+------------------------------------------------+--------------------------------------+Check out the Xcode 7 section on how to update build settings using environment variables.
Using `match development` or Xcode Automatic Provisioning
Apple's Automatic Provisioning in Xcode 8 will automatically generate a private key, development certificate, and managed development provisioning profile for each computer used to build a project. Since Xcode can auto-generate these for you, there is no need to share them between teammates' computers. As such, when using Xcode Automatic Provisioning, there is no need to use match development to keep development keys, certificates, and provisioning profiles in sync.
If you are already using match to manage development code signing, Automatic Provisioning will use the match-generated key and certificate. However, Xcode will create and manage its own provisioning profile and will not use the match-generated profile.
`match appstore` and Xcode Automatic Provisioning
Xcode Automatic Provisioning doesn't sync your private keys across machines (if you have multiple computers or share them between teammates). To securely store your private key and have access to it from all your devices, use match appstore or match adhoc. This will sync your keys, certificates and provisioning profiles via git, encrypted using OpenSSL.
Xcode 7 and lower
Note: This approach is deprecated with Xcode 8
If you use Automatic value for your provisioning profile, Xcode sometimes selects the wrong profile, resulting in code signing errors at a later point.
Instead it is recommended to specify a specific provisioning profile, which can only be done using the UUID (in Xcode 7).
Since it is not recommended to update the project file, every time you update your provisioning profile, you can pass the UUID via environment variables.
To do so, open your target settings, open the dropdown for Provisioning Profile and select Other:
Using the $(...) notation, Xcode will use the provisioning profile matching the UUID, and fallback to Automatic if it's not provided.
If you use fastlane you don't have to do any extra work, since the environment variable for the latest profile are automatically set by match
lane :beta do
match(type: "adhoc")
gym
endYou can also manually set the environment variable using
lane :beta do
ENV["PROVISIONING_PROFILE_TARGET1"] = "b01c39c9-1b4a-412e-9ae2-3087ee9ea9d3"
gym
endFile: docs/getting-started/ios/appstore-deployment.md
iOS App Store deployment using _fastlane_
Building your app
fastlane takes care of building your app using a feature called gym, just add the following to your Fastfile:
lane :appstore do
gym(scheme: "MyApp")
endAdditionally you can specify more options for building your app, for example
lane :appstore do
gym(scheme: "MyApp",
workspace: "Example.xcworkspace",
include_bitcode: true)
endTry running the lane using
fastlane appstoreIf everything works, you should have a [ProductName].ipa file in the current directory. To get a list of all available parameters for gym, run fastlane action gym.
Codesigning
Chances are that something went wrong because of code signing at the previous step. We prepared our own Code Signing Guide that helps you setting up the right code signing approach for your project.
Submitting your app
Generating screenshots
To find out more about how to automatically generate screenshots for the App Store, check out fastlane screenshots for iOS and tvOS.
Upload the binary and app metadata
After building your app, it's ready to be uploaded to the App Store. If you've already followed iOS Beta deployment using fastlane, the following code might look similar already.
lane :appstore do
snapshot # generate new screenshots for the App Store
match(type: "appstore") # see code signing guide for more information
gym(scheme: "MyApp") # build your app
appstore # upload your app to iTunes Connect
slack(message: "Successfully uploaded a new App Store build")
endfastlane automatically passes on information about the generated screenshots and the binary to the appstore action of your Fastfile.
For a list of all options for each of the steps run fastlane action [action_name].
Best Practices
Push Notifications
To make sure your latest push notification certificate is still valid during your submission process, add the following at the beginning of your lane:
lane :appstore do
pem
# ...
endpem will ensure your certificate is valid for at least another 2 weeks, and create a new one if it isn't.
If you don't have any push certificates already, pem will create one for you and store locally in your project's directory. To get more information about the available options run fastlane action pem.
File: docs/getting-started/ios/beta-deployment.md
iOS Beta deployment using _fastlane_
Building your app
fastlane takes care of building your app using a feature called gym, just add the following to your Fastfile:
lane :beta do
gym(scheme: "MyApp")
endAdditionally you can specify more options for building your app, for example
lane :beta do
gym(scheme: "MyApp",
workspace: "Example.xcworkspace",
include_bitcode: true)
endTry running the lane using
fastlane betaIf everything works, you should have a [ProductName].ipa file in the current directory. To get a list of all available parameters for gym, run fastlane action gym.
Codesigning
Chances are that something went wrong because of code signing at the previous step. We prepared our own Code Signing Guide that helps you setting up the right code signing approach for your project.
Uploading your app
After building your app, it's ready to be uploaded to a beta testing service of your choice. The beauty of fastlane is that you can easily switch beta provider, or even upload to multiple at once, without any extra work.
All you have to do is to put the name of the beta testing provider of your choice after building the app using gym:
lane :beta do
match(type: "appstore") # see code signing guide for more information
gym(scheme: "MyApp") # build your app
testflight # upload your app to TestFlight
slack(message: "Successfully distributed a new beta build")
endfastlane automatically passes on information about the generated .ipa file from gym to the beta testing provider of your choice.
To get a list of all available parameters for a given action, run
fastlane action slackSupported beta testing services
TestFlight
You can easily upload new builds to TestFlight (which is part of iTunes Connect) using fastlane. To do so, just use the built-in testflight action after building your app
lane :beta do
# ...
gym
testflight
endSome example use cases
lane :beta do
# ...
gym
# Variant 1: Provide a changelog to your build
testflight(changelog: "Add rocket emoji")
# Variant 2: Skip the "Waiting for processing" of the binary
# While this will speed up your build, it will not distribute
# the binary to your tests, nor set a changelog
testflight(skip_waiting_for_build_processing: true)
endIf you used fastlane init to setup fastlane, your Apple ID is stored in the fastlane/Appfile. You can also overwrite the username, using testflight(username: "[email protected]").
To get a list of all available options, run
fastlane action testflightWith fastlane, you can also automatically manage your beta testers, check out TODO for more information.
Crashlytics
lane :beta do
# ...
gym
crashlytics(api_token: "[insert_key_here]",
build_secret: "[insert_key_here]")
endTo get your API token, open the organizations settings page and click on the API key and build secret links.
To get a list of all available options, run
fastlane action crashlyticsTODO: Also mention the other onboarding method
HockeyApp
lane :beta do
# ...
gym
hockey(api_token: "[insert_key_here]")
endTo get your API token, open API Tokens in Account Settings. From there, you can find your existing API token, or create a new one.
To get a list of all available options see the hockey action docs, or run
fastlane action hockeyTestFairy
lane :beta do
# ...
gym
testfairy(api_key: "[insert_key_here]")
# Variant 1: Provide a changelog
testfairy(api_key: "[insert_key_here]",
comment: "Add rocket emoji")
# Variant 2: Specify tester groups
testfairy(api_key: "[insert_key_here]", testers_groups: ["group1"])
endTo get a list of all available options, run
fastlane action testfairyMore information about the service on TestFairy.com.
Release Notes
Automatically based on git commits
Your changelog changes, so it doesn't make a lot of sense to store a static release note in the Fastfile.
lane :beta do
match
gym
changelog_from_git_commits # this will generate the changelog based on your last commits
testflight
endGet a list of all available options using fastlane action changelog_from_git_commits, here are some examples
changelog_from_git_commits(
between: ['7b092b3', 'HEAD'], # Optional, lets you specify a revision/tag range between which to collect commit info
include_merges: true # Optional, lets you filter out merge commits
)Prompt for changelog
You can automatically be asked for the changelog in your terminal using the prompt action:
lane :beta do
# Variant 1: Ask for a one line input
changelog = prompt("Changelog: ")
# Variant 2: Ask for a multi-line input
# The user confirms their input by typing `END` and Enter
changelog = prompt(
text: "Changelog: ",
multi_line_end_keyword: "END"
)
match
gym
testflight(changelog: changelog)
endFetching the changelog from the file system or remote server
You can fetch values from anywhere in your Fastfile, including the file system and remote server
lane :beta do
# Variant 1: Read from file system
# note the `..`, since fastlane runs in the _fastlane_ directory
changelog = File.read("../Changelog.txt")
# Variant 2: Fetch data from a remote web server
changelog = download(url: "https://lookatmycms.com/changelog.txt")
match
gym
testflight(changelog: changelog)
endBest Practices
Manage devices and testers using fastlane
TestFlight
If you're using TestFlight you don't need to worry about UDIDs of your devices. Instead you just maintain a list of testers based on their Apple ID email address.
fastlane supports automatically registering devices using different approaches
[boarding](https://github.com/fastlane/boarding#readme)
boarding allows you set up a registration page for your beta testers, so they can enter their email address and start testing your application.
Check out the boarding GitHub repo for more information.
pilot
pilot is automatically installed with fastlane, you can use it to register individual testers to TestFlight
# Register a new external tester
fastlane pilot add [email protected]
# Register a new external tester and add them to your app
fastlane pilot add [email protected] -a com.app.nameThird party beta testing services
If you're using a third party beta testing service, you'll need to manage your registered devices and their UDIDs. fastlane already supports device registrations and updating provisioning profiles out of the box.
lane :beta do
# Before calling match, we make sure all our devices are registered on the Apple Developer Portal
register_devices(devices_file: "devices.txt")
# After registering the new devices, we'll make sure to update the provisioning profile if necessary
# Note how we make sure to pass "adhoc" to get and use a provisioning profile for Ad Hoc distribution
match(force_for_new_devices: true, type: "adhoc")
gym
# ...
endThe devices.txt should look like this:
Device ID Device Name
A123456789012345678901234567890123456789 DeviceName1
B123456789012345678901234567890123456789 DeviceName2Incrementing the build number
Depending on the beta testing service you use, you'll have to increment the build number each time you upload a new build. This is a requirement for TestFlight for example.
To do so, there are some built-in fastlane actions available, here are some examples
Commiting the build number to version control
The code sample below will increment the build number and commit the project changes to version control.
lane :beta do
# Ensure that your git status is not dirty
ensure_git_status_clean
# Increment the build number (not the version number)
# Providing the xcodeproj is optional
increment_build_number(xcodeproj: "Example.xcodeproj")
# Commit the version bump
commit_version_bump(xcodeproj: "Example.xcodeproj")
# Add a git tag for this build. This will automatically
# use an appropriate git tag name
add_git_tag
# Push the new commit and tag back to your git remote
push_to_git_remote
endFetching the latest build number from TestFlight
The code sample below will use the latest build number from TestFlight and temporarily set it.
lane :beta do
increment_build_number(
build_number: latest_testflight_build_number + 1,
xcodeproj: "Example.xcodeproj"
)
endFor all the steps above, there are more parameters available, run the following to get a full list:
fastlane action [action_name]