The release workflow (.github/workflows/release.yml) signs and notarizes the app when the
Apple secrets below are present, and otherwise falls back to ad-hoc signing (unsigned, not
notarizable) so releases still build. This page lists exactly what to collect and where each
value comes from.
Everything here comes from an Apple Developer Program account (99 USD per year). If you are
using someone else’s developer identity, note that the app ships under their name and team, and
the .p12 contains their private key, so treat these as sensitive credentials: store them only
as encrypted GitHub Actions secrets, never in the repository.
Two things are required: a signing certificate and a notarization credential. The certificate and the notarization credential must belong to the same Apple team.
| Secret | What it is |
|---|---|
APPLE_CERTIFICATE_P12 |
base64 of a Developer ID Application certificate exported as .p12 (certificate plus private key) |
APPLE_CERTIFICATE_PASSWORD |
the password set when exporting the .p12 |
APPLE_SIGNING_IDENTITY |
the identity string, for example Developer ID Application: Jane Doe (AB12CD34EF) |
The certificate must be of type Developer ID Application (for distribution outside the App Store). “Apple Development” and “Mac App Distribution” certificates will not work, and an ad-hoc signed build cannot be notarized.
To create and export it:
Developer ID Application: ... certificate and choose
Export, saving a .p12 and setting a password. That password is APPLE_CERTIFICATE_PASSWORD.Find the identity string for APPLE_SIGNING_IDENTITY with:
security find-identity -v -p codesigning
Style A, App Store Connect API key (recommended, does not expire, independently revocable):
| Secret | What it is |
|---|---|
APPLE_API_KEY_P8 |
base64 of the .p8 key file |
APPLE_API_KEY_ID |
the Key ID |
APPLE_API_ISSUER |
the Issuer ID (a UUID) |
Generate the key in App Store Connect > Users and Access > Integrations (Keys). The .p8 file
can only be downloaded once. The Key ID is shown next to the key, and the Issuer ID is at the top
of the Keys page.
Style B, Apple ID and app-specific password:
| Secret | What it is |
|---|---|
APPLE_ID |
the Apple ID email |
APPLE_APP_SPECIFIC_PASSWORD |
an app-specific password from appleid.apple.com > Sign-In and Security |
APPLE_TEAM_ID |
the 10-character team ID (from developer.apple.com membership, or the parentheses in the signing identity) |
notarize.sh uses the API key style if it is set, otherwise the Apple ID style.
HOMEBREW_TAP_TOKEN is a GitHub token for the homebrew-tap repository. It is only used on
stable tags (no hyphen) to update the Homebrew cask. Beta tags such as v2.5.3-beta.2 skip it.
Prepare the base64 values:
base64 -i DeveloperID.p12 | pbcopy # APPLE_CERTIFICATE_P12
base64 -i AuthKey_XXXX.p8 | pbcopy # APPLE_API_KEY_P8
Then set each secret, either in the repository UI (Settings > Secrets and variables > Actions) or with the GitHub CLI:
gh secret set APPLE_CERTIFICATE_P12 < <(base64 -i DeveloperID.p12)
gh secret set APPLE_CERTIFICATE_PASSWORD --body '...'
gh secret set APPLE_SIGNING_IDENTITY --body 'Developer ID Application: Jane Doe (AB12CD34EF)'
gh secret set APPLE_API_KEY_P8 < <(base64 -i AuthKey_XXXX.p8)
gh secret set APPLE_API_KEY_ID --body '...'
gh secret set APPLE_API_ISSUER --body '...'
Confirm what is already configured with gh secret list.
APPLE_CERTIFICATE_P12, APPLE_CERTIFICATE_PASSWORD, APPLE_SIGNING_IDENTITYWith those in place, a tag push produces a signed and notarized DMG. Without them, the workflow still builds and publishes an ad-hoc signed DMG.