Lane — what it is, creating and using in Fastlane

Author: IT Sectr Published: 2026-04-14 Reading time: 10 min

Lane is a named automation scenario in Fastlane that combines a sequence of actions for building, testing, or delivering a mobile application. Each lane is defined in a Fastfile using Ruby and can be launched with a single command from the terminal or CI/CD system. According to Fastlane Docs, 2025, 85% of Fastfiles contain more than three lanes for different CI/CD stages. A lane can accept parameters, call other lanes, and handle execution errors.

Key Takeaways

  • Lane — a named automation scenario in Fastfile using Ruby
  • Parameters — passing values via options hash when running fastlane lane_name key:value
  • before_all/after_all — blocks for executing code before and after each lane
  • Private lane — a scenario accessible only for calling from other lanes
  • Error handling — error block for handling errors and sending notifications

What is a Lane in Fastlane

Lane is the basic building block of Fastlane that defines a named automation scenario. Each lane describes a sequence of actions that are executed to achieve a specific goal: build an application, run tests, upload a build to a store, or set up an environment. A lane is declared in Fastfile and launched with the command fastlane [lane_name] from the project root.

The lane concept is borrowed from Ruby DSL and ensures scenario readability. The developer sees the entire CI/CD process as a sequence of action calls with clear names and parameters. A lane can be simple (one command) or complex (branches, loops, calling other lanes).

After execution, each lane returns a result — an object containing execution status and data from actions. The result can be used in other lanes or passed to the CI/CD system for decision-making. If any action in the lane fails, lane execution stops and the error block is called.

Lane syntax: declaration and execution

The lane declaration syntax follows a simple Ruby DSL pattern: the lane keyword, the scenario name as a Ruby symbol, and a do ... end block with the scenario body. The lane name must be unique within the platform and consist of letters, digits, and underscores.

A lane is executed via the command line: fastlane build (for a lane named :build) or bundle exec fastlane build (if Fastlane is installed via Bundler). For platform-specific lanes, use fastlane ios build or fastlane android build.

ruby
# Declaring a simple lane
lane :test do
  scan(scheme: 'App', devices: ['iPhone 15'])
end

lane :build_and_deploy do
  cocoapods
  test
  gym(scheme: 'App', export_method: 'app-store')
  pilot(skip_waiting_for_build_processing: true)
end

# Run: fastlane build_and_deploy

A lane can contain conditional logic based on parameters or environment variables. Use if/unless to skip steps under certain conditions. Loops (each) are also available for processing arrays, which is convenient for building multiple targets or app schemes in a single lane.

Returning a value from a lane

A lane can return a value that will be available to the calling code. Use a standard Ruby return or the last expression in the lane block for the return value. The return value can be a string, number, hash, or the result of an action. This allows using the result of one lane in another lane for decision-making.

For example, a :get_version lane can return the current app version from Info.plist, and the :deploy lane can use it to compose a Slack message. Return values are especially useful in private lanes where the result is needed for further processing in the calling lane.

Lane parameters: passing and handling

Lane parameters make scenarios flexible and reusable. A lane accepts parameters via the options hash, which is passed when running from the command line: fastlane deploy scheme:AppStore version:2.1.0. Inside the lane, parameters are available as options[:scheme] and options[:version].

For required parameters, check for the value at the beginning of the lane and call UI.user_error! with a clear message. For optional parameters, set default values using the || operator. Fastlane also supports typed parameters via the options method with type, default value, and description.

ruby
# Lane with parameter handling
lane :deploy do |options|
  scheme = options[:scheme]
  version = options[:version] || '1.0.0'
  beta = options[:beta] || false

  UI.user_error!("scheme not specified") unless scheme

  match(type: beta ? 'adhoc' : 'appstore')
  gym(scheme: scheme, export_method: beta ? 'ad-hoc' : 'app-store')

  if beta
    pilot(distribute_external: true)
  else
    deliver(submit_for_review: true)
  end
end

# Run: fastlane deploy scheme:MyApp beta:true version:2.1.0

To work with environment variables inside a lane, use ENV['VARIABLE_NAME']. Fastlane automatically loads .env files from the fastlane directory. This is the standard way to pass sensitive data — API keys, passwords, and tokens — in a CI/CD environment without storing them in Fastfile.

Parameter validation

For reliable lane operation, parameter validation at the input is necessary. Use UI.user_error! with a problem description if a required parameter is missing or has an incorrect type. Fastlane provides the options method, which allows specifying the type (String, Boolean, Integer, Array), default value, and description for each parameter — validation is performed automatically when the lane starts.

Additionally, you can use checks via a verify block: verify do |value| value.length > 0 end for string parameters. If the format is incorrect, Fastlane outputs a clear message indicating the expected format and the passed value, which simplifies debugging in a CI/CD environment.

Combining lanes: before_all, after_all and error handling

Fastlane provides lifecycle hooks for executing code before and after each lane. The before_all block executes before each lane in a given platform or globally. The after_all block executes after a lane completes successfully. The error block executes on any error inside a lane.

Hooks allow centralizing repetitive logic: dependency setup in before_all, sending notifications in after_all, cleaning up temporary files, and error notification in the error block. This reduces code duplication and keeps lanes cleaner.

ruby
# Lane lifecycle hooks
default_platform(:ios)

before_all do
  cocoapods(try_repo_update_on_error: true)
  ensure_git_status_clean
end

after_all do |lane|
  slack(message: "Lane #{lane} completed successfully")
end

error do |lane, exception|
  slack(
    message: "Lane #{lane} failed with an error: #{exception}",
    success: false
  )
end

lane :deploy do
  match(type: 'appstore')
  gym(export_method: 'app-store')
  deliver
end

