CI secrets for release builds¶
The Release
workflow builds signed Windows and macOS installers (and unsigned Linux packages)
when you push a tag matching v* — for example after
npm run release -- patch.
On macOS, signing alone is not enough for Gatekeeper. After a clean download, macOS shows “Apple could not verify Consoleri.app…” until the app is notarized. This document covers signing and notarization secrets end to end.
Add secrets under the repository: Settings → Secrets and variables → Actions → New repository secret. Do not store certificates or Apple passwords in Variables — those values can appear in logs.
Secret overview¶
Secret |
Platform |
Purpose |
|---|---|---|
|
Windows |
Base64-encoded |
|
Windows |
Password for that certificate |
|
macOS |
Base64-encoded |
|
macOS |
Password for that certificate |
|
macOS notarization (preferred) |
Base64-encoded App Store Connect API |
|
macOS notarization (preferred) |
Key ID of that API key |
|
macOS notarization (preferred) |
Issuer ID (UUID) from App Store Connect |
|
macOS notarization (Apple ID method only) |
10-character Apple Team ID |
|
macOS notarization (alternative) |
Apple ID email |
|
macOS notarization (alternative) |
App-specific password for that Apple ID |
Linux builds do not need signing or notarization secrets. GITHUB_TOKEN is
provided by GitHub Actions automatically.
If a signing secret is missing, electron-builder still produces installers,
but they are unsigned. If notarization secrets are missing while notarize is
enabled, the macOS job fails.
You only need one complete notarization method: API Key
(APPLE_API_KEY + APPLE_API_KEY_ID + APPLE_API_ISSUER) or
Apple ID (APPLE_ID + APPLE_APP_SPECIFIC_PASSWORD +
APPLE_TEAM_ID). Preferred for CI: API Key. Do not rely on mixing both sets —
the Release workflow picks API Key when complete and ignores Apple ID credentials
in that case.
Windows signing (WIN_CSC_*)¶
You need a code-signing certificate as a .pfx / .p12 file (EV or OV from
a public CA such as DigiCert, Sectigo, SSL.com).
Export the certificate from your CA portal or Windows Certificate Manager as a Personal Information Exchange (``.pfx``), including the private key.
Note the export password — that becomes
WIN_CSC_KEY_PASSWORD.Encode the file as base64 for
WIN_CSC_LINK:
# macOS / Linux
base64 -i Consoleri-windows.pfx | tr -d '\n' > win-csc-link.txt
# Windows (PowerShell)
[Convert]::ToBase64String([IO.File]::ReadAllBytes("Consoleri-windows.pfx")) | Set-Content -NoNewline win-csc-link.txt
In GitHub: Settings → Secrets and variables → Actions → New repository secret.
Name:
WIN_CSC_LINK— paste the contents ofwin-csc-link.txt(the base64 string itself, not a file path).Name:
WIN_CSC_KEY_PASSWORD— paste the.pfxpassword.
If GitHub rejects a very long secret (Windows env vars can truncate above ~8192
characters), re-export the .pfx without the full certificate chain and
encode again.
macOS signing (MAC_CSC_*)¶
Prerequisite: an active Apple Developer Program membership.
You need a Developer ID Application certificate (distribution outside the Mac App Store — GitHub Releases DMG/ZIP).
On Apple Developer¶
Click + to create a certificate.
Under Software, select Developer ID Application (not Apple Development, Apple Distribution, or Mac App Distribution).
Choose G2 Sub-CA when asked for the intermediary.
Create a Certificate Signing Request on a Mac: Keychain Access → Certificate Assistant → Request a Certificate From a Certificate Authority.
Choose Saved to disk (do not use “Emailed to the CA”).
Leave CA Email empty.
Upload the
.certSigningRequeston the Apple site, continue, then download the.cercertificate.Double-click the
.certo install it into your login keychain.In Keychain Access → My Certificates, find Developer ID Application: … (it must show a disclosure triangle and a private key underneath).
Export that certificate as a
.p12file and set an export password.Note your Team ID: developer.apple.com/account → Membership details (10 characters, e.g.
ABCDE12345). Needed only if you use Apple ID notarization (APPLE_TEAM_ID).
On GitHub — signing secrets¶
base64 -i Consoleri-macos.p12 | tr -d '\n' > mac-csc-link.txt
Open the GitHub repository → Settings → Secrets and variables → Actions.
Click New repository secret (not Variables).
Name:
MAC_CSC_LINK— paste the contents ofmac-csc-link.txt(the base64 string itself, not a file path).Name:
MAC_CSC_KEY_PASSWORD— paste the.p12export password.
The Release workflow maps these to CSC_LINK / CSC_KEY_PASSWORD for
electron-builder on the macOS runner.
In a successful Release log, signing must show:
identityName=Developer ID Application: …
If you see Apple Development: … instead, Gatekeeper will keep blocking
downloads even if notarization is configured: MAC_CSC_* is missing, empty, or
the .p12 is an Apple Development cert rather than Developer ID
Application. Fix the certificate export and re-run Release.
macOS notarization¶
Notarization is required so Gatekeeper stops showing “Apple could not verify Consoleri.app…” after a clean download of the DMG.
On Apple — preferred: App Store Connect API Key¶
Open App Store Connect.
Go to Users and Access → Integrations → Team Keys (App Store Connect API).
Copy the Issuer ID (UUID) at the top of the page — this becomes
APPLE_API_ISSUER.Click Generate API Key (or +).
Name it something like
Consoleri CI, access Developer, then generate.Copy the Key ID — this becomes
APPLE_API_KEY_ID.Download the
.p8private key file. Apple shows this download once; store it securely.
Encode the .p8 for GitHub (recommended):
# AuthKey_XXXXXXXXXX.p8 from the App Store Connect download
base64 -i AuthKey_XXXXXXXXXX.p8 | tr -d '\n' > apple-api-key.txt
notarytool needs a file path to the .p8, not the base64 string. The
Release workflow decodes APPLE_API_KEY into
${RUNNER_TEMP}/AuthKey_<KEY_ID>.p8 and sets APPLE_API_KEY to that path
before electron-builder runs. You can also store the raw PEM (including
-----BEGIN PRIVATE KEY-----) in the secret; the workflow detects that and
writes the file without base64 decoding.
On Apple — alternative: Apple ID + app-specific password¶
Open appleid.apple.com and sign in with the Apple ID that belongs to the Developer team.
Go to Sign-In and Security → App-Specific Passwords.
Generate a password (label e.g.
Consoleri CI). Copy it once — this becomesAPPLE_APP_SPECIFIC_PASSWORD.APPLE_IDis that Apple ID email address.APPLE_TEAM_IDis the 10-character Team ID from developer.apple.com/account → Membership details.
On GitHub — notarization secrets¶
Open the repository → Settings → Secrets and variables → Actions.
Click New repository secret (do not use Variables).
Add secrets for the method you chose.
Preferred for CI — API Key
Secret name |
Value |
|---|---|
|
Contents of |
|
Key ID from App Store Connect (e.g. |
|
Issuer ID UUID from the Integrations / Team Keys page |
Do not set APPLE_TEAM_ID for this method in the workflow path — team is
inferred from the API key. If API Key secrets are complete, the workflow ignores
Apple ID secrets for that run.
Alternative — Apple ID
Secret name |
Value |
|---|---|
|
Apple ID email used for the Developer team |
|
App-specific password from appleid.apple.com |
|
10-character Team ID from Membership details |
Use this set only when API Key secrets are not configured.
Verifying¶
Confirm signing secrets and at least one complete notarization set exist in the repository.
Cut a release:
npm run release -- patch(pushes commit and tag when push is enabled).Open the Release workflow → macOS job. Expect:
Prepare step:
Notarization strategy: App Store Connect API key(or Apple ID)identityName=Developer ID Application: …— if you still seeApple Development: …, fixMAC_CSC_*before chasing Gatekeepernotarization succeeding (no
file couldn't be opened/ invalid--keyerrors)
On a clean Mac: download the DMG from the GitHub Release, open the app. Gatekeeper should not show “Apple could not verify Consoleri.app…”.
Confirm Release assets include
.exe,.dmg,.AppImage, and.debinstallers only (not helper tools from unpacked builds).