From 4dfe2dfce8010aae8d8ff1f99df883b60c8653fd Mon Sep 17 00:00:00 2001 From: Ali Turki Date: Fri, 3 Jul 2026 13:28:49 +0800 Subject: [PATCH] fix(release): stage per-arch sidecar slices and deflake sidecar verify Universal macOS builds compile each arch separately and tauri-build validates externalBin against the current cargo triple, so the per-arch slices must be staged alongside the lipo output the bundler embeds. Verified locally: universal .app carries both binaries with x86_64+arm64. The deb verify piped dpkg-deb into grep -q under pipefail; grep exiting on first match killed the tar child with EPIPE and failed the step even though the sidecar was present. Both verify steps now capture output before matching. --- .github/workflows/release.yml | 11 +++++++++-- scripts/build-sidecar.ts | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0a56041..7477f59 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -150,7 +150,11 @@ jobs: APP=$(find src-tauri/target/universal-apple-darwin/release/bundle/macos -name '*.app' -maxdepth 1 | head -1) SIDECAR="$APP/Contents/MacOS/docsreader-mcp" test -f "$SIDECAR" || { echo "::error::sidecar missing from $APP"; exit 1; } - lipo -archs "$SIDECAR" | grep -q "x86_64 arm64" || { echo "::error::sidecar is not universal"; exit 1; } + ARCHS=$(lipo -archs "$SIDECAR") + case "$ARCHS" in + *x86_64*arm64*|*arm64*x86_64*) ;; + *) echo "::error::sidecar is not universal (archs: $ARCHS)"; exit 1 ;; + esac codesign --verify --strict "$SIDECAR" echo "sidecar present, universal, and signed" @@ -159,7 +163,10 @@ jobs: run: | set -euo pipefail DEB=$(find src-tauri/target/release/bundle/deb -name '*.deb' | head -1) - dpkg-deb -c "$DEB" | grep -q 'usr/bin/docsreader-mcp' || { echo "::error::sidecar missing from $DEB"; exit 1; } + # Capture the listing first: grep -q closing the pipe early makes + # dpkg-deb's tar child fail with EPIPE under pipefail. + CONTENTS=$(dpkg-deb -c "$DEB") + grep -q 'usr/bin/docsreader-mcp' <<<"$CONTENTS" || { echo "::error::sidecar missing from $DEB"; exit 1; } echo "sidecar present in deb" # macOS-only: submit the DMG to Apple async (no --wait), then stash diff --git a/scripts/build-sidecar.ts b/scripts/build-sidecar.ts index 18a661e..5773e09 100644 --- a/scripts/build-sidecar.ts +++ b/scripts/build-sidecar.ts @@ -45,10 +45,17 @@ const triple = process.env.TAURI_ENV_TARGET_TRIPLE ?? hostTriple(); mkdirSync(outDir, { recursive: true }); if (triple === "universal-apple-darwin") { - const slices = ["aarch64-apple-darwin", "x86_64-apple-darwin"].map(buildFor); + // tauri-build validates externalBin per compiled arch (appending the + // current cargo triple), so the per-arch slices must be staged alongside + // the lipo output the bundler embeds. + const slices = ["aarch64-apple-darwin", "x86_64-apple-darwin"].map((arch) => { + const staged = path.join(outDir, `docsreader-mcp-${arch}`); + copyFileSync(buildFor(arch), staged); + return staged; + }); const dest = path.join(outDir, `docsreader-mcp-${triple}`); run("lipo", ["-create", ...slices, "-output", dest]); - console.log(`sidecar: ${dest} (universal)`); + console.log(`sidecar: ${dest} (universal + per-arch slices)`); } else { const ext = triple.includes("windows") ? ".exe" : ""; const dest = path.join(outDir, `docsreader-mcp-${triple}${ext}`);