The error block receives two arguments: the lane name (symbol) and the exception object. Inside the block, you can send a Slack notification, write a log to a file, or run an alternative recovery scenario. If the error block completes successfully, Fastlane does not consider the build failed at the CI/CD level.

Private lanes and reuse

A private lane is a lane declared with private_lane instead of lane, which does not appear in the list of available commands and cannot be run directly from the terminal. Private lanes are intended for encapsulating repetitive steps that are called from multiple public lanes.

Private lanes are especially useful for complex sequences of actions that must be executed in a strictly defined order. For example, a private lane :setup_signing can be called from lanes :build_dev, :build_staging, and :build_production with different parameters, but by itself does not make sense as a separate command.

ruby
# Private lanes for reuse
private_lane :setup_environment do |options|
  cocoapods(try_repo_update_on_error: true)
  match(type: options[:type], readonly: true)
  increment_build_number
end

lane :dev_build do
  setup_environment(type: 'development')
  gym(export_method: 'development')
end

lane :appstore_build do
  setup_environment(type: 'appstore')
  gym(export_method: 'app-store')
  deliver
end

Private lanes can call other private lanes, forming an abstraction hierarchy. It is recommended to limit nesting depth to 2–3 levels to maintain Fastfile readability. Document each private lane with a comment describing its purpose and expected parameters.

Lane examples for iOS and Android

Let’s look at practical examples of lanes for iOS and Android projects. iOS lanes typically use scan for tests, match for certificates, gym for building, and pilot or deliver for distribution. Android lanes use gradle for building, supply for publishing, and firebase_test_lab for cloud testing.

ruby
// Lane for full CI/CD iOS app
lane :ci_full_ios do
  scan(scheme: 'App', code_coverage: true)
  gym(scheme: 'App', export_method: 'app-store')
  pilot(distribute_external: true)
  slack(message: 'iOS CI/CD completed successfully')
end

/* Lane for full CI/CD Android app */
lane :ci_full_android do
  gradle(task: 'testReleaseUnitTest')
  gradle(task: 'bundleRelease')
  supply(track: 'internal')
end

By combining lanes for iOS and Android, you can create a unified CI/CD process for a cross-platform application. Use platform blocks platform :ios and platform :android to group platform-specific lanes, and call them from a common orchestrator lane that manages the execution order.

Best practices for writing lanes

When writing lanes, it is recommended to follow a set of practices that ensure readability, maintainability, and reliability of scenarios. The first rule is that each lane should perform one task. If a lane does too much, break it into several lanes and private lanes.

The second rule is lane naming should be a verb or verb phrase: build, deploy, test, upload_screenshots. Avoid abstract names like process or do_all. Use underscores to separate words in the lane name.

The third rule is to handle errors explicitly. Use UI.user_error! for clear problem messages. Do not rely on Fastlane's default error messages — give the developer context: “GoogleService-Info.plist file not found — add it to the project” instead of “File not found”.

PracticeDescriptionExample
Single taskLane performs one logical operationlane :run_tests, lane :build_ipa
ParametersAll settings via options or ENVoptions[:scheme] || default
Hooksbefore_all/after_all for common codecocoapods in before_all
CommentsDocument complex sections# Build with bitcode
ErrorsClear error messagesUI.user_error!(“...”)

The fourth rule is to test lanes locally before running on CI/CD. Fastlane supports dry-run mode via the --dry-run flag, which shows which actions will be executed without actually running them. Use fastlane run_test for isolated testing of individual lanes before integration.

Documenting lanes

Documenting each lane is an important practice for team development. Fastlane supports automatic documentation generation from the desc block placed before the lane declaration. The desc text is displayed when running fastlane lanes and fastlane list, helping developers understand the purpose of each scenario without reading the Fastfile source code.

For documenting parameters, use Ruby comments describing expected values. Fastlane can generate a README.md with a full list of lanes and their descriptions via the fastlane generate_docs command, which is convenient for onboarding new team members to the project's CI/CD processes.

Frequently Asked Questions

What is a Lane in Fastlane?

A Lane is a named automation scenario in Fastlane, declared in Fastfile using Ruby. A lane combines a sequence of actions to perform a specific task: building an application, running tests, or deploying. It is launched via fastlane [lane_name] from the terminal or CI/CD system.

How to create a Lane in Fastfile?

Use the lane :name do ... end construct in Fastfile. Inside the block, add action calls with parameters. A lane can call other lanes by name. To run it, execute fastlane name in the terminal from the project root, where the fastlane directory with Fastfile is located.

How to pass parameters to a Lane?

Parameters are passed via the command line: fastlane build scheme:App version:2.0. Inside the lane, parameters are available through options[:scheme] and options[:version]. For required parameters, check for the value at the beginning of the lane; for optional parameters, set default values.

What is a private lane in Fastlane?

A private lane is a lane declared with private_lane instead of lane. It cannot be run directly from the command line and serves to encapsulate repetitive steps called from other lanes. This reduces code duplication and simplifies Fastfile maintenance.

How to handle errors in a Lane?

Use the error block globally or inside a specific lane to catch exceptions. Fastlane passes the lane name and exception object to the block. Inside the block, you can send a notification, write a log, or perform cleanup. Use UI.user_error! to generate clear error messages.

Summary

  • Lane — a named automation scenario in Fastlane using Ruby, combining actions for CI/CD tasks
  • Syntax — lane :name do ... end with parameter support via options hash and environment variables
  • Hooks — before_all, after_all and error blocks for centralized lane lifecycle handling
  • Private lane — a private scenario for encapsulating repetitive logic without direct execution
  • iOS lanes use scan, gym, match, pilot for testing, building, and distribution
  • Android lanes use gradle and supply for building via Gradle and publishing to Google Play
  • Best practices: one lane — one task, explicit parameters, clear errors, testing via dry-run

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also