Ship your app: code signing and provisioning, an archived build to App Store Connect, testing with TestFlight, submitting for review, and automating the pipeline with Fastlane.
Every iOS app must be code-signed so the system can verify its author and integrity. Signing combines a certificate (identifies you/your team) and a provisioning profile (ties an app id, devices, and capabilities together). Xcode’s automatic signing manages this for most teams; understanding the pieces helps when a build fails with the infamous signing errors.
Code signing = "who made this + has it been tampered with?"
Certificate identifies you / your team (development or distribution)
App ID unique bundle identifier (com.you.MyApp) + capabilities
Provisioning profile ties certificate + App ID + (dev) devices together
Entitlements capabilities the app is allowed (push, iCloud, ...)
Xcode "Automatically manage signing" handles most of this. When a build fails
with a signing error, one of these four is out of sync — that's where to look.To distribute, you create an Archive — a release build — and upload it to App Store Connect, Apple’s web console for managing apps. From there a build can go to TestFlight or App Store review. You bump the build number every upload. This archive-and-upload step is the gateway from your machine to Apple’s distribution system.
# from Xcode: Product > Archive -> Organizer > Distribute App -> App Store Connect
# or via command line (what CI uses):
xcodebuild -scheme MyApp -configuration Release \
-archivePath build/MyApp.xcarchive archive
xcodebuild -exportArchive -archivePath build/MyApp.xcarchive \
-exportPath build/ -exportOptionsPlist ExportOptions.plist
# then upload the resulting .ipa to App Store Connect (Transporter / altool / Fastlane).
# bump CFBundleVersion (build number) on every upload.Before release you distribute builds to testers with TestFlight — internal testers get them instantly, external testers after a light review. When ready, you submit for App Store review, where Apple checks the app against its guidelines; approval can take a day or so. Use TestFlight to catch problems with real users first, then submit, ideally with a phased release.
Distribution flow:
Archive -> App Store Connect
|
TestFlight
internal testers (your team) -> instant
external testers (up to 10k) -> quick "beta app review" first
|
Submit for App Store REVIEW
Apple checks vs. the App Review Guidelines (privacy, crashes, IAP, content)
approval typically ~1 day; rejections come with reasons to fix
|
Release: manual, scheduled, or PHASED rollout (ramp over 7 days)
Beta-test on TestFlight first; submit a build real users already exercised.Doing signing, building, and uploading by hand is slow and error-prone, so teams automate with Fastlane — a tool that scripts the whole release in "lanes" and manages signing certificates across a team (via match). Wired into CI (GitHub Actions, etc.), a push can produce a TestFlight build automatically. Automation is what makes frequent, reliable releases practical.
# Fastfile — define reusable "lanes" for the release pipeline
lane :beta do
build_app(scheme: "MyApp") # archive + export
upload_to_testflight # push to TestFlight
end
lane :release do
build_app(scheme: "MyApp")
upload_to_app_store(submit_for_review: true)
end
# run it: fastlane beta
# 'match' syncs signing certs/profiles across the team + CI.
# wire a lane into CI (see the GitHub course) so a push -> a TestFlight build.