Last modified: May 03, 2026
This article is written in: πΊπΈ
The macOS build workflow includes automatic code signing and notarization to ensure the application can be opened on macOS without Gatekeeper warnings. This process:
.app bundle with a Developer ID Application certificateTo enable signing and notarization, you need:
.p12 formatxxxx-xxxx-xxxx-xxxx)A1B2C3D4E5)Add the following secrets to your GitHub repository:
| Secret Name | Description | How to Get Value |
MACOS_CERTIFICATE |
Base64-encoded .p12 certificate | Run: base64 -i certificate.p12 | pbcopy (copies to clipboard) |
MACOS_CERTIFICATE_PASSWORD |
Password for the .p12 file | The password you set when exporting the certificate |
MACOS_KEYCHAIN_PASSWORD |
Password for temporary keychain | Any strong random password (e.g., openssl rand -base64 32) |
APPLE_ID |
Your Apple ID email | Your Apple Developer account email |
APPLE_ID_PASSWORD |
App-specific password | The password from Step 3 (with dashes) |
APPLE_TEAM_ID |
Your Apple Developer Team ID | The 10-character code from Step 4 |
# On macOS, encode and copy to clipboard
base64 -i /path/to/certificate.p12 | pbcopy
# On Linux
base64 -w 0 /path/to/certificate.p12
When all required secrets are present:
.app is signed with your Developer IDIf secrets are not configured:
This graceful fallback allows: - Testing builds without certificates - Community contributors to build without Apple Developer accounts - Quick iterations during development
If only signing credentials are present (no notarization credentials):
If notarization fails, the script will: 1. Show the error message from Apple 2. Attempt to retrieve detailed logs 3. Exit with an error code
Common issues: - Invalid code signature: Ensure frameworks are signed before the main app - Hardened runtime violations: Add appropriate entitlements if needed - Invalid credentials: Verify Apple ID, password, and Team ID
Error: "Developer ID Application certificate not found in keychain"
Solutions: - Verify the certificate is a Developer ID Application certificate - Ensure the certificate is not expired - Check that the .p12 file contains the certificate and private key
Error: "User interaction is not allowed"
Solutions:
- Ensure MACOS_KEYCHAIN_PASSWORD secret is set
- Check that the keychain is properly unlocked in the script
GitHub Secrets are: - β Encrypted at rest - β Only exposed to GitHub Actions runners - β Never logged or exposed in outputs - β Redacted in build logs
The signing script: - Creates a temporary keychain for signing - Immediately deletes certificates after use - Cleans up keychains on completion or failure
Developer ID Application certificates: - Valid for 5 years - Must be renewed before expiration - Apple will email reminders before expiration
Remember to: - Update the certificate in GitHub Secrets before expiration - Test the new certificate before the old one expires
You can test the signing script locally:
# Set environment variables
export MACOS_CERTIFICATE="$(base64 -i certificate.p12)"
export MACOS_CERTIFICATE_PASSWORD="your-password"
export MACOS_KEYCHAIN_PASSWORD="temp-password"
export APPLE_ID="your@email.com"
export APPLE_ID_PASSWORD="xxxx-xxxx-xxxx-xxxx"
export APPLE_TEAM_ID="A1B2C3D4E5"
# Run the script
./scripts/sign-and-notarize-macos.sh build/bin/standard_of_iron.app standard_of_iron-macos.dmg
# Check code signature
codesign --verify --deep --strict --verbose=2 standard_of_iron.app
# Check Gatekeeper assessment
spctl --assess --type execute --verbose standard_of_iron.app
# Verify stapled ticket
stapler validate standard_of_iron-macos.dmg
To test the fallback behavior:
# Run without environment variables
./scripts/sign-and-notarize-macos.sh build/bin/standard_of_iron.app standard_of_iron-macos.dmg
Expected output: "macOS signing credentials not found, skipping signing and notarization"
If you encounter issues: