4.7 KiB
Release Signing and Notarization
Goal
Turn Atlas for Mac from an installable local build into a publicly distributable macOS release.
Required Credentials
Developer ID Applicationcertificate for app signingDeveloper ID Installercertificate for installer signingnotarytoolkeychain profile for notarization
Environment Variables Used by Packaging
ATLAS_CODESIGN_IDENTITYATLAS_CODESIGN_KEYCHAINATLAS_INSTALLER_SIGN_IDENTITYATLAS_NOTARY_PROFILEATLAS_NOTARY_KEYCHAIN(optional; required when the notary profile lives in a non-default keychain such as CI)
Stable Local Signing
For local development machines that do not have Apple release certificates yet, provision a stable app-signing identity once:
./scripts/atlas/ensure-local-signing-identity.sh
After that, ./scripts/atlas/package-native.sh automatically prefers this local identity over ad hoc signing. This keeps the installed app bundle identity stable enough for macOS permission prompts and TCC decisions to behave consistently across rebuilds.
Notes:
- This local identity is only for internal/dev packaging.
.pkgsigning and notarization still require AppleDeveloper ID Installerandnotarytoolcredentials.- The local identity is stored in a dedicated keychain at
~/Library/Keychains/AtlasLocalSigning.keychain-dbunless overridden by env vars.
Preflight
Run:
./scripts/atlas/signing-preflight.sh
If preflight passes, the current machine is ready for signed packaging.
Version Prep
Before pushing a release tag, align the app version, build number, and changelog skeleton:
./scripts/atlas/prepare-release.sh 1.0.3
Optional arguments:
./scripts/atlas/prepare-release.sh 1.0.3 4 2026-03-23
This updates:
project.ymlApps/AtlasApp/Sources/AtlasApp/AtlasAppModel.swiftCHANGELOG.md
The script increments CURRENT_PROJECT_VERSION automatically when you omit the build number. Review the new changelog section before creating the V1.0.3 tag.
Signed Packaging
Run:
ATLAS_CODESIGN_IDENTITY="Developer ID Application: <Name> (<TEAMID>)" \
ATLAS_INSTALLER_SIGN_IDENTITY="Developer ID Installer: <Name> (<TEAMID>)" \
ATLAS_NOTARY_PROFILE="<profile-name>" \
./scripts/atlas/package-native.sh
This signs the app bundle, emits .zip, .dmg, and .pkg, submits artifacts for notarization, and staples results when credentials are available.
If the notary profile is stored in a non-default keychain, also set:
ATLAS_NOTARY_KEYCHAIN="/path/to/release.keychain-db"
Install Verification
After packaging, validate the DMG installation path with:
KEEP_INSTALLED_APP=1 ./scripts/atlas/verify-dmg-install.sh
GitHub Tag Release Automation
Tagged pushes matching V* now reuse the same packaging flow in CI and attach native release assets to the GitHub Release created by .github/workflows/release.yml.
Required GitHub Actions secrets:
ATLAS_RELEASE_APP_CERT_P12_BASE64ATLAS_RELEASE_APP_CERT_P12_PASSWORDATLAS_RELEASE_INSTALLER_CERT_P12_BASE64ATLAS_RELEASE_INSTALLER_CERT_P12_PASSWORDATLAS_NOTARY_KEY_IDATLAS_NOTARY_ISSUER_IDfor Team API keys; omit only if you intentionally use an Individual API keyATLAS_NOTARY_API_KEY_BASE64
If those secrets are present, the workflow bootstraps a temporary keychain with ./scripts/atlas/setup-release-signing-ci.sh, stores a notarytool profile there, derives ATLAS_VERSION from the pushed tag name, then runs ./scripts/atlas/package-native.sh.
If those secrets are missing, the workflow automatically falls back to:
./scripts/atlas/ensure-local-signing-identity.sh- local development signing for the app bundle
- unsigned installer packaging if no installer identity exists
- no notarization
- GitHub Release marked as
prerelease
Release flow:
git tag -a V1.0.3 -m "Release V1.0.3"
git push origin V1.0.3
That tag creates one GitHub Release containing:
- legacy Go binaries and Homebrew tarballs from the existing release pipeline
Atlas-for-Mac.zipAtlas-for-Mac.dmgAtlas-for-Mac.pkg- native and aggregate SHA-256 checksum files
Packaging mode by credential state:
Developer ID secrets present-> signed and notarized native assets, normal GitHub ReleaseDeveloper ID secrets missing-> development-signed native assets, GitHubprerelease
Current Repo State
- Internal packaging can now use a stable local app-signing identity instead of ad hoc signing.
- Signed/notarized release artifacts remain blocked only by missing Apple release credentials on this machine.
- Tagged GitHub Releases can still publish development-mode native assets without those credentials.