From 77467311f10e9d351c0368ee1a5748bb284ef42c Mon Sep 17 00:00:00 2001 From: kalac2232 <35256979+kalac2232@users.noreply.github.com> Date: Thu, 12 Mar 2026 23:56:45 +0800 Subject: [PATCH] fix(ci): ensure sidecar architecture matches target in macOS releases (#637) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(ci): pass target architecture to beforeBuildCommand Set TAURI_ENV_TARGET_TRIPLE environment variable before running build commands to ensure sidecar binary matches target architecture. Problem: - CI builds both arm64 and x86_64 targets in parallel on arm64 runner - beforeBuildCommand executes before Tauri sets TAURI_ENV_TARGET_TRIPLE - build-sidecar.mjs fallbacks to process.arch (arm64 on CI runner) - Both parallel tasks build arm64 sidecars, second task overwrites first - Result: x86_64 releases contain arm64 sidecar → startup failure on Intel Macs Solution: - Explicitly set TAURI_ENV_TARGET_TRIPLE in CI workflow - Add architecture verification step to detect mismatches early Evidence: - Official DMG OpenChamber_1.8.5_darwin-x86_64.dmg contains arm64 sidecar - Local build with explicit env var produces correct x86_64 sidecar - /Applications/OpenChamber.app/Contents/MacOS/openchamber-server: arm64 - packages/desktop/src-tauri/sidecars/...: x86_64 (with env var) Fixes startup failure on Intel Macs where official x86_64 DMG contains arm64 sidecar binary, causing indefinite loading screen. * fix(ci): normalize architecture names in verification step Fix architecture mismatch where macOS 'file' command reports ARM binaries as 'arm64' but verification expects 'aarch64', causing false negatives in ARM builds. Changes: - Update grep pattern to include 'arm64' in extraction - Add normalize_arch() function to map arm64 -> aarch64 - Improve debug output to show raw and normalized architectures - Update error messages to show both raw and normalized values This fixes the issue reported by @btriapitsyn where ARM builds would fail verification even with correct artifacts, because: - macOS file command reports: 'Mach-O 64-bit executable arm64' - Old grep pattern only matched: 'x86_64|aarch64' - Result: empty string != 'aarch64' → false failure The normalization ensures consistency between: - macOS file output (arm64/x86_64) - Rust/Cargo naming (aarch64/x86_64) - Tauri target triples (aarch64-apple-darwin/x86_64-apple-darwin) Fixes architecture verification for both ARM and Intel builds. --- .github/workflows/release.yml | 62 ++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b350bda9..2a643840 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -166,8 +166,12 @@ jobs: - name: Build Desktop app # Note: We use inline commands instead of desktop:build to pass architecture-specific --target flag # This enables cross-compilation for both arm64 and x86_64 from the same runner - run: bun run --cwd packages/desktop build && bun run --cwd packages/desktop tauri build --target ${{ matrix.target }} + run: | + export TAURI_ENV_TARGET_TRIPLE=${{ matrix.target }} + bun run --cwd packages/desktop build + bun run --cwd packages/desktop tauri build --target ${{ matrix.target }} env: + TAURI_ENV_TARGET_TRIPLE: ${{ matrix.target }} TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} @@ -175,6 +179,62 @@ jobs: APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + - name: Verify binary architectures + run: | + set -euo pipefail + + BUNDLE_DIR="packages/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/macos" + + if [ ! -d "$BUNDLE_DIR" ]; then + echo "❌ Error: bundle directory not found: $BUNDLE_DIR" + exit 1 + fi + + APP_PATH=$(find "$BUNDLE_DIR" -maxdepth 2 -name "*.app" -print -quit) + if [ -z "$APP_PATH" ]; then + echo "❌ Error: .app bundle not found under $BUNDLE_DIR" + exit 1 + fi + + echo "🔍 Verifying binary architectures in $APP_PATH" + + # Extract raw architecture names (macOS file command reports ARM as "arm64") + MAIN_ARCH_RAW=$(file "$APP_PATH/Contents/MacOS/openchamber-desktop" | grep -oE 'arm64|x86_64|aarch64' | head -1) + SIDEARCH_ARCH_RAW=$(file "$APP_PATH/Contents/MacOS/openchamber-server" | grep -oE 'arm64|x86_64|aarch64' | head -1) + + # Normalize architecture names (arm64 -> aarch64 for consistency with Rust/Tauri) + normalize_arch() { + case "$1" in + arm64) echo "aarch64" ;; + aarch64|x86_64) echo "$1" ;; + *) echo "unknown" ;; + esac + } + + MAIN_ARCH=$(normalize_arch "$MAIN_ARCH_RAW") + SIDEARCH_ARCH=$(normalize_arch "$SIDEARCH_ARCH_RAW") + EXPECTED_ARCH=$(echo "${{ matrix.target }}" | grep -oE 'aarch64|x86_64' | head -1) + + echo " Main: $MAIN_ARCH_RAW → $MAIN_ARCH" + echo " Sidecar: $SIDEARCH_ARCH_RAW → $SIDEARCH_ARCH" + echo " Expected: $EXPECTED_ARCH" + + if [ "$MAIN_ARCH" != "$EXPECTED_ARCH" ]; then + echo "❌ ERROR: Main binary architecture mismatch!" + echo " Expected: $EXPECTED_ARCH" + echo " Got: $MAIN_ARCH (raw: $MAIN_ARCH_RAW)" + exit 1 + fi + + if [ "$SIDEARCH_ARCH" != "$EXPECTED_ARCH" ]; then + echo "❌ ERROR: Sidecar binary architecture mismatch!" + echo " Expected: $EXPECTED_ARCH" + echo " Got: $SIDEARCH_ARCH (raw: $SIDEARCH_ARCH_RAW)" + exit 1 + fi + + echo "✅ Architecture verification passed: both binaries match $EXPECTED_ARCH" + - name: Verify macOS entitlements run: | set -euo pipefail