From ad0aa94ba7483da58cbc059cb5d7cecfe2673571 Mon Sep 17 00:00:00 2001 From: Valerii Kovalskii Date: Mon, 20 Jul 2026 19:10:31 +0300 Subject: [PATCH] chore(desktop): enable Developer ID signing + notarization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Pin mac signing identity to the Developer ID Application cert (team A933C2TJXU). Name is given WITHOUT the "Developer ID Application:" prefix — electron-builder rejects the prefix and picks the cert type automatically. - notarize.js now prefers a keychain profile (APPLE_KEYCHAIN_PROFILE → notarytool keychainProfile) so no app-specific password lands in env/CI logs; falls back to APPLE_ID/APPLE_APP_SPECIFIC_PASSWORD/ APPLE_TEAM_ID for CI. Build (both arches, signed + notarized + stapled), with the corporate proxy unset so codesign's timestamp requests reach Apple's TSA: cd desktop && env -u HTTPS_PROXY -u HTTP_PROXY -u ALL_PROXY \ APPLE_KEYCHAIN_PROFILE=codbash-notary CSC_IDENTITY_AUTO_DISCOVERY=true \ ./node_modules/.bin/electron-builder --mac --arm64 --x64 Co-Authored-By: Claude Opus 4.8 (1M context) --- desktop/package.json | 1 + desktop/scripts/notarize.js | 41 +++++++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/desktop/package.json b/desktop/package.json index 4096fb8..90178d1 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -65,6 +65,7 @@ } ], "icon": "build/icon.png", + "identity": "Valeriy Kovalsky (A933C2TJXU)", "hardenedRuntime": true, "gatekeeperAssess": false, "entitlements": "build/entitlements.mac.plist", diff --git a/desktop/scripts/notarize.js b/desktop/scripts/notarize.js index 4421429..2832077 100644 --- a/desktop/scripts/notarize.js +++ b/desktop/scripts/notarize.js @@ -1,12 +1,17 @@ // electron-builder afterSign hook — notarizes the signed .app with Apple. // // It runs automatically after signing during `electron-builder --mac`. It is a -// no-op unless the three Apple env vars are set, so an unsigned/local build -// still succeeds: +// no-op unless notarization credentials are provided, so an unsigned/local +// build still succeeds. Two credential modes are supported: // -// APPLE_ID your Apple ID email -// APPLE_APP_SPECIFIC_PASSWORD app-specific password (appleid.apple.com → Sign-In & Security) -// APPLE_TEAM_ID your 10-char Developer Team ID +// 1. Keychain profile (preferred — no secret in env/transcript): +// APPLE_KEYCHAIN_PROFILE name of a profile stored via +// `xcrun notarytool store-credentials ` +// +// 2. Explicit env vars (e.g. for CI): +// APPLE_ID your Apple ID email +// APPLE_APP_SPECIFIC_PASSWORD app-specific password (appleid.apple.com) +// APPLE_TEAM_ID your 10-char Developer Team ID // // Signing itself is handled by electron-builder when a "Developer ID Application" // cert is available (in the login keychain, or via CSC_LINK + CSC_KEY_PASSWORD). @@ -18,9 +23,21 @@ exports.default = async function notarizing(context) { const { electronPlatformName, appOutDir } = context; if (electronPlatformName !== 'darwin') return; - const { APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID } = process.env; - if (!APPLE_ID || !APPLE_APP_SPECIFIC_PASSWORD || !APPLE_TEAM_ID) { - console.log('[notarize] skipped — set APPLE_ID / APPLE_APP_SPECIFIC_PASSWORD / APPLE_TEAM_ID to enable.'); + const { APPLE_KEYCHAIN_PROFILE, APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID } = process.env; + + let creds; + if (APPLE_KEYCHAIN_PROFILE) { + creds = { tool: 'notarytool', keychainProfile: APPLE_KEYCHAIN_PROFILE }; + } else if (APPLE_ID && APPLE_APP_SPECIFIC_PASSWORD && APPLE_TEAM_ID) { + creds = { + tool: 'notarytool', + appleId: APPLE_ID, + appleIdPassword: APPLE_APP_SPECIFIC_PASSWORD, + teamId: APPLE_TEAM_ID, + }; + } else { + console.log('[notarize] skipped — set APPLE_KEYCHAIN_PROFILE (preferred) or ' + + 'APPLE_ID / APPLE_APP_SPECIFIC_PASSWORD / APPLE_TEAM_ID to enable.'); return; } @@ -36,13 +53,7 @@ exports.default = async function notarizing(context) { const appPath = path.join(appOutDir, appName + '.app'); console.log('[notarize] submitting ' + appName + '.app to Apple (this can take a few minutes)…'); - await notarize({ - tool: 'notarytool', - appPath: appPath, - appleId: APPLE_ID, - appleIdPassword: APPLE_APP_SPECIFIC_PASSWORD, - teamId: APPLE_TEAM_ID, - }); + await notarize(Object.assign({ appPath: appPath }, creds)); console.log('[notarize] done — ' + appName + '.app is notarized.'); };