diff --git a/scripts/codesign_mac_app.sh b/scripts/codesign_mac_app.sh index 85387890d8..bc8edef063 100755 --- a/scripts/codesign_mac_app.sh +++ b/scripts/codesign_mac_app.sh @@ -5,33 +5,49 @@ # # 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") +# KEYCHAIN_PASSWORD - Password to unlock the keychain (optional, CI only) +# KEYCHAIN_NAME - Name of the keychain containing the signing certificate (optional, CI only) +# When set, looks for certificate in this specific keychain. +# When not set, searches all keychains (local dev mode). set -euxo pipefail APP_PATH="$1" ENTITLEMENTS_PATH="${2:-}" SIGNING_IDENTITY="${SIGNING_IDENTITY:-Developer ID Application}" -KEYCHAIN_NAME="${KEYCHAIN_NAME:-build.keychain}" +# KEYCHAIN_NAME is set by CI workflow - don't set a default here so we can detect if we're in CI 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 +# Unlock keychain if password and keychain name are provided (CI environment) +if [ -n "${KEYCHAIN_PASSWORD:-}" ] && [ -n "${KEYCHAIN_NAME:-}" ]; then security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_NAME" || true fi # Get the SHA-1 hash of the signing certificate # Using the hash avoids "ambiguous" errors when the same identity exists in multiple keychains -echo "Available codesigning identities:" -security find-identity -v -p codesigning +# We look in the build keychain specifically if KEYCHAIN_NAME is set (CI environment) +# Otherwise fall back to searching all keychains (local dev) + +if [ -n "${KEYCHAIN_NAME:-}" ]; then + # CI environment: look for certificate in the build keychain specifically + KEYCHAIN_PATH="$HOME/Library/Keychains/${KEYCHAIN_NAME}-db" + echo "Looking for signing identity in build keychain: $KEYCHAIN_PATH" + echo "Available identities in build keychain:" + security find-identity -v -p codesigning "$KEYCHAIN_PATH" + + CERT_HASH=$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" | grep -E '^\s+[0-9]+\)' | head -1 | awk '{print $2}') +else + # Local dev: search all keychains + echo "Available codesigning identities:" + security find-identity -v -p codesigning + + CERT_HASH=$(security find-identity -v -p codesigning | grep -E '^\s+[0-9]+\)' | head -1 | awk '{print $2}') +fi -# Get the first valid identity hash (the hash is unique and unambiguous) -CERT_HASH=$(security find-identity -v -p codesigning | grep -E '^\s+[0-9]+\)' | head -1 | awk '{print $2}') if [ -z "$CERT_HASH" ]; then echo "ERROR: No valid signing identity found" exit 1 @@ -42,13 +58,11 @@ echo "Using certificate hash: $CERT_HASH" SIGNING_IDENTITY="$CERT_HASH" 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 @@ -56,7 +70,6 @@ done 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 @@ -68,7 +81,6 @@ find "$APP_PATH" -name "*.xpc" -print0 | while IFS= read -r -d '' item; do fi echo "Signing XPC service: $item" codesign --force --verify --verbose --timestamp --options runtime \ - --keychain "$KEYCHAIN_NAME" \ --sign "$SIGNING_IDENTITY" "$item" done @@ -80,7 +92,6 @@ find "$APP_PATH" -path "*/Frameworks/*.app" -print0 | while IFS= read -r -d '' i fi echo "Signing nested app: $item" codesign --force --verify --verbose --timestamp --options runtime \ - --keychain "$KEYCHAIN_NAME" \ --sign "$SIGNING_IDENTITY" "$item" done @@ -92,7 +103,6 @@ find "$APP_PATH" -path "*/Frameworks/*/Versions/*/Autoupdate" -type f -print0 | fi echo "Signing executable: $item" codesign --force --verify --verbose --timestamp --options runtime \ - --keychain "$KEYCHAIN_NAME" \ --sign "$SIGNING_IDENTITY" "$item" done @@ -102,12 +112,10 @@ 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 @@ -117,12 +125,10 @@ 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