Fastlane setup
Skill almasumdev/awesome-mobile-release-agent-skills/.github/skills/ci_cd/fastlane-setup
Agent skills for mobile release engineering: signing, versioning, store submissions, and rollouts.
npx -y skills add almasumdev/awesome-mobile-release-agent-skills --skill fastlane-setupAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Set up a complete Fastlane pipeline — Fastfile structure, lanes, match, pilot, supply. Use this when introducing Fastlane to an iOS or Android project.
SKILL.md
5.5 KB, as published. Nobody here has run it
Fastlane Setup
Instructions
Fastlane is the lingua franca of mobile release automation. This skill covers the minimum viable Fastfile for iOS + Android, set up so every lane runs identically on a developer laptop and on CI.
1. Install Fastlane
Pin the version in a Gemfile at the repo root:
source "https://rubygems.org"
gem "fastlane", "~> 2.220"
plugins_path = File.join(File.dirname(__FILE__), "fastlane", "Pluginfile")
eval_gemfile(plugins_path) if File.exist?(plugins_path)
bundle config set --local path "vendor/bundle"
bundle install
Run as bundle exec fastlane ... everywhere.
2. Directory Layout
ios/
fastlane/
Appfile
Fastfile
Matchfile
Pluginfile
metadata/
screenshots/
android/
fastlane/
Appfile
Fastfile
Pluginfile
metadata/
Separate fastlane/ dirs per platform keep lanes tidy and allow platform-only lane runs from platform CI jobs.
3. Appfile (iOS)
app_identifier("com.acme.app")
apple_id("[email protected]")
team_id("ABCDE12345")
itc_team_id("109876543")
4. Appfile (Android)
json_key_file("") # provided via env var PLAY_SERVICE_ACCOUNT_JSON_PATH
package_name("com.acme.app")
5. iOS Fastfile
default_platform(:ios)
platform :ios do
before_all { setup_ci }
desc "Install certs & profiles via match"
lane :certs do
match(type: "development", readonly: true)
match(type: "appstore", readonly: true)
end
desc "Build and upload to TestFlight"
lane :beta do
api_key = asc_api_key
match(type: "appstore", readonly: true, api_key: api_key)
build_app(
workspace: "Runner.xcworkspace",
scheme: "Runner",
export_method: "app-store",
export_options: "ExportOptions.plist",
)
upload_to_testflight(
api_key: api_key,
skip_waiting_for_build_processing: true,
changelog: File.read("../CHANGELOG_CURRENT.txt"),
)
upload_symbols_to_crashlytics(gsp_path: "Runner/GoogleService-Info.plist")
end
desc "Submit latest TestFlight build to App Store Review"
lane :release do
deliver(
api_key: asc_api_key,
submit_for_review: true,
automatic_release: false,
phased_release: true,
force: true,
precheck_include_in_app_purchases: false,
)
end
def asc_api_key
app_store_connect_api_key(
key_id: ENV["APP_STORE_CONNECT_KEY_ID"],
issuer_id: ENV["APP_STORE_CONNECT_ISSUER_ID"],
key_content: ENV["APP_STORE_CONNECT_KEY_CONTENT"],
is_key_content_base64: true,
duration: 1200,
)
end
end
6. Android Fastfile
default_platform(:android)
platform :android do
desc "Build AAB and upload to Play internal track"
lane :internal do
gradle(task: "bundleRelease",
properties: {
"versionName" => ENV["VERSION_NAME"],
"versionCode" => ENV["GITHUB_RUN_NUMBER"],
})
upload_to_play_store(
track: "internal",
aab: "app/build/outputs/bundle/release/app-release.aab",
json_key_data: ENV["PLAY_SERVICE_ACCOUNT_JSON"],
release_status: "completed",
)
end
desc "Promote internal to production at 5%"
lane :promote_to_production do |options|
upload_to_play_store(
track: "internal",
track_promote_to: "production",
rollout: options[:rollout] || "0.05",
skip_upload_aab: true,
json_key_data: ENV["PLAY_SERVICE_ACCOUNT_JSON"],
)
end
end
7. Matchfile
git_url("[email protected]:acme/certificates.git")
storage_mode("git")
type("appstore")
app_identifier(["com.acme.app"])
Encrypted with MATCH_PASSWORD. Store the password in CI secrets.
8. Environment Variables on CI
Minimum env set for a release run:
APP_STORE_CONNECT_KEY_IDAPP_STORE_CONNECT_ISSUER_IDAPP_STORE_CONNECT_KEY_CONTENT(base64.p8)MATCH_PASSWORDMATCH_GIT_BASIC_AUTHORIZATIONor SSH deploy keyPLAY_SERVICE_ACCOUNT_JSONKEYSTORE_PATH/KEYSTORE_PASSWORD/KEY_ALIAS/KEY_PASSWORD
9. Common Plugins
ios/fastlane/Pluginfile:
gem "fastlane-plugin-versioning"
gem "fastlane-plugin-firebase_app_distribution"
gem "fastlane-plugin-sentry"
Install: bundle exec fastlane add_plugin firebase_app_distribution.
10. Running Locally vs CI
- Locally:
bundle exec fastlane ios beta— uses your keychain, real Apple ID. - CI: the same command —
setup_cicreates a scoped temporary keychain;match --readonlynever writes to the certs repo.
This parity is the main reason to use Fastlane. Do not introduce CI-only scripts that bypass lanes.
11. Anti-Patterns
- One giant Fastfile at the repo root mixing platforms.
- Using
--generate_apple_certsin CI (can regenerate the distribution cert and break other teams). - Hardcoding paths to build artefacts; use Fastlane variables (
SharedValues::IPA_OUTPUT_PATH). - Running
matchinforcemode on CI. Alwaysreadonly: true.
12. Checklist
-
Gemfile+Gemfile.lockcommitted; Fastlane pinned. - Per-platform
fastlane/directories withAppfile,Fastfile,Matchfile. - ASC API key used, not Apple ID + password.
-
match readonly: truein every CI lane. -
setup_cicalled before signing on CI. - Same lane names run locally and in CI, producing identical artefacts.
- Required env vars documented in
docs/release-env.md.