Sign and notarize
Archive a release build
Create an Xcode archive from a clean release configuration and preserve the archive as the input to export and notarization.
12 minute lesson
An Xcode archive is the frozen output of one release build: the app, its debug symbols, and metadata about how it was produced. Everything downstream — export, signing, notarization, crash symbolication — derives from it.
In Xcode the flow is Product → Archive, which builds the release configuration and opens the result in Organizer. From a script, it’s two xcodebuild steps. First, archive:
xcodebuild -project Notes.xcodeproj \
-scheme Notes \
-configuration Release \
archive -archivePath build/Notes.xcarchive
Then export a Developer ID-signed app from the archive. The export step reads a small plist that names the distribution method:
<key>method</key>
<string>developer-id</string>
xcodebuild -exportArchive \
-archivePath build/Notes.xcarchive \
-exportOptionsPlist ExportOptions.plist \
-exportPath build/export
The signed app lands in build/export/Notes.app.
Before distributing, inspect what you got: the version and build, the signing identity, the entitlements, the embedded frameworks. Fix problems by changing the project and archiving again. Never edit the exported app by hand — you learned why in the bundle lesson. Edits break the seal.
Keep the archive. It contains the dSYM debug symbol bundles that turn the addresses in a user’s crash report back into function names and line numbers. Lose the archive and that crash report from version 1.2.0 becomes hexadecimal soup.
Record alongside it the source commit, the Xcode version, and the export options. The archive is the bridge between “this commit” and “these shipped bytes”, and the record is what makes the bridge usable months later.
A subtle failure: archiving with uncommitted local changes. The archive says 1.2.0, your repository says 1.2.0, but they differ by the three lines you never committed. Archive from a clean working tree, ideally in CI.
Lesson completed