From e6b27fb9dcbd7f47c42f799b38478c10a8afbceb Mon Sep 17 00:00:00 2001 From: orangeboyChen Date: Fri, 30 Oct 2026 01:18:25 +0800 Subject: [PATCH 1/2] fix(desktop): materialize gateway resources before signing --- .github/workflows/ci-desktop.yml | 14 ++++++++++++++ .github/workflows/release.yml | 15 +++++++++++++++ scripts/build-desktop.ts | 6 +++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-desktop.yml b/.github/workflows/ci-desktop.yml index bf185bb3..74516608 100644 --- a/.github/workflows/ci-desktop.yml +++ b/.github/workflows/ci-desktop.yml @@ -138,6 +138,20 @@ jobs: - name: Build the macOS app run: bun scripts/build-desktop.ts --dev-icon --mac --arm64 --dir + - name: Check gateway bundle resources + run: | + set -euo pipefail + app="$(find build/desktop -name '*.app' -maxdepth 2 -print -quit)" + if [[ -z "$app" ]]; then + echo '::error::electron-builder left no .app behind' + exit 1 + fi + link="$(find "$app/Contents/Resources/gateway" -type l -print -quit)" + if [[ -n "$link" ]]; then + echo "::error::gateway contains a symlink that can invalidate macOS signing: $link" + exit 1 + fi + # Zipped with ditto rather than handed over as a directory: an app is a # bundle, and a bundle carries resource forks, symlinks and an executable # bit that an archive has to keep or the app will not open. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b20cfb19..f6b6e60a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -325,6 +325,21 @@ jobs: else bun scripts/build-desktop.ts ${{ matrix.targets }} fi + - name: Check gateway bundle resources + if: ${{ matrix.macos }} + shell: bash + run: | + set -euo pipefail + app="$(find build/desktop -name '*.app' -maxdepth 2 -print -quit)" + if [[ -z "$app" ]]; then + echo '::error::electron-builder left no .app behind' + exit 1 + fi + link="$(find "$app/Contents/Resources/gateway" -type l -print -quit)" + if [[ -n "$link" ]]; then + echo "::error::gateway contains a symlink that can invalidate macOS signing: $link" + exit 1 + fi - name: Check that the app is signed if: ${{ env.MATCH_GIT_URL != '' }} shell: bash diff --git a/scripts/build-desktop.ts b/scripts/build-desktop.ts index 4166c023..a7b2a22f 100644 --- a/scripts/build-desktop.ts +++ b/scripts/build-desktop.ts @@ -72,7 +72,11 @@ const requirePath = (target: string, hint: string) => { }; const copyInto = (source: string, destination: string) => { - fs.cpSync(source, destination, { recursive: true }); + // macOS code signing rejects resource symlinks whose destination is not + // represented as a bundle resource. The standalone Next.js output uses + // symlinks for a few traced packages, so materialize those packages while + // assembling the gateway instead of copying the links into the app bundle. + fs.cpSync(source, destination, { dereference: true, recursive: true }); }; /** From 7f1a0d589ffbde8bc1e50a722a286bfd1c852cd0 Mon Sep 17 00:00:00 2001 From: orangeboyChen Date: Fri, 30 Oct 2026 01:19:51 +0800 Subject: [PATCH 2/2] ci(desktop): verify macOS bundles on pull requests --- .github/workflows/ci-desktop.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-desktop.yml b/.github/workflows/ci-desktop.yml index 74516608..6fe50ebf 100644 --- a/.github/workflows/ci-desktop.yml +++ b/.github/workflows/ci-desktop.yml @@ -4,6 +4,7 @@ on: push: branches: - main + pull_request: # A push only ever builds Linux, so the macOS and Windows targets would # otherwise first run at release time. Dispatch this by hand to build another # one of them, from any branch: the installer comes back as an artifact of the