From ffbebd437cffebbafa07ae5d1f252b64a2209d06 Mon Sep 17 00:00:00 2001 From: Exidex <16986685+Exidex@users.noreply.github.com> Date: Sun, 25 Aug 2024 11:17:38 +0200 Subject: [PATCH] Sign, notarize and staple macos dmg --- .github/workflows/release.yaml | 1 + .github/workflows/setup-macos.yaml | 4 ++ assets/macos/entitlements.plist | 6 +++ js/build/src/main.ts | 62 ++++++++++++++++++++++++++++-- 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 assets/macos/entitlements.plist diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d5f0119..20de2e8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -73,6 +73,7 @@ jobs: with: command: npm run publish-macos-project --workspace @project-gauntlet/build github-release-id: ${{ needs.publish-init.outputs.github-release-id }} + secrets: inherit publish-final: needs: diff --git a/.github/workflows/setup-macos.yaml b/.github/workflows/setup-macos.yaml index cb8f299..86896af 100644 --- a/.github/workflows/setup-macos.yaml +++ b/.github/workflows/setup-macos.yaml @@ -36,6 +36,7 @@ jobs: - run: brew install protobuf - run: brew install create-dmg + - run: cargo install apple-codesign - uses: Swatinem/rust-cache@v2 with: @@ -48,3 +49,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }} GITHUB_RELEASE_ID: ${{ inputs.github-release-id }} + APPLE_SIGNING_KEY_PEM: ${{ secrets.APPLE_SIGNING_KEY_PEM && fromJson(secrets.APPLE_SIGNING_KEY_PEM).content }} + APPLE_SIGNING_CERT_PEM: ${{ secrets.APPLE_SIGNING_CERT_PEM && fromJson(secrets.APPLE_SIGNING_CERT_PEM).content }} + APP_STORE_CONNECT_KEY: ${{ secrets.APP_STORE_CONNECT_KEY }} diff --git a/assets/macos/entitlements.plist b/assets/macos/entitlements.plist new file mode 100644 index 0000000..8c00664 --- /dev/null +++ b/assets/macos/entitlements.plist @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/js/build/src/main.ts b/js/build/src/main.ts index 12beaae..3126603 100644 --- a/js/build/src/main.ts +++ b/js/build/src/main.ts @@ -113,7 +113,7 @@ async function doPublishMacOS() { build(projectRoot, arch) - const { fileName, filePath } = await packageForMacos(projectRoot, arch) + const { fileName, filePath } = await packageForMacos(projectRoot, arch, true, true) await addFileToRelease(filePath, fileName) } @@ -123,7 +123,7 @@ async function doBuildMacOS() { const arch = 'aarch64-apple-darwin'; await doBuild(projectRoot, arch) - await packageForMacos(projectRoot, arch) + await packageForMacos(projectRoot, arch, true, false) } async function doPublishWindows() { @@ -306,7 +306,7 @@ function packageForLinux(projectRoot: string, arch: string): { filePath: string; } } -async function packageForMacos(projectRoot: string, arch: string): Promise<{ filePath: string; fileName: string }> { +async function packageForMacos(projectRoot: string, arch: string, sign: boolean, notarize: boolean): Promise<{ filePath: string; fileName: string }> { const releaseDirPath = path.join(projectRoot, 'target', arch, 'release'); const sourceExecutableFilePath = path.join(releaseDirPath, 'gauntlet'); const outFileName = "gauntlet-aarch64-macos.dmg" @@ -316,6 +316,7 @@ async function packageForMacos(projectRoot: string, arch: string): Promise<{ fil const sourceInfoFilePath = path.join(assetsDirPath, 'Info.plist'); const sourceIconFilePath = path.join(assetsDirPath, 'AppIcon.icns'); const dmgBackground = path.join(assetsDirPath, 'dmg-background.png'); + const entitlementsPath = path.join(assetsDirPath, 'entitlements.plist'); const bundleDir = path.join(releaseDirPath, 'Gauntlet.app'); const contentsDir = path.join(bundleDir, 'Contents'); @@ -340,6 +341,33 @@ async function packageForMacos(projectRoot: string, arch: string): Promise<{ fil const infoResult = infoSource.replace('__VERSION__', `${version}.0.0`); writeFileSync(targetInfoFilePath, infoResult,'utf8'); + const signKeyPath = path.join(releaseDirPath, 'signKey.pem'); + const signCertPath = path.join(releaseDirPath, 'signCert.pem'); + const connectApiKeyPath = path.join(releaseDirPath, 'connectApiKey.json'); + + const signKeyContent = process.env.APPLE_SIGNING_KEY_PEM; + const signCertContent = process.env.APPLE_SIGNING_CERT_PEM; + const connectApiKeyContent = process.env.APP_STORE_CONNECT_KEY; + + if (sign) { + writeFileSync(signKeyPath, signKeyContent!!); + writeFileSync(signCertPath, signCertContent!!); + + spawnWithErrors(`rcodesign`, [ + 'sign', + '--pem-file', + signKeyPath, + '--pem-file', + signCertPath, + '--for-notarization', + '--entitlements-xml-file', + entitlementsPath, + bundleDir + ], { + cwd: releaseDirPath + }) + } + spawnWithErrors(`create-dmg`, [ '--volname', 'Gauntlet Installer', '--window-size', '660', '400', @@ -354,6 +382,34 @@ async function packageForMacos(projectRoot: string, arch: string): Promise<{ fil cwd: releaseDirPath }) + if (sign) { + spawnWithErrors(`rcodesign`, [ + 'sign', + '--pem-file', + signKeyPath, + '--pem-file', + signCertPath, + '--for-notarization', + outFilePath + ], { + cwd: releaseDirPath + }) + } + + if (notarize) { + writeFileSync(connectApiKeyPath, connectApiKeyContent!!); + + spawnWithErrors(`rcodesign`, [ + 'notary-submit', + '--api-key-file', + connectApiKeyPath, + '--staple', + outFilePath + ], { + cwd: releaseDirPath + }) + } + return { filePath: outFilePath, fileName: outFileName