Publish to TestFlight and the App Store
Upload signed iOS builds to App Store Connect and follow them through TestFlight, review and phased release.
A pipeline can upload its signed IPA to App Store Connect at the end of a build. Oore then sends the build to TestFlight groups or attaches it to an App Store version, and records each step as a release.
All App Store Connect calls leave from the Direct macOS runner and the daemon
host. Allow outbound HTTPS to api.appstoreconnect.apple.com and Apple’s
upload hosts.
What you need
- Project developer, maintainer, instance admin, or instance owner access.
- iOS signing with an App Store Connect API key, as in Configure App Store Connect signing.
- The app already exists in App Store Connect with the pipeline’s bundle ID.
- For TestFlight, the names of the groups to distribute to.
1. Export for the App Store
- Open the pipeline and select Edit.
- Under Signing > iOS, set Distribution to App Store.
- Select Save changes.
- In API or Hybrid mode, saving discards the stored profiles and syncs App Store distribution profiles from App Store Connect.
- In Manual mode, upload an App Store distribution profile for each bundle ID. Oore rejects ad hoc or development profiles for this distribution.
Ad hoc and App Store profiles are not interchangeable, which is why changing the distribution replaces them. App Store IPAs cannot be installed from Oore. Testers install them through TestFlight.
2. Turn on publishing
- Open the pipeline’s Publishing tab.
- Under App Store Connect, check that the readiness list shows App Store distribution and App Store Connect API key as ready.
- Turn on Upload to App Store Connect after each successful build.
- For Destination, choose TestFlight or App Store.
- For TestFlight, enter the TestFlight groups.
- For the App Store, turn on Submit for review to submit the version once the build is attached. Then Phased release turns on Apple’s seven-day phased release.
- Under Release notes, add What to Test or What’s New text per locale.
- Under Export compliance, turn on Uses non-exempt encryption only if the app uses encryption beyond what iOS provides, such as HTTPS.
- Select Turn on App Store publishing, or Save changes when publishing was already on.
For automation, set "export_method": "app_store" with
PUT /v1/pipelines/{pipeline_id}/ios-signing, then send the publish settings
with PUT /v1/pipelines/{pipeline_id}/publish/app-store:
{
"enabled": true,
"destination": "testflight",
"testflight_groups": ["Internal QA"],
"release_notes": [{ "locale": "en-US", "whats_new": "Checkout fixes" }],
"uses_non_exempt_encryption": false
}For an App Store release, set "destination": "app_store", then
submit_for_review and phased_release as needed.
What happens after a build
- The runner uploads the IPA with
xcrun altooland the pipeline’s API key. The key is written to a private folder only for the upload. - The release starts in processing while Apple processes the build. Oore sets the export compliance answer once the build is valid.
- TestFlight: Oore adds the build to the groups and sets “What to Test”. Internal groups complete at once. External groups go to beta review (in review) and complete when Apple approves.
- App Store: Oore finds or creates the version, attaches the build, sets “What’s New” and, if asked, submits it (in review). When the version is live the release follows the phased release (rolling at 1, 2, 5, 10, 20, 50 and 100 percent) until it is complete.
Pause, resume and complete on the release change Apple’s phased release. Apple sets the percentages, so raising a step is not available.
Verify the result
- The build shows a succeeded
publish-app-storestep. - The build’s Release tab shows the release moving through Processing to Complete for internal TestFlight groups, or to In review for external groups and App Store submissions.
- App Store Connect shows the build in the TestFlight groups, or attached to the App Store version.
Store health on Home
After the first release, the daemon reads the app’s hang rate and launch time per version from App Store Connect power and performance metrics, using the App Store Connect key of the pipeline that made the newest release. Home shows the latest version’s numbers for a typical user on all iPhones. They refresh every six hours, and Apple only reports them once enough users have run a version.
Troubleshooting
The publish-app-store step fails
Fix the cause, such as an expired API key, then retry the upload. The stored IPA is uploaded again without rebuilding or re-signing.
The release fails with “has no app with bundle ID”
Create the app in App Store Connect with the same bundle ID, then rebuild.
The upload fails with a bundle version error
Each upload needs a higher build number than the last one for that version.
Pass --build-number to flutter build ipa.
“What’s New” is not set
Apple does not accept “What’s New” on an app’s first version. The release history notes the skipped field and the release continues.
Next step
Promote builds between environments to send a tested TestFlight build to the App Store without rebuilding it.