From 132cc5fc74307c805d55cf7c83ef61b32856c8a8 Mon Sep 17 00:00:00 2001 From: hrhrng Date: Sun, 16 Aug 2026 19:04:38 +0800 Subject: [PATCH] Fix macOS DMG bundle signing --- .github/workflows/build-dmg.yml | 19 ++++++++------ package.json | 2 ++ scripts/verify-packaged-first-prompt.mjs | 4 ++- scripts/verify-packaged-macos-signature.mjs | 28 +++++++++++++++++++++ src/main/github-ci-contract.test.ts | 4 ++- 5 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 scripts/verify-packaged-macos-signature.mjs diff --git a/.github/workflows/build-dmg.yml b/.github/workflows/build-dmg.yml index b7b1616..9f48a70 100644 --- a/.github/workflows/build-dmg.yml +++ b/.github/workflows/build-dmg.yml @@ -49,6 +49,18 @@ jobs: test -n "$app" node scripts/verify-packaged-runtime.mjs "$app" + - name: Verify packaged macOS signature + run: | + app=$(find release -type d -name "Backchat.app" -print -quit) + test -n "$app" + node scripts/verify-packaged-macos-signature.mjs "$app" + + - name: Verify packaged first prompt + run: | + app=$(find release -type f -path "*/Backchat.app/Contents/MacOS/Backchat" -print -quit) + test -n "$app" + node scripts/verify-packaged-first-prompt.mjs "$app" + - name: Upload workflow artifact uses: actions/upload-artifact@v4 with: @@ -73,13 +85,6 @@ jobs: cp "$versioned" "$stable" gh release create "${GITHUB_REF_NAME}" "$versioned" "$stable" --generate-notes --verify-tag - - name: Verify packaged first prompt - continue-on-error: true - run: | - app=$(find release -type f -path "*/Backchat.app/Contents/MacOS/Backchat" -print -quit) - test -n "$app" - node scripts/verify-packaged-first-prompt.mjs "$app" - - name: Upload packaged first-prompt screenshot if: always() uses: actions/upload-artifact@v4 diff --git a/package.json b/package.json index 4bc1a9b..c3f2dad 100644 --- a/package.json +++ b/package.json @@ -124,6 +124,8 @@ "**/*.node" ], "mac": { + "identity": "-", + "hardenedRuntime": false, "target": [ "dmg" ], diff --git a/scripts/verify-packaged-first-prompt.mjs b/scripts/verify-packaged-first-prompt.mjs index c2800e0..b61bb36 100644 --- a/scripts/verify-packaged-first-prompt.mjs +++ b/scripts/verify-packaged-first-prompt.mjs @@ -99,7 +99,9 @@ try { await page.getByTestId("new-chat-button").waitFor({ timeout: 20_000 }); await page.getByTestId("new-chat-button").click(); - const composer = page.locator('[data-chat-surface="main"] textarea').last(); + // The first prompt is submitted from NewChatPage before a persisted chat + // surface exists. Session pages gain data-chat-surface only after submit. + const composer = page.locator('[data-page="new-chat"] textarea').last(); await composer.fill("packaged-first-prompt-e2e"); await composer.press("Enter"); await page diff --git a/scripts/verify-packaged-macos-signature.mjs b/scripts/verify-packaged-macos-signature.mjs new file mode 100644 index 0000000..3c78ac7 --- /dev/null +++ b/scripts/verify-packaged-macos-signature.mjs @@ -0,0 +1,28 @@ +#!/usr/bin/env node + +import { spawnSync } from "node:child_process"; +import { resolve } from "node:path"; + +const appBundle = process.argv[2]; + +if (!appBundle) { + console.error("Usage: node scripts/verify-packaged-macos-signature.mjs "); + process.exit(2); +} + +if (process.platform !== "darwin") { + console.error("Packaged macOS signature verification requires macOS"); + process.exit(2); +} + +const result = spawnSync( + "/usr/bin/codesign", + ["--verify", "--deep", "--strict", "--verbose=4", resolve(appBundle)], + { encoding: "utf8" }, +); + +if (result.stdout) process.stdout.write(result.stdout); +if (result.stderr) process.stderr.write(result.stderr); +if (result.error) throw result.error; + +process.exit(result.status ?? 1); diff --git a/src/main/github-ci-contract.test.ts b/src/main/github-ci-contract.test.ts index e2e3ef5..6c12c75 100644 --- a/src/main/github-ci-contract.test.ts +++ b/src/main/github-ci-contract.test.ts @@ -56,12 +56,14 @@ describe("github ci", () => { expect(website).toContain("secrets.CLOUDFLARE_API_TOKEN"); }); - it("keeps packaged-runtime and first-prompt verification on the DMG job", () => { + it("verifies packaged runtime, signature, and first prompt before publishing DMGs", () => { expect(dmg).toContain("./.github/actions/setup-node-pnpm"); expect(dmg).toContain("pnpm run test:ci"); expect(dmg).toContain("verify-packaged-runtime.mjs"); + expect(dmg).toContain("verify-packaged-macos-signature.mjs"); expect(dmg).toContain("verify-packaged-first-prompt.mjs"); expect(dmg).toContain("Backchat-arm64.dmg"); expect(dmg).toContain("gh release create"); + expect(dmg).not.toContain("continue-on-error"); }); });