Repository navigation
Add archive->IPA export options to "flutter build ipa" to avoid opening Xcode during iOS app distribution #97179
Description
To distribute an app, currently users need to run flutter build ipa to create an archive, then open the archive in Xcode to create an IPA through its UI wizard, which can then be uploaded to the App Store.
Under the covers, the Xcode wizard UI generates a plist that says how the archive should become an IPA (signing, thinning, stripping, is it for the App Store or local testing, etc). Currently, flutter build ipa --export-options-plist lets developers skip the wizard and pass that already-populated plist into Flutter so Xcode doesn't need to be opened.
https://docs.flutter.dev/deployment/ios#create-a-build-archive-with-xcode says:
Note: When you export your app at the end of Distribute App, Xcode will create a directory containing an IPA of your app and an ExportOptions.plist file. You can create new IPAs with the same options without launching Xcode by running flutter build ipa --export-options-plist=path/to/ExportOptions.plist. See xcodebuild -h for details about the keys in this property list.
Add options to the command to create the plist so the user doesn't have to craft a plist, or figure out how to otherwise generate one.
Let's start with the most obvious option of either exporting to the App Store, exporting as ad-hoc (uses the distribution certificate, appropriate for public testing), and development (only works on devices registered with the developer account). I don't think we need to handle sophisticated cases yet. Xcode already provides some reasonable defaults. If users have anything more complicated they can keep using --export-options-plist or go through the Xcode wizard.
Available keys for "xcodebuild -exportOptionsPlist"
Available keys for -exportOptionsPlist:
compileBitcode : Bool
For non-App Store exports, should Xcode re-compile the app from bitcode? Defaults to YES.
destination : String
Determines whether the app is exported locally or uploaded to Apple. Options are export or upload. The available options vary based on the selected distribution method. Defaults to export.
distributionBundleIdentifier : String
Reformat archive to focus on eligible target bundle identifier.
embedOnDemandResourcesAssetPacksInBundle : Bool
For non-App Store exports, if the app uses On Demand Resources and this is YES, asset packs are embedded in the app bundle so that the app can be tested without a server to host asset packs. Defaults to YES unless onDemandResourcesAssetPacksBaseURL is specified.
generateAppStoreInformation : Bool
For App Store exports, should Xcode generate App Store Information for uploading with iTMSTransporter? Defaults to NO.
iCloudContainerEnvironment : String
If the app is using CloudKit, this configures the "com.apple.developer.icloud-container-environment" entitlement. Available options vary depending on the type of provisioning profile used, but may include: Development and Production.
installerSigningCertificate : String
For manual signing only. Provide a certificate name, SHA-1 hash, or automatic selector to use for signing. Automatic selectors allow Xcode to pick the newest installed certificate of a particular type. The available automatic selectors are "Developer ID Installer" and "Mac Installer Distribution". Defaults to an automatic certificate selector matching the current distribution method.
manageAppVersionAndBuildNumber
Should Xcode manage the app's build number when uploading to App Store Connect? Defaults to YES.
manifest : Dictionary
For non-App Store exports, users can download your app over the web by opening your distribution manifest file in a web browser. To generate a distribution manifest, the value of this key should be a dictionary with three sub-keys: appURL, displayImageURL, fullSizeImageURL. The additional sub-key assetPackManifestURL is required when using on-demand resources.
method : String
Describes how Xcode should export the archive. Available options: app-store, validation, ad-hoc, package, enterprise, development, developer-id, and mac-application. The list of options varies based on the type of archive. Defaults to development.
onDemandResourcesAssetPacksBaseURL : String
For non-App Store exports, if the app uses On Demand Resources and embedOnDemandResourcesAssetPacksInBundle isn't YES, this should be a base URL specifying where asset packs are going to be hosted. This configures the app to download asset packs from the specified URL.
provisioningProfiles : Dictionary
For manual signing only. Specify the provisioning profile to use for each executable in your app. Keys in this dictionary are the bundle identifiers of executables; values are the provisioning profile name or UUID to use.
signingCertificate : String
For manual signing only. Provide a certificate name, SHA-1 hash, or automatic selector to use for signing. Automatic selectors allow Xcode to pick the newest installed certificate of a particular type. The available automatic selectors are "Mac App Distribution", "iOS Distribution", "iOS Developer", "Developer ID Application", "Apple Distribution", "Mac Developer", and "Apple Development". Defaults to an automatic certificate selector matching the current distribution method.
signingStyle : String
The signing style to use when re-signing the app for distribution. Options are manual or automatic. Apps that were automatically signed when archived can be signed manually or automatically during distribution, and default to automatic. Apps that were manually signed when archived must be manually signed during distribtion, so the value of signingStyle is ignored.
stripSwiftSymbols : Bool
Should symbols be stripped from Swift libraries in your IPA? Defaults to YES.
teamID : String
The Developer Portal team to use for this export. Defaults to the team used to build the archive.
thinning : String
For non-App Store exports, should Xcode thin the package for one or more device variants? Available options: <none> (Xcode produces a non-thinned universal app), <thin-for-all-variants> (Xcode produces a universal app and all available thinned variants), or a model identifier for a specific device (e.g. "iPhone7,1"). Defaults to <none>.
uploadBitcode : Bool
For App Store exports, should the package include bitcode? Defaults to YES.
uploadSymbols : Bool
For App Store exports, should the package include symbols? Defaults to YES.
Activity
jmagman commentedon Jan 25, 2022
More details in PR #97243
orestesgaolin commentedon Jan 26, 2022
It can be beneficial to reach out to Codemagic folks, as they already have figured out how to create export options file for store deployments.
jmagman commentedon Jan 26, 2022
#97243 uses the team and provisioning profile already set up in the Flutter Xcode project. It assumes automatically managed signing. It doesn't parse the provisioning profiles to figure out which method to use (ad-hoc, app-store, enterprise, development) (as CodeMagic does), it relies on the developer passing that in with the
--export-methodflag, defaulting toapp-store.So it's not automagical. But once you know the method to use it should work in a lot of cases Flutter developers will hit if their app it already building, and there's still the
--export-options-plistescape hatch.Unfortunately I don't have a lot of apps to test with, but the one I do have successfully created ad-hoc, app-store, and development IPAs on that PR.
jmagman commentedon Feb 2, 2022
#97243 has merged, and is available in the master channel. Would love to get feedback, please file issues if you see problems or have suggestions for improvements!
jmagman commentedon Feb 2, 2022
Follow-up to support
enterprisedistribution at #97611jmagman commentedon Feb 2, 2022
This was reverted #97614
github-actions commentedon Feb 17, 2022
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.