From 3dfd97b8f2f8e57ef669f686d7825ea405dc1547 Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 8 Apr 2026 20:05:01 +0000 Subject: [PATCH 1/3] fix(build): skip framework main binaries in codesign Step 1 to avoid ambiguity error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The inside-out signing loop from #1246 signs ALL Mach-O files in Step 1, then .framework bundles in Step 2. But Python.framework/Python is both a Mach-O binary AND the main binary of a .framework bundle — codesign errors with "bundle format is ambiguous (could be app or framework)" when it's signed as a standalone file. Fix: Skip files whose parent directory is a .framework, .bundle, or .plugin in Step 1. These are correctly signed as part of their bundle in Step 2. Also extends Step 2 to cover .bundle and .plugin directories (not just .framework) for completeness. Fixes the Build Tauri master CI failure after #1246 merge. --- scripts/package/build_app_tauri.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/package/build_app_tauri.sh b/scripts/package/build_app_tauri.sh index f2ebb448a..5fee51199 100755 --- a/scripts/package/build_app_tauri.sh +++ b/scripts/package/build_app_tauri.sh @@ -116,8 +116,20 @@ if [ -n "$APPLE_PERSONALID" ]; then # Use `xargs file` to batch all type queries in O(1) subprocess calls instead of # one `file` invocation per binary (PyInstaller bundles can contain hundreds of files). # Sort by path length descending so deeper binaries are signed before shallower containers. + # IMPORTANT: Skip the main binary of .framework bundles (e.g. Python.framework/Python). + # codesign treats those as ambiguous ("could be app or framework") when signed as + # standalone files. They are correctly signed in Step 2 as part of the framework bundle. echo " Signing Mach-O binary files..." while IFS= read -r f; do + # Skip main binaries of bundle directories (.framework, .bundle, .plugin) — + # they'll be signed as part of the bundle in Step 2. Signing them standalone + # causes "bundle format is ambiguous" errors from codesign. + parent_dir="$(dirname "$f")" + if [[ "$parent_dir" == *.framework ]] || [[ "$parent_dir" == *.framework/Versions/* ]] \ + || [[ "$parent_dir" == *.bundle ]] || [[ "$parent_dir" == *.plugin ]]; then + echo " Skipping bundle binary (signed in Step 2): $f" + continue + fi sign_binary "$f" done < <(find "dist/${APP_NAME}.app" -type f \ | xargs file \ From 7767d80930d7fa0f89c0782be5b9efd00f35a3b5 Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 8 Apr 2026 20:53:49 +0000 Subject: [PATCH 2/3] fix(build): handle non-standard Python.framework signing in Tauri build PyInstaller-embedded Python.framework bundles (inside aw-watcher-window, aw-watcher-input) lack the standard Versions/ directory structure and Info.plist, so codesign rejects them in Step 2 with: bundle format is ambiguous (could be app or framework) Previously #1247 correctly skipped the Python.framework/Python binary in Step 1 (standalone signing of the main framework binary causes ambiguous errors), but Step 2 still unconditionally attempted bundle-signing the .framework directory itself, hitting the same error. Fix: in Step 2, catch "bundle format is ambiguous" errors and fall back to signing the main binary inside the framework directly (e.g. Python.framework/Python). All other codesign errors remain fatal. This completes the signing chain: the .so files inside Python.framework are signed in Step 1, the Python binary itself is signed in this Step 2 fallback, and standard frameworks/bundles are signed normally. --- scripts/package/build_app_tauri.sh | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/scripts/package/build_app_tauri.sh b/scripts/package/build_app_tauri.sh index 5fee51199..63e0f0bd8 100755 --- a/scripts/package/build_app_tauri.sh +++ b/scripts/package/build_app_tauri.sh @@ -143,7 +143,29 @@ if [ -n "$APPLE_PERSONALID" ]; then # trigger notarytool bundle-integrity warnings. echo " Signing bundle directories (.framework, .bundle, .plugin)..." while IFS= read -r fw; do - sign_binary "$fw" + # PyInstaller-embedded frameworks (e.g. Python.framework inside aw-watcher-window) + # lack the standard Versions/ structure and Info.plist, so codesign rejects them + # with "bundle format is ambiguous (could be app or framework)". Fall back to + # signing the main binary inside the framework directly. All other signing errors + # are still fatal. + sign_output=$(codesign --force --options runtime --timestamp \ + --entitlements "$ENTITLEMENTS" \ + --sign "$APPLE_PERSONALID" \ + "$fw" 2>&1) && echo " Signed bundle: $fw" || { + if echo "$sign_output" | grep -q "bundle format is ambiguous"; then + echo " Note: $fw lacks standard bundle structure; signing main binary inside directly" + fw_name="$(basename "${fw%.*}")" + fw_binary="$fw/$fw_name" + if [ -f "$fw_binary" ]; then + sign_binary "$fw_binary" + else + echo " Warning: No main binary found at $fw_binary, skipping" + fi + else + echo "ERROR: Failed to sign $fw: $sign_output" >&2 + exit 1 + fi + } done < <(find "dist/${APP_NAME}.app" -type d \ \( -name "*.framework" -o -name "*.bundle" -o -name "*.plugin" \) \ | awk '{ print length, $0 }' | sort -rn | cut -d' ' -f2-) From c2c0af41889c1bc3856a369ae2e428426f5da3d0 Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 8 Apr 2026 21:03:44 +0000 Subject: [PATCH 3/3] fix(build): make missing fw_binary fatal instead of silent skip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the main binary is not found at the expected path after an ambiguous-bundle error, emit a clear error and exit 1 rather than silently skipping. A missing binary here means PyInstaller changed its output structure — a silent skip would produce a confusing downstream notarization failure instead of a clear build error. Addresses Greptile review comment (P2) on #1249. --- scripts/package/build_app_tauri.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/package/build_app_tauri.sh b/scripts/package/build_app_tauri.sh index 63e0f0bd8..5fd3bd14f 100755 --- a/scripts/package/build_app_tauri.sh +++ b/scripts/package/build_app_tauri.sh @@ -159,7 +159,9 @@ if [ -n "$APPLE_PERSONALID" ]; then if [ -f "$fw_binary" ]; then sign_binary "$fw_binary" else - echo " Warning: No main binary found at $fw_binary, skipping" + echo "ERROR: Expected main binary not found at $fw_binary" >&2 + echo " PyInstaller may have changed its output structure. Inspect $fw" >&2 + exit 1 fi else echo "ERROR: Failed to sign $fw: $sign_output" >&2