In fastlane, which action uploads an iOS build to App Store Connect and which uploads an Android build to Google Play?
answer
- one upload action per store
- the famous names are aliases
- canonical names start with upload_to
- deliver is Apple, supply is Google
basics
~10 sfastlane's upload_to_app_store, nicknamed deliver, sends an iOS build and its listing metadata to App Store Connect. upload_to_play_store, nicknamed supply, sends an Android APK or AAB to Google Play. Both spellings work in a Fastfile.
solid answer
~40 sfastlane ships one upload action per store, and the famous names are aliases. `deliver` is an alias for **`upload_to_app_store`**, which pushes an iOS `.ipa` (or a macOS `.pkg`) plus listing metadata to **App Store Connect**. `supply` is an alias for **`upload_to_play_store`**, which pushes an Android `.apk` or `.aab` plus listing metadata to **Google Play**. They are not two flavours of one action: different artifacts, different credentials (Apple takes an App Store Connect API key, Google takes a service-account JSON key), and different option names for the same idea. Neither one builds anything — on iOS `gym`, canonically **`build_app`**, produces the `.ipa` the upload lane consumes, and on Android the Gradle build produces the `.aab`. Prefer the canonical `upload_to_*` names in a Fastfile; the aliases are only convenience.
code
ruby · 21 linesplatform :ios do
lane :release do
build_app(scheme: 'LlamaTrek')
upload_to_app_store(
app_identifier: 'com.llamatrek.booking',
api_key_path: './asc_key.json',
skip_screenshots: true
)
end
end
platform :android do
lane :release do
upload_to_play_store(
package_name: 'com.llamatrek.booking',
json_key: './play_key.json',
aab: './build/llamatrek.aab',
track: 'production'
)
end
endgo deeper
Be ready to name both actions and their nicknames without hesitating: upload_to_app_store is deliver, upload_to_play_store is supply. Knowing which store each one talks to is the whole question at this level.
Explain what each action actually transmits and which option carries the artifact: ipa or pkg on Apple's side, apk or aab on Google's, plus the metadata folder each one reads.
Show that you keep the upload step separate from the build step in a release lane, so a failed or rejected upload can be retried without rebuilding and re-signing the artifact.
Own the naming convention across the team's Fastfiles. Standardise on the canonical upload_to_ spelling, because a repository that mixes nicknames and canonical names costs every new engineer a lookup.
## Two stores, two upload actions fastlane is a monorepo of Ruby tools, and nearly every famous tool name is an **alias for a canonical `verb_noun` action**. Store submission has exactly two of them, one per store: - `deliver` is the alias for **`upload_to_app_store`** — the Apple side, talking to **App Store Connect** for an iOS or macOS app. - `supply` is the alias for **`upload_to_play_store`** — the Android side, talking to **Google Play**. Both spellings are legal in a Fastfile and run the same code, so nothing breaks if you write `deliver`. The canonical name is still the one worth learning: it says what the action does, it is the name the action's options are filed under, and a Fastfile that mixes nicknames with canonical names costs every later reader a lookup. ## Why both names exist Each tool began life as a standalone command-line program with its own name — `deliver`, `supply`, `gym`, `match` — and was later folded into fastlane as an action inside one repository. The old names survived as aliases so existing Fastfiles kept working, and they are still what most CI templates and blog posts say. That history matters at an interview: when a colleague says run deliver, they mean `upload_to_app_store`, and when a log line mentions `supply`, that is `upload_to_play_store` reporting. ## They are not two flavours of one action It is tempting to picture a single upload action with a platform switch. There is no such thing, because Apple and Google agree on almost nothing that matters to an upload: | | iOS — `upload_to_app_store` (`deliver`) | Android — `upload_to_play_store` (`supply`) | |---|---|---| | Destination | App Store Connect | Google Play | | Binary option | `ipa`, `pkg` | `apk`, `apk_paths`, `aab`, `aab_paths` | | Credential | App Store Connect **API key** (`api_key`, `api_key_path`) or an Apple ID `username` | Google **service-account JSON key** (`json_key`, `json_key_data`) | | App identity | `app_identifier` | `package_name` | | Version identity | `app_version`, `build_number` | `version_name`, `version_code` | | Release control | `submit_for_review`, `automatic_release`, `phased_release` | `track`, `release_status`, `rollout` | | Metadata | `metadata_path`, `screenshots_path`, localized keys such as `release_notes` | `metadata_path`, with `skip_upload_changelogs` and `skip_upload_images` | Even the switches that turn parts of the upload off are spelled differently: `skip_binary_upload`, `skip_metadata` and `skip_screenshots` on Apple's side; `skip_upload_apk`, `skip_upload_aab`, `skip_upload_metadata` and `skip_upload_screenshots` on Google's. Learning one action does not give you the other for free. ## Neither action builds anything Both are upload actions. For the llama-trekking booking app the artifact arrives from a separate step: 1. On iOS, `gym` — canonically **`build_app`** — archives and exports the signed `.ipa`. `upload_to_app_store` takes it through the `ipa` option, or picks it up from the lane context that `build_app` populates when the two run in the same lane. 2. On Android, the Gradle build produces the `.aab` (or `.apk`) and you hand its path to `upload_to_play_store` through `aab` or `apk`. Keeping build and upload as separate actions is what lets you retry a failed upload — a dropped connection, an expired credential — without rebuilding and re-signing the artifact. ## A minimal release lane for each platform ```ruby platform :ios do lane :release do build_app(scheme: 'LlamaTrek') upload_to_app_store( app_identifier: 'com.llamatrek.booking', api_key_path: './asc_key.json', skip_screenshots: true ) end end platform :android do lane :release do upload_to_play_store( package_name: 'com.llamatrek.booking', json_key: './play_key.json', aab: './build/llamatrek.aab', track: 'production' ) end end ``` The two lanes sit under different `platform` blocks, take different credentials and different artifacts, and share only the app itself. ## What the upload lanes do and do not decide - They **do** decide which bytes and which text are sent, under which identity, and with which release switches set. - They **do not** decide whether a release is approved, nor how each store's own review and console work — those belong to the stores, not to fastlane. - They **do not** capture the screenshots a listing carries; a separate capture step produces those image files and the upload action merely sends the folder it is pointed at. Say the canonical name at least once whenever you talk about either one. An answer that only ever says `deliver` and `supply` teaches two nicknames; an answer that says `upload_to_app_store` and `upload_to_play_store` teaches what the actions actually are.
- If a Fastfile calls both `deliver` and `upload_to_app_store`, are those two different actions?No. `deliver` is an alias that resolves to `upload_to_app_store`, so calling both runs the same action twice and uploads twice. Pick one spelling — the canonical `upload_to_app_store` — and keep the whole Fastfile consistent, because logs and error messages mix the two names and a reader who only knows the nickname gets lost.
- Can `upload_to_play_store` update the Google Play listing without shipping a new Android binary?Yes. Pass no `apk`/`aab`, or set `skip_upload_apk` and `skip_upload_aab`, and it updates the listing only; `skip_upload_metadata`, `skip_upload_changelogs` and `skip_upload_images` narrow it further. `upload_to_app_store` has the mirror-image switch for Apple, `skip_binary_upload`, for a metadata-only App Store Connect run.
saying these in an interview costs you the question
- Thinking deliver and supply are one action with a platform flag
- Believing upload_to_play_store can push an iOS ipa
- Assuming the upload action also builds and signs the binary
- Saying the aliases are dead names that no longer work
- Expecting one credential to work for both stores