In Flutter, what does flutter build ipa produce, and how does that output reach App Store Connect?
answer
- archive first, then export
- build/ios/archive holds the .xcarchive
- build/ios/ipa holds the .ipa
- --export-method defaults to app-store
- Transporter, xcrun altool or Xcode
basics
~10 sflutter build ipa archives the app in release mode into an .xcarchive under build/ios/archive, then exports a signed App Store .ipa into build/ios/ipa; you upload that .ipa with Transporter, xcrun altool or Xcode.
solid answer
~30 s`flutter build ipa` (alias `xcarchive`) runs only on macOS. It builds in release mode by default and does two things: an Xcode **archive** into `build/ios/archive/Runner.xcarchive`, then `xcodebuild -exportArchive` into `build/ios/ipa`. The export method defaults to `app-store`, which the tool passes to Xcode 15.4+ as `app-store-connect`; `--export-method ad-hoc|development|enterprise` picks another channel, and `--export-options-plist` hands Xcode a full `ExportOptions.plist` instead. The command does not upload anything: you drag the `.ipa` into Apple's Transporter app, run `xcrun altool --upload-app`, or open the archive in Xcode and use Distribute App.
code
bash · 9 linesflutter build ipa
ls build/ios/archive build/ios/ipa
flutter build ipa --export-method ad-hoc
flutter build ipa --export-options-plist=ios/ExportOptions.plist
xcrun altool --upload-app --type ios -f build/ios/ipa/*.ipa \
--apiKey "$ASC_KEY_ID" --apiIssuer "$ASC_ISSUER_ID"go deeper
Recall the two outputs and their folders: the .xcarchive under build/ios/archive and the .ipa under build/ios/ipa, and that uploading is a separate step.
Explain the archive, validate and export stages, the default app-store method, the Xcode 15.4 renaming, and why --export-options-plist and --export-method cannot be combined.
Show you know a failed export still exits zero, so a pipeline must check for the .ipa, and that --no-codesign stops at the archive.
Discuss where the IPA should be produced and signed in a release process, and what a local archive, a CI archive and an Xcode Organizer export each trade in reproducibility.
## What the command is `flutter build ipa` is the Flutter CLI's release path for iOS. Its source describes it as building "an iOS archive bundle and IPA for distribution", it accepts `xcarchive` as an alias, and it can only run on a **macOS host** because it drives `xcodebuild`. Like the other `flutter build` subcommands it defaults to **release mode**; `--profile` and `--debug` exist but are not what you ship. Two artefact types matter: - **`.xcarchive`** — an Xcode archive: the compiled, signed `.app` plus its debug symbols and metadata. Xcode's Organizer can open it, validate it and distribute it. - **`.ipa`** — the iOS App Store Package, a zip of the `.app` re-signed for one distribution method. This is the file App Store Connect accepts. ## The two stages 1. **Archive.** The tool compiles the Dart code ahead of time, builds the Runner Xcode project with the Release configuration and archives it into `build/ios/archive/Runner.xcarchive` (the name follows the product name). Signing happens here with whatever the Runner target's Signing & Capabilities settings say. 2. **Validate.** It reads the archived `Info.plist` and prints an **App Settings Validation** summary: version number, build number, display name, deployment target and bundle identifier, flagging a missing value, a leftover `com.example` bundle ID, and placeholder app icons or launch images. 3. **Export.** It runs `xcrun xcodebuild -exportArchive` with `-allowProvisioningUpdates` and `-allowProvisioningDeviceRegistration`, writing the `.ipa` into `build/ios/ipa`. Unless you pass a plist, it writes a temporary `ExportOptions.plist` containing the export method. With `--no-codesign` the tool stops after the archive and prints that it is skipping the IPA: useful when a later step signs, useless for an upload. ## Export methods | `--export-method` | Meant for | Name sent to Xcode 15.4+ | |---|---|---| | `app-store` (default) | App Store Connect and TestFlight | `app-store-connect` | | `ad-hoc` | a limited set of test devices; needs a distribution certificate | `release-testing` | | `development` | devices registered on the developer account | `debugging` | | `enterprise` | Apple Developer Enterprise Program apps | `enterprise` | Xcode 15.4 renamed the first three methods, and the Flutter tool translates the old names when it detects that Xcode (a fix that shipped in Flutter 3.24). `--export-options-plist path/to/ExportOptions.plist` replaces the whole generated file; it is **rejected together with `--export-method`**, and the method is then read from the plist's `method` key. A common way to get such a plist is to distribute once from Xcode, which saves an `ExportOptions.plist` next to the exported IPA. ## Uploading to App Store Connect The command ends at a file; after an App Store export it prints the two upload routes: - **Transporter** — drag `build/ios/ipa/*.ipa` into Apple's Transporter macOS app. - **`xcrun altool --upload-app --type ios -f build/ios/ipa/*.ipa --apiKey … --apiIssuer …`** — the scriptable route, authenticated with an App Store Connect API key. - **Xcode** — open the `.xcarchive`, click Validate App, then Distribute App. App Store Connect then processes the build; once it finishes, the build can go to TestFlight or to review. ## When the export step fails If `-exportArchive` fails (a missing distribution profile is the usual cause), the tool prints only the `error:` lines from Xcode, tells you to open the archive in Xcode, and **still exits successfully**, because the archive itself succeeded. A CI job that only checks the exit code will therefore report green with no `.ipa`; checking that `build/ios/ipa` contains a file is the safer gate. ## A typical release sequence Putting the pieces together, a first App Store release of a Flutter app usually runs in this order: 1. Set the bundle identifier, display name, team and signing in Xcode on the Runner target, and replace the placeholder icon and launch image. 2. Run `flutter build ipa` and read the App Settings Validation summary; fix anything reported as missing or still set to a template value. 3. Confirm that `build/ios/ipa` contains an `.ipa`, not just that the command exited. 4. Upload with Transporter, `xcrun altool` or Xcode, then wait for App Store Connect to finish processing before choosing TestFlight or review. Re-running the command overwrites both folders, so keep a copy of any archive you uploaded if you want its symbols and exact binary later. Building from Xcode's own Product > Archive menu produces an equivalent archive, but going through the Flutter tool keeps the Dart build settings, the version from `pubspec.yaml` and the validation summary in one reproducible command. ## Common misconceptions - The command does **not** upload; it only produces files. - The outputs live under `build/ios/`, not under the Android `build/app/outputs` tree. - The default is an **App Store** export in release mode, not a development build. - The validation summary is a sanity check of a few `Info.plist` values and assets, not App Review: it does not look at purpose strings or the privacy manifest.
- Can flutter build ipa run on a Linux or Windows CI runner?No. The command is documented in its source as macOS-only because both stages shell out to `xcodebuild`: the archive and the `-exportArchive` step. A Linux runner can run tests and build Android; the iOS archive needs a Mac with Xcode installed.
- The export step failed but the CI job is green; how can that happen?When `xcodebuild -exportArchive` fails, `flutter build ipa` prints the `error:` lines, points you at the archive to distribute from Xcode, and returns success because the `.xcarchive` was produced. Add a step that fails when `build/ios/ipa` holds no `.ipa`.
- Does the App Settings Validation summary mean the build will pass review?No. It only reports version, build number, display name, deployment target and bundle ID, warns on a `com.example` bundle ID, and flags placeholder icons and launch images. Purpose strings, the privacy manifest and review guidelines are not checked there.
saying these in an interview costs you the question
- flutter build ipa uploads the build to App Store Connect by itself.
- The .ipa is written to build/app/outputs next to the Android bundle.
- flutter build ipa can run on a Linux runner if Xcode is not needed.
- With no flags it produces a debug, development-signed IPA.
- A failed IPA export makes the whole command exit with an error.
- You can pass --export-method and --export-options-plist together to override one key.