Signing & notarization
To ship a macOS app to other people without Gatekeeper warnings, it must be signed with an Apple Developer ID and notarized by Apple. This is the DIY path: you hold the certificate and the CLI runs the tools. If you would rather not, the Platform does this for you.
What you need
- A paid Apple Developer Program membership.
- A Developer ID Application certificate in your login keychain.
- An app-specific password for
notarytool, or a stored notary profile.
Put the secrets in .env.release
every release reads Apple's secrets from a dotenv file next to your app,
.env.release by default. Keep it out of git.
APPLE_SIGNING_IDENTITY="Developer ID Application: Your Name (TEAMID)"
APPLE_ID="[email protected]"
APPLE_PASSWORD="abcd-efgh-ijkl-mnop" # an app-specific password, not your Apple password
APPLE_TEAM_ID="TEAMID"
If you have already stored credentials in your keychain with
xcrun notarytool store-credentials, name the profile instead and drop the last
three:
APPLE_SIGNING_IDENTITY="Developer ID Application: Your Name (TEAMID)"
NOTARY_PROFILE="notes-release"
You can export the same variables in your shell or CI instead of using a file.
Release
One command builds, signs every binary inside the bundle, notarizes with Apple, staples the ticket, and writes a receipt:
every release
every release --env-file config/apple.env # a different dotenv file
every release --skip-build # sign what is already in dist/
It leaves you with:
Notes.app # signed, notarized, stapled
Notes.zip # the distributable archive
release.json # the build receipt
release.json records the app, version, target, channel, artifact checksum, and
the signing facts. every publish reads it to ship the
release to your update bucket.
Check the signature yourself any time:
codesign --verify --deep --strict --verbose=2 dist/Notes.app
xcrun stapler validate dist/Notes.app
Once stapled, the .app opens cleanly on any Mac. No right-click "Open", no
warnings.
Distribute
Ship the .zip, wrap the .app in a .dmg, or publish it to your own update
feed with every publish. That is it: built, signed,
notarized, and shipped from your own machine.
Managing certificates and app-specific passwords across a team gets old fast. The Platform's credential custody keeps them in one place and injects them into builds at the moment a build needs them.