Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Add Docs
fastlane
https://github.com/fastlane/fastlane
Admin
fastlane is a tool for iOS and Android developers to automate tedious tasks like generating
...
Tokens:
77,676
Snippets:
914
Trust Score:
8
Update:
1 day ago
Context
Skills
Chat
Benchmark
82
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# fastlane fastlane is an open-source automation tool for iOS and Android developers that streamlines tedious release engineering tasks. It orchestrates the entire release pipeline — from running tests, managing code signing, capturing App Store screenshots, bumping version numbers, and uploading binaries to the App Store or Google Play — through a Ruby-based DSL called the `Fastfile`. The tool is organized as a Ruby monorepo (v2.234.0) containing individually executable sub-tools (`gym`, `match`, `deliver`, `pilot`, `scan`, `snapshot`, `screengrab`, `supply`, `cert`, `sigh`, `produce`, `pem`, `frameit`, `spaceship`, and `trainer`) that can be used standalone or composed together inside a `Fastfile`. Core functionality is expressed through **lanes** — named, composable automation sequences defined in a `Fastfile`. Each lane calls one or more **actions** (over 170 built-in actions are available) that map to underlying sub-tools or shell operations. Actions communicate with each other through the `lane_context` shared-values store. Plugins (Ruby gems prefixed `fastlane-plugin-`) extend the action library, and a `Pluginfile` manages their dependencies. Authentication with Apple services can use Apple ID credentials or the modern App Store Connect API key (JWT), while Android automation authenticates via a Google Play service-account JSON key. --- ## Fastfile DSL — Lane Definition A `Fastfile` is a Ruby file evaluated in the context of `Fastlane::FastFile`. `lane` declares a public workflow, `private_lane` hides it from the CLI, and `platform` scopes lanes to a specific OS. Lifecycle hooks `before_all`, `before_each`, `after_all`, `after_each`, and `error` wrap lane execution. ```ruby # fastlane/Fastfile default_platform(:ios) platform :ios do before_all do # runs before every lane on iOS setup_ci if ENV["CI"] end desc "Run unit and UI tests" lane :test do run_tests( workspace: "MyApp.xcworkspace", scheme: "MyApp", devices: ["iPhone 15 Pro"], clean: true ) end desc "Build and submit a new beta to TestFlight" lane :beta do increment_build_number(xcodeproj: "MyApp.xcodeproj") sync_code_signing(type: "appstore") build_app( workspace: "MyApp.xcworkspace", scheme: "MyApp", export_method: "app-store" ) upload_to_testflight( changelog: changelog_from_git_commits, skip_waiting_for_build_processing: true ) slack( message: "New beta uploaded to TestFlight!", slack_url: ENV["SLACK_URL"] ) end desc "Release to the App Store" lane :release do capture_ios_screenshots frame_screenshots deliver(force: true) end error do |lane, exception| slack( message: "Error in lane #{lane}: #{exception.message}", success: false, slack_url: ENV["SLACK_URL"] ) end end platform :android do lane :beta do gradle(task: "bundle", build_type: "Release") upload_to_play_store(track: "internal") end end ``` --- ## `app_store_connect_api_key` — Load App Store Connect API Key Loads a JWT-based App Store Connect API key from a `.p8` file or inline key content and stores it in `lane_context`. Once set, downstream actions (`build_app`, `upload_to_testflight`, `sync_code_signing`, etc.) automatically pick it up without requiring additional authentication steps. ```ruby # fastlane/Fastfile lane :setup_api_auth do # From a .p8 file on disk app_store_connect_api_key( key_id: ENV["ASC_KEY_ID"], # e.g. "D83848D23" issuer_id: ENV["ASC_ISSUER_ID"], # e.g. "227b0bbf-ada8-458c-9d62-3d8022b7d07f" key_filepath: "~/AuthKey_D83848D23.p8", duration: 1200, # token TTL in seconds (max 1200) in_house: false, # true for Enterprise distribution set_spaceship_token: true # auto-authorizes all Spaceship calls ) # key hash is now in lane_context[SharedValues::APP_STORE_CONNECT_API_KEY] # Alternative: pass key content directly (useful on CI where files aren't available) app_store_connect_api_key( key_id: "D83848D23", issuer_id: "227b0bbf-ada8-458c-9d62-3d8022b7d07f", key_content: ENV["ASC_KEY_CONTENT"], # full PEM content from env var is_key_content_base64: false ) end ``` --- ## `sync_code_signing` (`match`) — Sync Certificates and Provisioning Profiles Fetches or creates iOS/macOS certificates and provisioning profiles from a central Git, Google Cloud Storage, or S3 storage repository and installs them on the local machine. On CI, set `readonly: true` to prevent accidental certificate creation. Outputs `MATCH_PROVISIONING_PROFILE_MAPPING` used automatically by `build_app`. ```ruby lane :codesign do # App Store distribution profile for a single app sync_code_signing( type: "appstore", # "appstore" | "adhoc" | "development" | "enterprise" app_identifier: "com.example.MyApp", git_url: "https://github.com/myorg/certificates", readonly: ENV["CI"] == "true", # never create certs on CI keychain_name: ENV["MATCH_KEYCHAIN_NAME"] ) # Multiple identifiers (e.g., app + extensions) sync_code_signing( type: "appstore", app_identifier: [ "com.example.MyApp", "com.example.MyApp.NotificationExtension", "com.example.MyApp.ShareExtension" ] ) # After this action, MATCH_PROVISIONING_PROFILE_MAPPING is populated so # build_app automatically knows which profile to use per target end ``` --- ## `build_app` (`gym`) — Build and Sign an iOS/macOS App Compiles the Xcode project, archives it, and exports the signed `.ipa` or `.pkg`. Stores the output path in `IPA_OUTPUT_PATH` / `PKG_OUTPUT_PATH` so `upload_to_testflight` and `upload_to_app_store` pick it up automatically. Works seamlessly after `sync_code_signing`. ```ruby lane :build do sync_code_signing(type: "appstore", app_identifier: "com.example.MyApp") build_app( # alias: gym, build_ios_app, build_mac_app workspace: "MyApp.xcworkspace", scheme: "MyApp", configuration: "Release", clean: true, silent: false, output_directory: "./build", output_name: "MyApp.ipa", export_method: "app-store", # set automatically if match was used export_options: { provisioningProfiles: { "com.example.MyApp" => "match AppStore com.example.MyApp" } }, sdk: "iphoneos17.0", xcargs: "SWIFT_COMPILATION_MODE=wholemodule" ) # lane_context[SharedValues::IPA_OUTPUT_PATH] is now set end ``` --- ## `run_tests` (`scan`) — Run Xcode Tests Executes the Xcode test suite and generates JUnit, HTML, and JSON reports. Returns a hash of test results. Supports running tests without rebuilding (using a pre-built `xctestrun`) and parallel device testing. ```ruby lane :test do results = run_tests( # alias: scan workspace: "MyApp.xcworkspace", scheme: "MyAppTests", devices: ["iPhone 15", "iPad Air (5th generation)"], clean: false, code_coverage: true, output_directory: "./test_output", output_types: "junit,html", fail_build: true, number_of_retries: 2, # retry flaky tests up to 2 times parallel_testing: true, concurrent_workers: 4 ) puts "Tests: #{results[:number_of_tests]}" puts "Failures: #{results[:number_of_failures]}" # Run tests from a previous build (faster on CI) run_tests( derived_data_path: "DerivedData", test_without_building: true ) end ``` --- ## `upload_to_testflight` (`pilot`) — Upload to TestFlight Uploads a compiled `.ipa` to TestFlight via App Store Connect. Can distribute the build to specific test groups immediately or wait for Apple's processing before distributing. Picks up `IPA_OUTPUT_PATH` from `build_app` automatically. ```ruby lane :beta do upload_to_testflight( # aliases: testflight, pilot api_key: lane_context[SharedValues::APP_STORE_CONNECT_API_KEY], app_identifier: "com.example.MyApp", ipa: "./build/MyApp.ipa", # optional: auto-filled from build_app changelog: "Bug fixes and performance improvements", beta_app_description: "Internal beta for QA team", demo_account_required: true, notify_external_testers: false, distribute_external: true, groups: ["QA Team", "Beta Users"], skip_waiting_for_build_processing: false, beta_app_review_info: { contact_email: "dev@example.com", contact_first_name: "Dev", contact_last_name: "Team", contact_phone: "5551234567", notes: "Test account: test@example.com / password123" } ) end ``` --- ## `upload_to_app_store` (`deliver`) — Upload to the App Store Uploads the binary, metadata (descriptions, keywords, URLs), and screenshots to App Store Connect for App Store review submission. Can read metadata from a local directory structure. Uses `IPA_OUTPUT_PATH` and `SNAPSHOT_SCREENSHOTS_PATH` from upstream actions automatically. ```ruby lane :release do upload_to_app_store( # aliases: deliver, appstore api_key: lane_context[SharedValues::APP_STORE_CONNECT_API_KEY], app_identifier: "com.example.MyApp", ipa: "./build/MyApp.ipa", metadata_path: "./metadata", # folder with locale subdirs, e.g. metadata/en-US/description.txt screenshots_path: "./screenshots", submit_for_review: true, automatic_release: false, force: true, # skip HTML preview verification submission_information: { add_id_info_uses_idfa: false, export_compliance_uses_encryption: false }, precheck_include_in_app_purchases: true ) end ``` --- ## `capture_ios_screenshots` (`snapshot`) — Automated iOS Screenshots Drives the iOS Simulator via Xcode UI tests to automatically capture localized screenshots on multiple devices and in multiple languages. Stores the output path in `SNAPSHOT_SCREENSHOTS_PATH` for use by `frame_screenshots` and `upload_to_app_store`. ```ruby lane :screenshots do capture_ios_screenshots( # alias: snapshot workspace: "MyApp.xcworkspace", scheme: "MyAppUITests", devices: [ "iPhone 15 Pro Max", "iPhone SE (3rd generation)", "iPad Pro (12.9-inch) (6th generation)" ], languages: ["en-US", "de-DE", "ja-JP", "fr-FR"], output_directory: "./screenshots", clear_previous_screenshots: true, stop_after_first_error: false, skip_open_summary: true, clean: true ) # lane_context[SharedValues::SNAPSHOT_SCREENSHOTS_PATH] is now set end ``` --- ## `frame_screenshots` (`frameit`) — Add Device Frames to Screenshots Wraps screenshots with device bezels and optionally adds background colors and marketing text. Reads `.frameit.json` configuration for styling. Designed to be called after `capture_ios_screenshots`. ```ruby lane :framed_screenshots do capture_ios_screenshots(scheme: "MyAppUITests") frame_screenshots( # alias: frameit path: lane_context[SharedValues::SNAPSHOT_SCREENSHOTS_PATH], silver: false, # use black device frames rose_gold: false, use_platform: "IOS" # "IOS", "ANDROID", "ANY" ) # With a .frameit.json in the screenshots directory, titles and backgrounds # are applied automatically. Example .frameit.json: # { # "default": { # "background": "./background.jpg", # "title": { "color": "#545454" }, # "keyword": { "color": "#a9a9a9" } # } # } end ``` --- ## `capture_android_screenshots` (`screengrab`) — Automated Android Screenshots Automates screenshot capture across multiple Android locales using Espresso/UI Automator. Requires the app APK and instrumentation test APK to already be built. Stores the output path in `SCREENGRAB_OUTPUT_DIRECTORY`. ```ruby lane :android_screenshots do capture_android_screenshots( # alias: screengrab android_home: ENV["ANDROID_HOME"], build_tools_version: "34.0.0", locales: ["en-US", "de-DE", "fr-FR"], clear_previous_screenshots: true, output_directory: "fastlane/metadata/android", app_apk_path: "app/build/outputs/apk/release/app-release.apk", tests_apk_path: "app/build/outputs/apk/androidTest/release/app-release-androidTest.apk", app_package_name: "com.example.myapp", tests_package_name: "com.example.myapp.test" ) end ``` --- ## `upload_to_play_store` (`supply`) — Upload to Google Play Uploads APKs, AABs, metadata, and screenshots to the Google Play Store. Automatically picks up `GRADLE_APK_OUTPUT_PATH` or `GRADLE_AAB_OUTPUT_PATH` from a prior `gradle` action. Requires a service-account JSON key for authentication. ```ruby lane :android_release do gradle( task: "bundle", build_type: "Release", project_dir: "android/" ) upload_to_play_store( # alias: supply package_name: "com.example.myapp", json_key: ENV["GOOGLE_PLAY_JSON_KEY_PATH"], track: "internal", # "internal" | "alpha" | "beta" | "production" aab: lane_context[SharedValues::GRADLE_AAB_OUTPUT_PATH], rollout: "0.1", # staged rollout — 10% skip_upload_screenshots: false, metadata_path: "fastlane/metadata/android", version_name: "2.0.0", release_status: "draft" # "completed" | "draft" | "halted" | "inProgress" ) end ``` --- ## `increment_build_number` / `get_build_number` — Manage Xcode Build Numbers Reads or increments the Xcode project build number (CFBundleVersion) via Apple Generic Versioning (`agvtool`). `increment_build_number` writes the value back to all project targets. Stores the result in `BUILD_NUMBER`. ```ruby lane :bump_build do # Get current number current = get_build_number(xcodeproj: "MyApp.xcodeproj") puts "Current build: #{current}" # e.g. "42" # Increment automatically new_build = increment_build_number( xcodeproj: "MyApp.xcodeproj" ) # Or set a specific number (e.g. from CI build counter) increment_build_number( build_number: ENV["CI_BUILD_NUMBER"] || "75", xcodeproj: "MyApp.xcodeproj", skip_info_plist: false ) commit_version_bump( message: "Bump build number to #{lane_context[SharedValues::BUILD_NUMBER]}", xcodeproj: "MyApp.xcodeproj" ) end ``` --- ## `increment_version_number` — Manage Xcode Marketing Version Reads and bumps the iOS/macOS marketing version (CFBundleShortVersionString) using `agvtool`. Supports semantic `major`, `minor`, and `patch` bump types, or setting an exact version string. ```ruby lane :bump_version do # Increment patch: 1.2.3 → 1.2.4 increment_version_number( bump_type: "patch", xcodeproj: "MyApp.xcodeproj" ) # Increment minor: 1.2.4 → 1.3.0 increment_version_number(bump_type: "minor") # Increment major: 1.3.0 → 2.0.0 increment_version_number(bump_type: "major") # Set a specific version version = increment_version_number( version_number: "3.0.0", xcodeproj: "MyApp.xcodeproj" ) puts "New version: #{version}" # "3.0.0" # lane_context[SharedValues::VERSION_NUMBER] => "3.0.0" end ``` --- ## `changelog_from_git_commits` — Generate a Changelog from Git History Collects formatted Git commit messages between two refs (defaults to the last tag and `HEAD`) and stores the result as `FL_CHANGELOG`. The changelog is automatically picked up by `upload_to_testflight` and `set_github_release`. ```ruby lane :build_changelog do # Simple: collect all commits since last tag changelog_from_git_commits # Custom format and range notes = changelog_from_git_commits( between: ["v1.5.0", "HEAD"], pretty: "• %s (%an)", # custom git log --pretty format date_format: "short", merge_commit_filtering: "exclude_merges", match_lightweight_tag: false, quiet: false ) # Use last N commits changelog_from_git_commits(commits_count: 10) puts lane_context[SharedValues::FL_CHANGELOG] # => "• Fix login crash (Alice)\n• Add dark mode (Bob)\n..." end ``` --- ## `add_git_tag` / `push_to_git_remote` — Git Tagging and Pushing `add_git_tag` creates an annotated Git tag using the build number, lane name, and optional prefix/postfix. `push_to_git_remote` pushes committed changes and tags back to the remote repository — essential for CI pipelines that bump versions or add tags locally. ```ruby lane :tag_and_push do # Auto-format: builds/appstore/v42-RC1 add_git_tag( grouping: "builds", includes_lane: true, # includes current lane name prefix: "v", postfix: "-RC1", build_number: lane_context[SharedValues::BUILD_NUMBER] ) # Or use a fully custom tag add_git_tag(tag: "release/#{lane_context[SharedValues::VERSION_NUMBER]}") # Push commits and tags to origin push_to_git_remote( remote: "origin", local_branch: "main", remote_branch: "main", force: false, tags: true, # push tags along with commits no_verify: false ) end ``` --- ## `set_github_release` — Create a GitHub Release Creates a GitHub release for a tag, optionally uploading binary assets. Reads the release description from `FL_CHANGELOG` by default. Outputs `SET_GITHUB_RELEASE_HTML_LINK` and `SET_GITHUB_RELEASE_RELEASE_ID` for downstream use. ```ruby lane :github_release do changelog_from_git_commits(between: ["v1.4.0", "HEAD"]) release = set_github_release( repository_name: "myorg/MyApp", api_token: ENV["GITHUB_TOKEN"], tag_name: "v#{lane_context[SharedValues::VERSION_NUMBER]}", name: "MyApp #{lane_context[SharedValues::VERSION_NUMBER]}", description: lane_context[SharedValues::FL_CHANGELOG], commitish: "main", is_draft: false, is_prerelease: false, is_generate_release_notes: false, upload_assets: [ "./build/MyApp.ipa", "./build/MyApp.app.dSYM.zip" ] ) puts "Release published: #{release[:html_url]}" # lane_context[SharedValues::SET_GITHUB_RELEASE_HTML_LINK] is also set end ``` --- ## `create_app_online` (`produce`) — Create an App in App Store Connect Creates a new app record in App Store Connect and the Apple Developer Portal simultaneously. If the app already exists, the action is a no-op. Returns the new app's Apple ID in `PRODUCE_APPLE_ID`. ```ruby lane :create_new_app do create_app_online( # alias: produce username: "dev@example.com", app_identifier: "com.example.NewApp", app_name: "My New App", language: "English", app_version: "1.0", sku: "MYAPP001", team_name: "Example Org", # only needed for multiple teams enable_services: { push_notification: "on", in_app_purchase: "on", apple_pay: "off" } ) puts "Apple ID: #{lane_context[SharedValues::PRODUCE_APPLE_ID]}" end ``` --- ## `register_devices` — Register Test Devices in the Developer Portal Registers new iOS/macOS device UDIDs with the Apple Developer Portal for inclusion in development and Ad Hoc provisioning profiles. Accepts a Ruby hash or a tab-delimited `.txt` file in Apple's UDID export format. ```ruby lane :add_devices do # From a hash register_devices( devices: { "Alice's iPhone 15 Pro" => "00008030-001A2B3C4D5E6F70", "Bob's iPad Air" => "00008103-001A2B3C4D5E001E" }, api_key: lane_context[SharedValues::APP_STORE_CONNECT_API_KEY] ) # From a TSV file (Device ID\tDevice Name\tDevice Platform) register_devices( devices_file: "./devices.txt", team_id: "XXXXXXXXXX" ) # Mac devices register_devices( devices: { "Dev MacBook Pro" => "12345678-1234-1234-1234-123456789012" }, platform: "mac" ) end ``` --- ## `cocoapods` — Run CocoaPods Install Runs `pod install` for the iOS/macOS project. Supports `clean_install` for a full cache-less install and optional automatic `--repo-update` retry on errors. ```ruby lane :install_deps do cocoapods( clean_install: true, # ignore the cache (equivalent to: rm -rf Pods && pod install) repo_update: false, try_repo_update_on_error: true, # retry with --repo-update if first attempt fails podfile: "./iOS/Podfile", use_bundle_exec: true, deployment: true # fail if Podfile.lock is out of sync ) end ``` --- ## `swiftlint` — Lint Swift Code Runs SwiftLint to enforce Swift style and conventions. Supports `lint`, `autocorrect`, `fix`, and `analyze` modes. Can be scoped to specific files and will auto-select the appropriate mode based on the installed SwiftLint version. ```ruby lane :lint do swiftlint( mode: :lint, # :lint | :fix | :analyze path: "Sources/", config_file: ".swiftlint.yml", reporter: "xcode", # "xcode" | "json" | "html" | "github-actions-logging" output_file: "swiftlint.result.json", strict: true, # treat warnings as errors quiet: false, raise_if_swiftlint_error: true, # fail the lane on lint violations ignore_exit_status: false, files: [ # optional: scope to specific files "Sources/AppDelegate.swift", "Sources/Models/User.swift" ] ) end ``` --- ## `setup_ci` — Configure Keychain and Paths for CI Creates a temporary keychain, puts `match` in readonly mode, and configures output directory environment variables for CI environments (CircleCI, CodeBuild, Travis). Designed to be called at the top of every CI-triggered lane. ```ruby lane :ci_setup do setup_ci( provider: "circleci", # "circleci" | "travis"; auto-detected if omitted timeout: 3600, # keychain auto-lock timeout in seconds (0 = never) keychain_name: "fastlane_tmp_keychain", force: false # set true to run even outside of CI ) # After this: # ENV["MATCH_KEYCHAIN_NAME"] = "fastlane_tmp_keychain" # ENV["MATCH_KEYCHAIN_PASSWORD"] = "" # ENV["MATCH_READONLY"] = "true" # ENV["SCAN_OUTPUT_DIRECTORY"], ENV["GYM_OUTPUT_DIRECTORY"] etc. are set if FL_OUTPUT_DIR is set end ``` --- ## `slack` — Send Slack Notifications Posts a success or failure notification to a Slack channel via an Incoming Webhook. Automatically includes git branch, git author, and last commit message as payload fields. Supports threading via `thread_ts`. ```ruby lane :notify do slack( message: "Build #{lane_context[SharedValues::BUILD_NUMBER]} deployed to TestFlight!", slack_url: ENV["SLACK_URL"], channel: "#releases", success: true, username: "fastlane-bot", icon_url: "https://fastlane.tools/assets/img/fastlane_icon.png", payload: { "Build Number" => lane_context[SharedValues::BUILD_NUMBER], "Version" => lane_context[SharedValues::VERSION_NUMBER] }, default_payloads: [:git_branch, :git_author, :last_git_commit_hash], fail_on_error: false # don't block the lane if Slack is unreachable ) # On failure error do |lane, exception| slack( message: "Lane #{lane} failed: #{exception.message}", slack_url: ENV["SLACK_URL"], success: false, channel: "#ci-failures" ) end end ``` --- ## `sh` — Run Shell Commands Executes an arbitrary shell command and returns its output as a string. Commands run in the fastlane project root by default. Supports an `error_callback` block for custom error handling. ```ruby lane :shell_tasks do # Simple one-liner sh("ls -la ./build") # Multi-argument form (safe from shell injection) sh("git", "commit", "-m", "Automated version bump [ci skip]") # Capture output git_hash = sh("git rev-parse --short HEAD").strip puts "Current commit: #{git_hash}" # Custom error handling instead of crashing the lane sh( command: "bundle exec rubocop --parallel", log: true, error_callback: lambda do |result| UI.important("RuboCop found issues:\n#{result}") end ) end ``` --- ## `fastlane` CLI — Running Lanes from the Command Line Lanes are invoked via the `fastlane` CLI. Options can be passed as key:value pairs directly on the command line and are available inside the lane via the `options` parameter. ```bash # Run a specific lane fastlane ios beta # Pass parameters to a lane fastlane ios release version_number:2.1.0 submit:true # Run on Android fastlane android deploy # List all available lanes fastlane lanes # Print environment info for debugging fastlane env # Install a plugin fastlane add_plugin firebase_app_distribution # Search for plugins fastlane search_plugins screenshot ``` ```ruby # Accessing CLI options inside a lane lane :release do |options| version = options[:version_number] || "1.0.0" increment_version_number(version_number: version) build_app(scheme: "MyApp") upload_to_app_store if options[:submit] end ``` --- ## Plugin System — Extending fastlane Third-party actions are distributed as Ruby gems prefixed with `fastlane-plugin-`. A `Pluginfile` inside the `fastlane/` directory pins their versions. Plugins are loaded automatically at runtime and their actions become available in the `Fastfile` alongside built-in actions. ```bash # Add a plugin (updates Pluginfile and Gemfile automatically) fastlane add_plugin firebase_app_distribution fastlane add_plugin versioning # Pluginfile is auto-generated: # fastlane/Pluginfile gem "fastlane-plugin-firebase_app_distribution" gem "fastlane-plugin-versioning" ``` ```ruby # fastlane/Fastfile — using plugin actions just like built-in actions lane :distribute do build_app(scheme: "MyApp") # fastlane-plugin-firebase_app_distribution firebase_app_distribution( app: ENV["FIREBASE_APP_ID"], groups: "qa-team", release_notes: changelog_from_git_commits, firebase_cli_token: ENV["FIREBASE_CLI_TOKEN"] ) end ``` --- fastlane's primary use cases are **continuous delivery pipelines for iOS and Android apps**: automating the complete path from a code commit to a production release, including running the test suite, managing code-signing identities and provisioning profiles, capturing and framing App Store screenshots in multiple languages, incrementing version and build numbers, uploading binaries to TestFlight or the Google Play Store, creating GitHub releases with build artifacts, and notifying the team via Slack. The composable lane/action model means each step can be run independently during development or chained into a full release workflow on a CI server. Integration patterns typically follow one of two approaches: a **developer-centric Fastfile** where lanes map to daily tasks (`test`, `beta`, `release`, `screenshots`) invoked from the terminal, and a **CI-centric Fastfile** that begins with `setup_ci` and is triggered automatically by a GitHub Actions/CircleCI/Jenkins pipeline on push or tag events. Credentials are injected via environment variables (`APP_STORE_CONNECT_API_KEY_*`, `MATCH_GIT_URL`, `GOOGLE_PLAY_JSON_KEY_PATH`, `SLACK_URL`), and the `Appfile` stores stable app-level defaults (`app_identifier`, `apple_id`, `team_id`, `package_name`) to avoid repeating them in every action call.