mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-28 22:35:42 +00:00
Add --keychain flag to all codesign commands to explicitly specify which keychain to use. This fixes the "ambiguous" error when the same signing identity exists in multiple keychains (build keychain and login keychain). Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
120 lines
4.4 KiB
Bash
Executable File
120 lines
4.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Code sign a macOS .app bundle for distribution
|
|
# Usage: codesign_mac_app.sh <app_path> [entitlements_path]
|
|
#
|
|
# Environment variables:
|
|
# SIGNING_IDENTITY - The signing identity (default: "Developer ID Application")
|
|
# KEYCHAIN_PASSWORD - Password to unlock the build keychain (optional)
|
|
# KEYCHAIN_NAME - Name of the keychain to unlock and use for signing (default: "build.keychain")
|
|
|
|
set -euxo pipefail
|
|
|
|
APP_PATH="$1"
|
|
ENTITLEMENTS_PATH="${2:-}"
|
|
SIGNING_IDENTITY="${SIGNING_IDENTITY:-Developer ID Application}"
|
|
KEYCHAIN_NAME="${KEYCHAIN_NAME:-build.keychain}"
|
|
|
|
if [ ! -d "$APP_PATH" ]; then
|
|
echo "ERROR: App not found at $APP_PATH"
|
|
exit 1
|
|
fi
|
|
|
|
# Unlock keychain if password provided
|
|
if [ -n "${KEYCHAIN_PASSWORD:-}" ]; then
|
|
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_NAME" || true
|
|
fi
|
|
|
|
echo "=== Signing nested components first ==="
|
|
echo "Using keychain: $KEYCHAIN_NAME"
|
|
|
|
# Sign all dylibs
|
|
find "$APP_PATH" -name "*.dylib" -print0 | while IFS= read -r -d '' item; do
|
|
echo "Signing dylib: $item"
|
|
codesign --force --verify --verbose --timestamp --options runtime \
|
|
--keychain "$KEYCHAIN_NAME" \
|
|
--sign "$SIGNING_IDENTITY" "$item"
|
|
done
|
|
|
|
# Sign all bundles (plugins)
|
|
find "$APP_PATH" -name "*.bundle" -print0 | while IFS= read -r -d '' item; do
|
|
echo "Signing bundle: $item"
|
|
codesign --force --verify --verbose --timestamp --options runtime \
|
|
--keychain "$KEYCHAIN_NAME" \
|
|
--sign "$SIGNING_IDENTITY" "$item"
|
|
done
|
|
|
|
# Sign XPC services (but skip ones inside Sparkle.framework - they're already signed)
|
|
find "$APP_PATH" -name "*.xpc" -print0 | while IFS= read -r -d '' item; do
|
|
if [[ "$item" == *"Sparkle.framework"* ]]; then
|
|
echo "Skipping Sparkle XPC service (pre-signed): $item"
|
|
continue
|
|
fi
|
|
echo "Signing XPC service: $item"
|
|
codesign --force --verify --verbose --timestamp --options runtime \
|
|
--keychain "$KEYCHAIN_NAME" \
|
|
--sign "$SIGNING_IDENTITY" "$item"
|
|
done
|
|
|
|
# Sign nested apps (but skip ones inside Sparkle.framework - they're already signed)
|
|
find "$APP_PATH" -path "*/Frameworks/*.app" -print0 | while IFS= read -r -d '' item; do
|
|
if [[ "$item" == *"Sparkle.framework"* ]]; then
|
|
echo "Skipping Sparkle nested app (pre-signed): $item"
|
|
continue
|
|
fi
|
|
echo "Signing nested app: $item"
|
|
codesign --force --verify --verbose --timestamp --options runtime \
|
|
--keychain "$KEYCHAIN_NAME" \
|
|
--sign "$SIGNING_IDENTITY" "$item"
|
|
done
|
|
|
|
# Sign standalone executables inside frameworks (but skip Sparkle.framework internals)
|
|
find "$APP_PATH" -path "*/Frameworks/*/Versions/*/Autoupdate" -type f -print0 | while IFS= read -r -d '' item; do
|
|
if [[ "$item" == *"Sparkle.framework"* ]]; then
|
|
echo "Skipping Sparkle executable (pre-signed): $item"
|
|
continue
|
|
fi
|
|
echo "Signing executable: $item"
|
|
codesign --force --verify --verbose --timestamp --options runtime \
|
|
--keychain "$KEYCHAIN_NAME" \
|
|
--sign "$SIGNING_IDENTITY" "$item"
|
|
done
|
|
|
|
# Sign all frameworks (after their contents are signed)
|
|
# Use --deep for Sparkle.framework to handle its XPC services
|
|
find "$APP_PATH" -name "*.framework" -print0 | while IFS= read -r -d '' item; do
|
|
if [[ "$item" == *"Sparkle.framework" ]]; then
|
|
echo "Signing Sparkle framework with --deep: $item"
|
|
codesign --deep --force --verify --verbose --timestamp --options runtime \
|
|
--keychain "$KEYCHAIN_NAME" \
|
|
--sign "$SIGNING_IDENTITY" "$item"
|
|
else
|
|
echo "Signing framework: $item"
|
|
codesign --force --verify --verbose --timestamp --options runtime \
|
|
--keychain "$KEYCHAIN_NAME" \
|
|
--sign "$SIGNING_IDENTITY" "$item"
|
|
fi
|
|
done
|
|
|
|
echo "=== Signing main app bundle ==="
|
|
|
|
if [ -n "$ENTITLEMENTS_PATH" ] && [ -f "$ENTITLEMENTS_PATH" ]; then
|
|
echo "Using entitlements: $ENTITLEMENTS_PATH"
|
|
codesign --force --verify --verbose --timestamp --options runtime \
|
|
--keychain "$KEYCHAIN_NAME" \
|
|
--entitlements "$ENTITLEMENTS_PATH" \
|
|
--sign "$SIGNING_IDENTITY" "$APP_PATH"
|
|
else
|
|
codesign --force --verify --verbose --timestamp --options runtime \
|
|
--keychain "$KEYCHAIN_NAME" \
|
|
--sign "$SIGNING_IDENTITY" "$APP_PATH"
|
|
fi
|
|
|
|
echo "=== Verifying signature ==="
|
|
codesign --verify --verbose=4 "$APP_PATH"
|
|
|
|
echo "=== Checking Gatekeeper assessment ==="
|
|
spctl --assess --type exec -v "$APP_PATH" || echo "Note: Gatekeeper may reject until notarized"
|
|
|
|
echo "Code signing complete: $APP_PATH"
|