diff --git a/.github/workflows/ci-desktop.yml b/.github/workflows/ci-desktop.yml index bf185bb3..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 @@ -138,6 +139,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 }); }; /**