To pass parameters from the command line to your lane, use the following syntax:
fastlane [lane] key:value key2:value2 fastlane deploy submit:false build_number:24
To access those values, change your lane declaration to also include
before_all do |lane, options| # ... end before_each do |lane, options| # ... end lane :deploy do |options| # ... if options[:submit] # Only when submit is true end # ... increment_build_number(build_number: options[:build_number]) # ... end after_all do |lane, options| # ... end after_each do |lane, options| # ... end error do |lane, exception, options| if options[:debug] puts "Hi :)" end end
To switch lanes while executing a lane, use the following code:
lane :deploy do |options| # ... build(release: true) # that's the important bit hockey # ... end lane :staging do |options| # ... build # it also works when you don't pass parameters hockey # ... end lane :build do |options| scheme = (options[:release] ? "Release" : "Staging") ipa(scheme: scheme) end
fastlane takes care of all the magic for you. You can call lanes of the same platform or a general lane outside of the
Passing parameters is optional.
Additionally, you can retrieve the return value. In Ruby, the last line of the
lane definition is the return value. Here is an example:
lane :deploy do |options| value = calculate(value: 3) puts value # => 5 end lane :calculate do |options| # ... 2 + options[:value] # the last line will always be the return value end
Stop executing a lane early
next keyword can be used to stop executing a
lane before it reaches the end.
lane :build do |options| if cached_build_available? UI.important 'Skipping build because a cached build is available!' next # skip doing the rest of this lane end match gym end private_lane :cached_build_available? do |options| # ... true end
next is used during a
lane switch, control returns to the previous
lane that was executing.
lane :first_lane do |options| puts "If you run: `fastlane first_lane`" puts "You'll see this!" second_lane puts "As well as this!" end private_lane :second_lane do |options| next puts "This won't be shown" end
When you stop executing a lane early with
after_all blocks you have will still trigger as usual :+1:
before_each blocks are called before any lane is called. This would include being called before each lane you've switched to.
before_each do |lane, options| # ... end
after_each blocks are called after any lane is called. This would include being called after each lane you've switched to.
after_each is not called if an error occurs. The
error block should be used in this case.
after_each do |lane, options| # ... end
e.g. With this scenario,
after_each would be called 4 times: before the
deploy lane, before the switch to
upload, and after each of these lanes as well.
lane :deploy do archive sign upload end lane :archive do # ... end lane :sign do # ... end lane :upload do # ... end
Run actions directly
If you just want to try an action without adding them to your
Fastfile yet, you can use
fastlane run notification message:"My Text" title:"The Title"
To get the available options for any action run
fastlane action [action_name]. You might not be able to set some kind of parameters using this method.
You can get value from shell commands:
output = sh("pod update")
Priorities of parameters and options
The order in which fastlane tools take their values from
- CLI parameter (e.g.
gym --scheme Example) or Fastfile (e.g.
- Environment variable (e.g.
- Tool specific config file (e.g.
- Default value (which might be taken from the
- If this value is required, you'll be asked for it (e.g. you have multiple schemes, you'll be asked for it)
Importing another Fastfile
Fastfile you can import another
Fastfile using 2 methods:
Fastfile from a local path
import "../GeneralFastfile" override_lane :from_general do # ... end
Import from another git repository, which you can use to have one git repo with a default
Fastfile for all your project
import_from_git(url: 'https://github.com/fastlane/fastlane/tree/master/fastlane') # or import_from_git(url: [email protected]:MyAwesomeRepo/MyAwesomeFastlaneStandardSetup.git', path: 'fastlane/Fastfile') lane :new_main_lane do # ... end
This will also automatically import all the local actions from this repo.
You should import the other
Fastfile on the top above your lane declarations. When defining a new lane fastlane will make sure to not run into any name conflicts. If you want to overwrite an existing lane (from the imported one), use the
You can define environment variables in a
.env.default file in the same directory as your
Fastfile. Environment variables are loading using dotenv. Here's an example.
fastlane also has a
--env option that allows loading of environment specific
.env.default will be loaded before environment specific
dotenv files are loaded. The naming convention for environment specific
dotenv files is
fastlane <lane-name> --env development will load
The different actions can communicate with each other using a shared hash. You can access them in your lanes with the following code.
VARIABLE_NAME_HERE with any of the following.
lane_context[SharedValues::LANE_NAME] # The name of the current lane (stays the same when switching lanes) lane_context[SharedValues::BUILD_NUMBER] # Generated by `increment_build_number` lane_context[SharedValues::VERSION_NUMBER] # Generated by `increment_version_number` lane_context[SharedValues::SNAPSHOT_SCREENSHOTS_PATH] # Generated by _snapshot_ lane_context[SharedValues::PRODUCE_APPLE_ID] # The Apple ID of the newly created app lane_context[SharedValues::IPA_OUTPUT_PATH] # Generated by _gym_ lane_context[SharedValues::DSYM_OUTPUT_PATH] # Generated by _gym_ lane_context[SharedValues::SIGH_PROFILE_PATH] # Generated by _sigh_ lane_context[SharedValues::SIGH_UDID] # The UDID of the generated provisioning profile lane_context[SharedValues::HOCKEY_DOWNLOAD_LINK] # Generated by `hockey` lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH] # Generated by `gradle` lane_context[SharedValues::GRADLE_ALL_APK_OUTPUT_PATHS] # Generated by `gradle` lane_context[SharedValues::GRADLE_FLAVOR] # Generated by `gradle` lane_context[SharedValues::GRADLE_BUILD_TYPE] # Generated by `gradle`
To get information about the available lane variables, run
fastlane action [action_name].
Sometimes you might have a lane that is used from different lanes, for example:
lane :production do # ... build(release: true) appstore # Deploy to the AppStore # ... end lane :beta do # ... build(release: false) crashlytics # Distribute to testers # ... end lane :build do |options| # ... ipa # ... end
It probably doesn't make sense to execute the
build lane directly using
fastlane build. You can hide this lane using
private_lane :build do |options| # ... end
This will hide the lane from:
And also, you can't call the private lane using
The resulting private lane can only be called from another lane using the lane switching technology.
Load own actions from external folder
Add this to the top of your
Skip update check when launching fastlane
You can set the environment variable
FASTLANE_SKIP_UPDATE_CHECK to skip the update check.
You can add credentials for use by fastlane to your keychain using the CredentialsManager command line interface. This is useful for situations like CI environments.
Adding a Credential
fastlane-credentials add --username [email protected] Password: ********* Credential [email protected]:********* added to keychain.
Removing a Credential
fastlane-credentials remove --username [email protected] password has been deleted.
Control configuration by lane and by platform
In general, configuration files take only the first value given for a particular configuration item. That means that for an
Appfile like the following:
app_identifier "com.used.id" app_identifier "com.ignored.id"
app_identfier will be
"com.used.id" and the second value will be ignored. The
for_platform configuration blocks provide a limited exception to this rule.
All configuration files (Appfile, Matchfile, Screengrabfile, etc.) can use
for_platform blocks to control (and override) configuration values for those circumstances.
for_lane blocks will be called when the name of lane invoked on the command line matches the one specified by the block. So, given a
locales ['en-US', 'fr-FR', 'ja-JP'] for_lane :screenshots_english_only do locales ['en-US'] end for_lane :screenshots_french_only do locales ['fr-FR'] end
locales will have the values
['en-US', 'fr-FR', 'ja-JP'] by default, but will only have one value when running the
fastlane screenshots_english_only or
for_platform gives you similar control based on the platform for which you have invoked fastlane. So, for an
Appfile configured like:
app_identifier "com.default.id" for_lane :enterprise do app_identifier "com.forlane.enterprise" end for_platform :mac do app_identifier "com.forplatform.mac" for_lane :release do app_identifier "com.forplatform.mac.forlane.release" end end
you can expect the
app_identifier to equal
"com.forplatform.mac.forlane.release" when invoking
fastlane mac release.
Manually Manage the fastlane match Repo
Most users can benefit from match's automatic management of the repo that stores certificates and provisioning profiles. From time to time, it may be necessary to manually change the files in this repo.
For example, fastlane requires admin access to the Apple Developer account to generate the appropriate files. If you are provided with an updated certificate or profile but do not have admin access, you can manually edit the repo.
Warning: Manually editing your match repo can introduce unexpected behavior and is not recommended. Proceed with caution.
- fastlane encrypts the repo, and
- fastlane doesn't support manual edits to the repo
it's necessary to manually decrypt, then modify, then encrypt, the repo to make any changes.
These instructions presuppose you already have fastlane match configured correctly.
🔓 Decryption Instructions
The easiest way to decrypt the repo is to use the fastlane match
GitHelper class. You can do this from an interactive Ruby console:
$ bundle console irb(main):001:0>
Then, require match and set the appropriate parameters:
irb(main):001:0> require 'match' irb(main):002:0> git_url = 'https://github.com/fastlane/example-certificate-repo' => "https://github.com/fastlane/example-certificate-repo" irb(main):003:0> shallow_clone = false => false irb(main):004:0> manual_password = 'example-password' => "example-password"
GitHelper.clone, which will clone and decrypt the repo for you. Assign the return value to
workspace, which we'll need later when we re-encrypt:
irb(main):005:0> workspace = Match::GitHelper.clone(git_url, shallow_clone, manual_password: manual_password) [14:49:30]: Cloning remote git repo... [14:49:31]: 🔓 Successfully decrypted certificates repo => "/var/folders/0j/29ytx6wx0fg86sznfb4mqdph0000gn/T/d20170314-14350-11hmdro"
The directory beginning with
/var/folders contains the decrypted git repo. Modify it as needed.
If you are updating a
.p12 file, ensure it's exported from the keychain without a password, since match doesn't support importing private keys with a password.
Warning: Do not commit your changes. Allow fastlane to do that for you.
Once your changes are made, we'll need to encrypt the repo and push it.
🔒 Encryption Instructions
In the Ruby console, call
GitHelper.commit_changes, passing in the commit message you want. For example:
irb(main):006:0> Match::GitHelper.commit_changes(workspace, "remove password from p12 file", git_url)
Your changes will be encrypted, committed, and pushed.
Note: If your keychain doesn't include the encryption passcode, you may be prompted for it. If so, just enter the same password you used to decrypt it.
fastlane was designed in a way that you can run fastlane from both the root directory of the project, and from the
Take this example
Fastfile on the path
sh "pwd" # => "[root]/fastlane" puts Dir.pwd # => "[root]/fastlane" lane :something do sh "pwd" # => "[root]/fastlane" puts Dir.pwd # => "[root]/fastlane" my_action end
The implementation of
my_action looks like this:
def run(params) puts Dir.pwd # => "[root]" end
Notice how every action and every plugin's code runs in the root of the project, while all user code from the
Fastfile runs inside the
./fastlane directory. This is important to consider when migrating existing code from your
Fastfile into your own action or plugin. To change the directory manually you can use standard Ruby blocks:
Dir.chdir("..") do # code here runs in the parent directory end
This behavior isn't great, and has been like this since the very early days of fastlane. As much as we'd like to change it, there is no good way to do so, without breaking thousands of production setups, so we decided to keep it as is for now.