This guide covers the GitHub secrets required to code-sign and notarize the GQuick macOS app in CI.
Create these secrets in Settings > Secrets and variables > Actions > Repository secrets.
Do not put these only under Settings > Environments. Environment secrets require the workflow job to attach to that exact environment, and if GitHub does not attach the environment, every secret resolves as empty. Repository secrets are available directly to this build workflow on trusted
push, tag, andworkflow_dispatchruns.
| Secret | Description |
|---|---|
APPLE_CERTIFICATE |
Base64-encoded .p12 Developer ID Application certificate |
APPLE_CERTIFICATE_PASSWORD |
Password used when exporting the .p12 |
APPLE_SIGNING_IDENTITY |
Certificate name shown in Keychain (e.g., Developer ID Application: Your Name (TEAMID)) |
APPLE_ID |
Apple ID email used for notarization |
APPLE_PASSWORD |
App-specific password for notarization |
APPLE_TEAM_ID |
Apple Developer Team ID (10-character string) |
- Open Keychain Access on a Mac.
- In My Certificates, find your Developer ID Application certificate.
- Expand it and select both the certificate and its private key.
- Right-click > Export 2 items…
- Choose format Personal Information Exchange (.p12) and save as
certificate.p12. - Set a strong password when prompted — this becomes
APPLE_CERTIFICATE_PASSWORD.
Important: Strip newlines from the base64 output. Line-wrapped base64 will cause security import to fail in CI.
Run this in Terminal:
base64 -i certificate.p12 | tr -d '\n' | pbcopyPaste the output into the APPLE_CERTIFICATE GitHub secret.
In Terminal, run:
security find-identity -v -p codesigningCopy the full name of your Developer ID Application identity (including the Team ID in parentheses) into APPLE_SIGNING_IDENTITY.
- Visit appleid.apple.com.
- Sign in and go to App-Specific Passwords.
- Generate a new password.
- Save it as the
APPLE_PASSWORDsecret.
- Go to developer.apple.com/account.
- Select Membership details from the sidebar.
- Copy the Team ID (10 characters) into
APPLE_TEAM_ID.
This error means Tauri could not import the .p12 into the CI keychain. Common causes:
| Cause | Fix |
|---|---|
| Base64 has line breaks | Re-encode with base64 -i certificate.p12 | tr -d '\n' | pbcopy and re-paste the secret |
| Wrong certificate type | Must be Developer ID Application, not "Apple Development" or "Mac Developer" |
| Missing private key | Export both the certificate and its private key from Keychain Access |
| Wrong password | Verify APPLE_CERTIFICATE_PASSWORD matches the password you set when exporting the .p12 |
| Secret not set | Check the secret exists and is not empty in Settings > Secrets and variables > Actions |
# Create a temp keychain and try importing
security create-keychain -p "temp123" /tmp/test.keychain
security unlock-keychain -p "temp123" /tmp/test.keychain
security import certificate.p12 -P "YOUR_PASSWORD_HERE" -k /tmp/test.keychain
security find-identity -v -p codesigning /tmp/test.keychainIf this fails with the same error, your password is wrong or the .p12 is missing the private key. Re-export from Keychain Access.
Decode the secret locally and inspect it:
echo "$APPLE_CERTIFICATE" | base64 -d -o certificate_check.p12
# Verify it's a valid PKCS#12 (use -legacy on OpenSSL 3.x)
openssl pkcs12 -in certificate_check.p12 -info -noout -legacyYou should see PKCS7 Encrypted data and a shrouded keybag. If the file is corrupt, re-export and re-encode.
Note: On macOS with OpenSSL 3.x, you may see
unsupported: Algorithm (RC2-40-CBC)without-legacy. This is normal — the certificate is still valid, OpenSSL just can't decrypt the legacy encryption. The macOSsecuritytool handles this fine.
These secrets are injected only into the macOS ARM64 build job. Tauri v2 reads them automatically during tauri build to sign the .app bundle and submit it for notarization. No changes to tauri.conf.json are required.
The beforeBundleCommand OCR bundling script also reads APPLE_SIGNING_IDENTITY. When present, it signs bundled Tesseract/OCR dylibs in Contents/Resources/Frameworks with the Developer ID identity and a secure timestamp before Tauri signs and notarizes the final app. Local builds without this secret continue to use ad-hoc signing.
After tauri build, CI performs a final macOS-only notarization pass over the generated .dmg: it verifies the .app signature, signs the .dmg with the Developer ID Application identity, submits the .dmg with notarytool --wait, staples the notarization ticket, and validates the stapled installer with Gatekeeper. This ensures the uploaded release .dmg is the notarized/stapled artifact users install from.
CI recreates the .dmg from the verified signed .app bundle with ditto before final DMG notarization. This avoids distributing a Tauri-generated DMG that may contain a pre-final-signing copy of the app bundle.
Download and install the signed .dmg artifact for macOS. Do not distribute or open the raw .app bundle from a GitHub Actions artifact ZIP; re-zipping .app directories can break macOS code signature metadata and trigger "app is damaged" Gatekeeper errors.