Fastlane
fastlaneDeployment35 lines
Scripted build, signing and store upload with shared certificate management.
Current — as published in v1.3.2. Written by hand for Fastlane, not generated.
The rule
Signing
- Signing identities come from
match, never from certificates generated per developer. - `readonly: true` in CI. Without it a runner can regenerate certificates and invalidate every other machine's.
setup_ciat the start of any lane that runs on a fresh runner, or keychain access fails.
Credentials
- Keystore,
.p8key and Play service account JSON are supplied by CI at runtime. None of them are committed. - The match repository is private, and its passphrase lives only in CI secrets.
- Use an App Store Connect API key, not an Apple ID password — CI cannot answer a 2FA prompt.
Reproducibility
- Pin fastlane in a
Gemfileand commitGemfile.lock. An unpinned gem update changes release behaviour without a code change. - A lane must behave the same locally and in CI. Branching on
ENV['CI']beyondsetup_ciusually means the lane is doing too much.
Releases
- Upload to a beta or internal track and promote deliberately.
- Increment build numbers automatically — duplicates are rejected after upload.
Never
- Never commit a signing credential of any kind.
- Never run a team release from a personal machine; it is unreproducible.
As each tool receives it
The same guidance, in the shape each editor reads. Cursor and Claude Code are written separately by hand; the rest are derived from the Cursor rule.
.cursor/rules/fastlane.mdc
---
description: Fastlane conventions
globs: ["fastlane/**", "ios/fastlane/**", "android/fastlane/**", "Gemfile"]
alwaysApply: false
---
# Fastlane
## Signing
- Signing identities come from `match`, never from certificates generated per
developer.
- **`readonly: true` in CI.** Without it a runner can regenerate certificates
and invalidate every other machine's.
- `setup_ci` at the start of any lane that runs on a fresh runner, or keychain
access fails.
## Credentials
- Keystore, `.p8` key and Play service account JSON are supplied by CI at
runtime. None of them are committed.
- The match repository is private, and its passphrase lives only in CI secrets.
- Use an App Store Connect API key, not an Apple ID password — CI cannot answer
a 2FA prompt.
## Reproducibility
- Pin fastlane in a `Gemfile` and commit `Gemfile.lock`. An unpinned gem update
changes release behaviour without a code change.
- A lane must behave the same locally and in CI. Branching on `ENV['CI']` beyond
`setup_ci` usually means the lane is doing too much.
## Releases
- Upload to a beta or internal track and promote deliberately.
- Increment build numbers automatically — duplicates are rejected after upload.
## Never
- Never commit a signing credential of any kind.
- Never run a team release from a personal machine; it is unreproducible.
What else this module writes
Selecting Fastlane contributes more than a rule file — all of it merged with every other module you pick, with conflicts resolved rather than duplicated.
Environment
MATCH_PASSWORDrequiredDecrypts the match certificate repository. CI secrets only.MATCH_GIT_URLrequiredPrivate repository holding encrypted signing identities.ASC_KEY_IDrequiredApp Store Connect API key id.ASC_ISSUER_IDrequiredApp Store Connect issuer id.ASC_KEY_CONTENTrequiredContents of the `.p8` key. Provided as a CI secret, never a file in git.PLAY_JSON_KEY_PATHoptionalPath to the Play service account JSON written by CI at runtime.ANDROID_KEYSTORE_PASSWORDoptionalRelease keystore password. CI secrets only.Folders
fastlane/
Related
Put this in your repo
Adds Fastlane to a project this tool generated, without starting over. Files you have hand-edited are left alone.