diff --git a/.gitea/actions/macos-notarize/action.yml b/.gitea/actions/macos-notarize/action.yml
index 9b06d0e0..1f9c1973 100644
--- a/.gitea/actions/macos-notarize/action.yml
+++ b/.gitea/actions/macos-notarize/action.yml
@@ -177,7 +177,61 @@ runs:
else
echo "Signing app bundle with Developer ID hash: $IDENTITY_HASH"
- # Sign the app bundle using the hash
+ # Enhanced deep recursive signing for all binaries
+ echo "🔍 Performing deep recursive signing of all components..."
+
+ # First, find all .dylib files and sign them individually
+ echo "Signing all dynamic libraries (.dylib files)..."
+ find "${{ inputs.app-path }}" -name "*.dylib" | while read -r dylib; do
+ echo "Signing: $dylib"
+ codesign --force --verbose --options runtime --entitlements "${{ inputs.entitlements-file }}" --sign "$IDENTITY_HASH" --timestamp "$dylib" || echo "⚠️ Failed to sign: $dylib"
+ done
+
+ # Sign all .so files
+ echo "Signing all shared objects (.so files)..."
+ find "${{ inputs.app-path }}" -name "*.so" | while read -r so; do
+ echo "Signing: $so"
+ codesign --force --verbose --options runtime --entitlements "${{ inputs.entitlements-file }}" --sign "$IDENTITY_HASH" --timestamp "$so" || echo "⚠️ Failed to sign: $so"
+ done
+
+ # Sign all executable files (files with execute permission)
+ echo "Signing all executable files..."
+ find "${{ inputs.app-path }}" -type f -perm +111 -not -path "*.framework/*" -not -name "*.dylib" -not -name "*.so" | while read -r exe; do
+ echo "Signing executable: $exe"
+ codesign --force --verbose --options runtime --entitlements "${{ inputs.entitlements-file }}" --sign "$IDENTITY_HASH" --timestamp "$exe" || echo "⚠️ Failed to sign: $exe"
+ done
+
+ # Sign all frameworks
+ echo "Signing frameworks..."
+ find "${{ inputs.app-path }}" -path "*.framework" -type d | while read -r framework; do
+ echo "Signing framework: $framework"
+ codesign --force --verbose --options runtime --entitlements "${{ inputs.entitlements-file }}" --sign "$IDENTITY_HASH" --timestamp "$framework" || echo "⚠️ Failed to sign: $framework"
+ done
+
+ # Special handling for CrashReportClient.app
+ CRASH_REPORTER=$(find "${{ inputs.app-path }}" -path "*CrashReportClient.app" -type d | head -1)
+ if [ -n "$CRASH_REPORTER" ]; then
+ echo "🔍 Special handling for CrashReportClient.app: $CRASH_REPORTER"
+ # Sign CrashReportClient.app specifically with focus on hardened runtime
+ find "$CRASH_REPORTER" -type f -perm +111 | while read -r crash_bin; do
+ echo "Signing CrashReportClient binary: $crash_bin"
+ codesign --force --verbose --options runtime --entitlements "${{ inputs.entitlements-file }}" --sign "$IDENTITY_HASH" --timestamp "$crash_bin" || echo "⚠️ Failed to sign: $crash_bin"
+ done
+
+ echo "Signing the CrashReportClient.app bundle itself..."
+ codesign --force --deep --verbose --options runtime --entitlements "${{ inputs.entitlements-file }}" --sign "$IDENTITY_HASH" --timestamp "$CRASH_REPORTER" || echo "⚠️ Failed to sign CrashReportClient.app"
+ fi
+
+ # Sign any other nested app bundles
+ find "${{ inputs.app-path }}" -path "*.app" -type d | grep -v CrashReportClient | while read -r nested_app; do
+ if [ "$nested_app" != "${{ inputs.app-path }}" ]; then
+ echo "Signing nested app: $nested_app"
+ codesign --force --deep --verbose --options runtime --entitlements "${{ inputs.entitlements-file }}" --sign "$IDENTITY_HASH" --timestamp "$nested_app" || echo "⚠️ Failed to sign: $nested_app"
+ fi
+ done
+
+ # Final signing of the main bundle
+ echo "🔐 Performing final signing of the main app bundle..."
codesign --force --deep --verbose --options runtime --entitlements "${{ inputs.entitlements-file }}" --sign "$IDENTITY_HASH" --timestamp "${{ inputs.app-path }}"
echo "::set-output name=signed::identity"
fi
@@ -189,6 +243,16 @@ runs:
# Check entitlements
echo "🔍 Checking entitlements..."
codesign -d --entitlements - "${{ inputs.app-path }}"
+
+ # Verify CrashReportClient
+ CRASH_REPORTER=$(find "${{ inputs.app-path }}" -path "*CrashReportClient.app" -type d | head -1)
+ if [ -n "$CRASH_REPORTER" ]; then
+ echo "🔍 Verifying CrashReportClient signature..."
+ codesign -vvv --deep --strict "$CRASH_REPORTER" || echo "⚠️ CrashReportClient may have verification issues"
+
+ echo "CrashReportClient entitlements:"
+ codesign -d --entitlements - "$CRASH_REPORTER" || echo "⚠️ Could not display CrashReportClient entitlements"
+ fi
- name: Notarize App
id: notarize
diff --git a/.gitea/workflows/test-macos-build.yml b/.gitea/workflows/test-macos-build.yml
index 887c9046..f6fa982a 100644
--- a/.gitea/workflows/test-macos-build.yml
+++ b/.gitea/workflows/test-macos-build.yml
@@ -30,6 +30,29 @@ jobs:
echo "Environment setup complete"
shell: bash
+ # Set correct bundle identifier before build
+ - name: Set bundle identifier
+ run: |
+ # Set the correct bundle identifier in DefaultGame.ini if it exists
+ CONFIG_FILE="Config/DefaultGame.ini"
+ if [ -f "$CONFIG_FILE" ]; then
+ # Check if section exists or add it
+ if grep -q "\[/Script/MacTargetPlatform\.MacTargetSettings\]" "$CONFIG_FILE"; then
+ # Section exists, update the setting
+ sed -i '' 's/BundleIdentifier=.*/BundleIdentifier=com.luckyrobots.luckyworld/g' "$CONFIG_FILE"
+ else
+ # Section doesn't exist, add it
+ echo "" >> "$CONFIG_FILE"
+ echo "[/Script/MacTargetPlatform.MacTargetSettings]" >> "$CONFIG_FILE"
+ echo "BundleIdentifier=com.luckyrobots.luckyworld" >> "$CONFIG_FILE"
+ fi
+ echo "Updated bundle ID in project config"
+ fi
+
+ # Set the constant bundle ID for the workflow
+ echo "BUNDLE_ID=com.luckyrobots.luckyworld" >> "$GITHUB_ENV"
+ shell: bash
+
# Build for macOS - use your own build script or create a test app if needed
- name: Build for macOS
run: |
@@ -86,14 +109,65 @@ jobs:
# Export APP_PATH for next steps to use
echo "APP_PATH=$MAIN_APP_PATH" >> "$GITHUB_ENV"
- # Extract bundle ID from Info.plist
+ # Fix bundle ID in Info.plist before signing
if [ -f "$MAIN_APP_PATH/Contents/Info.plist" ]; then
- BUNDLE_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$MAIN_APP_PATH/Contents/Info.plist")
- echo "Detected bundle ID from app: $BUNDLE_ID"
- echo "BUNDLE_ID=$BUNDLE_ID" >> "$GITHUB_ENV"
+ echo "Setting bundle identifier to $BUNDLE_ID"
+ /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $BUNDLE_ID" "$MAIN_APP_PATH/Contents/Info.plist"
+ echo "Updated bundle ID in Info.plist: $(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$MAIN_APP_PATH/Contents/Info.plist")"
else
- echo "WARNING: Could not find Info.plist in app bundle. Using default bundle ID."
- echo "BUNDLE_ID=com.YourCompany.LuckyWorld" >> "$GITHUB_ENV"
+ echo "WARNING: Could not find Info.plist in app bundle."
+ fi
+
+ # Find and repair nested app bundles as well (like CrashReportClient.app)
+ NESTED_APPS=$(find "$MAIN_APP_PATH" -name "*.app" -type d)
+ if [ -n "$NESTED_APPS" ]; then
+ echo "Found nested app bundles, fixing their bundle IDs:"
+ echo "$NESTED_APPS" | while read -r NESTED_APP; do
+ if [ -f "$NESTED_APP/Contents/Info.plist" ]; then
+ NESTED_NAME=$(basename "$NESTED_APP" .app)
+ NESTED_BUNDLE_ID="$BUNDLE_ID.$NESTED_NAME"
+ echo "Setting nested bundle ID to $NESTED_BUNDLE_ID for $NESTED_APP"
+ /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $NESTED_BUNDLE_ID" "$NESTED_APP/Contents/Info.plist"
+ fi
+ done
+ fi
+ shell: bash
+
+ # Fix common issues that may cause notarization failure
+ - name: Fix common issues for notarization
+ run: |
+ echo "🛠️ Fixing common issues that may cause notarization failure..."
+
+ APP_PATH="${{ env.APP_PATH }}"
+
+ # Remove get-task-allow entitlement from Info.plist files
+ echo "Checking for get-task-allow entitlement..."
+ find "$APP_PATH" -name "*.plist" -exec plutil -convert xml1 {} \; -exec grep -l "get-task-allow" {} \; | while read -r plist_file; do
+ echo "Removing get-task-allow from $plist_file"
+ /usr/libexec/PlistBuddy -c "Delete :com.apple.security.get-task-allow" "$plist_file" 2>/dev/null || true
+ done
+
+ # Check for problematic libraries that cause issues
+ echo "Looking for problematic files..."
+ PROBLEM_FILES=$(find "$APP_PATH" -type f -name "*.dylib" | grep -i "boost\|tbb\|ogg\|vorbis\|onnx")
+ if [ -n "$PROBLEM_FILES" ]; then
+ echo "Found potentially problematic libraries. These will be carefully handled during signing:"
+ echo "$PROBLEM_FILES" | head -10
+ if [ $(echo "$PROBLEM_FILES" | wc -l) -gt 10 ]; then
+ echo "... and $(echo "$PROBLEM_FILES" | wc -l) more"
+ fi
+ fi
+
+ # Verify CrashReportClient specifically
+ CRASH_REPORTER=$(find "$APP_PATH" -path "*CrashReportClient.app*" -type d | head -1)
+ if [ -n "$CRASH_REPORTER" ]; then
+ echo "Found CrashReportClient at $CRASH_REPORTER"
+ if [ -f "$CRASH_REPORTER/Contents/Info.plist" ]; then
+ # Ensure it has the correct bundle ID format
+ CRASH_BUNDLE_ID="$BUNDLE_ID.CrashReportClient"
+ echo "Setting CrashReportClient bundle ID to $CRASH_BUNDLE_ID"
+ /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $CRASH_BUNDLE_ID" "$CRASH_REPORTER/Contents/Info.plist"
+ fi
fi
shell: bash
@@ -112,7 +186,7 @@ jobs:
notary-api-key-issuer-id: ${{ secrets.NOTARY_API_KEY_ISSUER_ID }}
notary-api-key-path: ${{ secrets.NOTARY_API_KEY_PATH }}
bundle-id: ${{ env.BUNDLE_ID }}
- fallback-to-adhoc: 'true'
+ fallback-to-adhoc: 'false'
# Upload signed app if available
- name: Upload Signed App
diff --git a/LuckyWorld.entitlements b/LuckyWorld.entitlements
index ee35bd86..4dc9a495 100644
--- a/LuckyWorld.entitlements
+++ b/LuckyWorld.entitlements
@@ -14,5 +14,13 @@
com.apple.security.device.camera
+ com.apple.security.automation.apple-events
+
+ com.apple.security.cs.debugger
+
+ com.apple.security.files.user-selected.read-write
+
+ com.apple.security.network.client
+
\ No newline at end of file
diff --git a/scripts/mac_build.sh b/scripts/mac_build.sh
index 7f243488..d8b46c43 100755
--- a/scripts/mac_build.sh
+++ b/scripts/mac_build.sh
@@ -13,6 +13,22 @@ PROJECT_ROOT="$(pwd)"
PROJECT_FILE="$PROJECT_ROOT/LuckyWorld.uproject"
ARCHIVE_DIR="$PROJECT_ROOT/Builds"
+# Check for Developer ID certificate
+CERTIFICATE_NAME=""
+if [ -z "$CERTIFICATE_NAME" ]; then
+ # Try to find a Developer ID Application certificate
+ CERTIFICATE_NAME=$(security find-identity -v -p codesigning | grep "Developer ID Application" | head -1 | sed -E 's/.*"(Developer ID Application.*)"$/\1/')
+
+ if [ -z "$CERTIFICATE_NAME" ]; then
+ echo "⚠️ No Developer ID Application certificate found. Please specify a valid certificate name."
+ echo "Available certificates:"
+ security find-identity -v -p codesigning
+ exit 1
+ else
+ echo "🔑 Found Developer ID certificate: $CERTIFICATE_NAME"
+ fi
+fi
+
# Check for entitlements file
if [ -f "$PROJECT_ROOT/LuckyWorld.entitlements" ]; then
ENTITLEMENTS_FILE="$PROJECT_ROOT/LuckyWorld.entitlements"
@@ -28,6 +44,7 @@ echo "Project root: $PROJECT_ROOT"
echo "Project file: $PROJECT_FILE"
echo "Archive directory: $ARCHIVE_DIR"
echo "Entitlements file: $ENTITLEMENTS_FILE"
+echo "Signing with certificate: $CERTIFICATE_NAME"
# Clean up previous build artifacts
rm -rf DerivedDataCache Intermediate Binaries Saved
@@ -97,17 +114,17 @@ if [ -n "$APP_PATH" ]; then
find "$APP_PATH" -name "*PhysX*" -o -name "*APEX*"
fi
-# Bundle ID'yi proje ayarlarında güncelle
+# Update bundle ID in project settings
echo ""
echo "🔧 Updating bundle ID in UE config..."
CONFIG_FILE="$PROJECT_ROOT/Config/DefaultGame.ini"
if [ -f "$CONFIG_FILE" ]; then
- # Mevcut bölümü kontrol et veya ekle
+ # Check if section exists or add it
if grep -q "\[/Script/MacTargetPlatform\.MacTargetSettings\]" "$CONFIG_FILE"; then
- # Bölüm var, ayarı güncelleyebiliriz
+ # Section exists, update the setting
sed -i '' 's/BundleIdentifier=.*/BundleIdentifier=com.luckyrobots.luckyworld/g' "$CONFIG_FILE"
else
- # Bölüm yok, eklememiz gerekiyor
+ # Section doesn't exist, add it
echo "" >> "$CONFIG_FILE"
echo "[/Script/MacTargetPlatform.MacTargetSettings]" >> "$CONFIG_FILE"
echo "BundleIdentifier=com.luckyrobots.luckyworld" >> "$CONFIG_FILE"
@@ -115,7 +132,7 @@ if [ -f "$CONFIG_FILE" ]; then
echo "Updated bundle ID in project config"
fi
-# Build sonrası işlemler - bundle ID ayarlama
+# Post-build process - set bundle ID
echo ""
echo "🔧 Performing post-build fix for bundle ID..."
if [ -n "$APP_PATH" ]; then
@@ -129,16 +146,17 @@ if [ -n "$APP_PATH" ]; then
fi
fi
-# Recursive imzalama fonksiyonu - tüm binary dosyaları imzalar
+# Recursive signing function - signs all binary files
function sign_recursively() {
local app_path="$1"
local entitlements_file="$2"
+ local certificate="$3"
local counter=0
local total=0
local failed=0
- # Önce toplam dosya sayısını hesapla
- # Tüm binary dosyaları bul (executable, dylib, so, çerçeveler)
+ # First calculate total file count
+ # Find all binary files (executables, dylibs, .so files, frameworks)
echo "Scanning for binary files..."
# Executable binary files (libraries, executables)
@@ -147,12 +165,12 @@ function sign_recursively() {
echo "Found $total binary files to sign"
- # Helper binary dosyaları imzala (tercih sırasına göre)
+ # Sign helper binary files (in order of preference)
echo "Signing all binary files (libraries and executables)..."
echo "$binaries" | while read -r binary; do
counter=$((counter + 1))
- # Her 20 dosyada bir ilerleme göster
+ # Show progress every 20 files
if [ $((counter % 20)) -eq 0 ] || [ $counter -eq 1 ] || [ $counter -eq $total ]; then
echo "Progress: $counter/$total - Signing: $binary"
fi
@@ -162,10 +180,10 @@ function sign_recursively() {
continue
fi
- # Dosya türünü kontrol et
+ # Check file type
file_info=$(file "$binary")
- # Sadece Mach-O dosyalarını imzala
+ # Only sign Mach-O files
if ! echo "$file_info" | grep -q "Mach-O"; then
continue
fi
@@ -174,18 +192,18 @@ function sign_recursively() {
echo "🛠️ Special handling for CrashReportClient: $binary"
fi
- # Timestamp ve runtime options ile imzala
- codesign --force --options runtime --deep --sign - --timestamp --entitlements "$entitlements_file" "$binary" 2>&1 || {
+ # Sign with timestamp and runtime options
+ codesign --force --options runtime --deep --sign "$certificate" --timestamp --entitlements "$entitlements_file" "$binary" 2>&1 || {
echo "⚠️ Failed to sign: $binary"
failed=$((failed + 1))
}
done
- # Başvuru için ENTITLEMENTS içeriğini göster
+ # Show ENTITLEMENTS content for reference
echo "Using entitlements file for signatures:"
cat "$entitlements_file"
- # Tüm nested app'leri bul ve imzala
+ # Find all nested apps and sign them
nested_apps=$(find "$app_path" -name "*.app" -type d)
if [ -n "$nested_apps" ]; then
@@ -194,14 +212,14 @@ function sign_recursively() {
if [ "$nested_app" != "$app_path" ]; then
echo "Signing nested app: $nested_app"
- # İmzalamadan önce Info.plist varsa Bundle ID ayarla
+ # Set Bundle ID in Info.plist if it exists before signing
nested_info="$nested_app/Contents/Info.plist"
if [ -f "$nested_info" ]; then
echo "Setting bundle identifier for nested app"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier com.luckyrobots.luckyworld.nested" "$nested_info" 2>/dev/null || true
fi
- codesign --force --options runtime --deep --sign - --timestamp --entitlements "$entitlements_file" "$nested_app" 2>&1 || {
+ codesign --force --options runtime --deep --sign "$certificate" --timestamp --entitlements "$entitlements_file" "$nested_app" 2>&1 || {
echo "⚠️ Failed to sign nested app: $nested_app"
failed=$((failed + 1))
}
@@ -209,24 +227,24 @@ function sign_recursively() {
done
fi
- # Asıl uygulamayı imzala
+ # Sign the main application
echo "Signing main application: $app_path"
- codesign --force --options runtime --deep --sign - --timestamp --entitlements "$entitlements_file" "$app_path" 2>&1 || {
+ codesign --force --options runtime --deep --sign "$certificate" --timestamp --entitlements "$entitlements_file" "$app_path" 2>&1 || {
echo "⚠️ Failed to sign main app: $app_path"
failed=$((failed + 1))
}
echo "✅ Signing completed: $counter files processed, $failed failures"
- # İmzalama durumunu kontrol et
+ # Check signing status
echo "Verifying signatures..."
codesign -vvv --deep --strict "$app_path"
- # Hardened Runtime ve diğer güvenlik ayarları kontrol et
+ # Check Hardened Runtime and other security settings
echo "Checking security settings (Hardened Runtime, etc.):"
codesign -d --entitlements - "$app_path" | grep -i "runtime\|hardened\|security"
- # Spesifik olarak CrashReportClient'i kontrol et (sorunlu dosya)
+ # Check CrashReportClient specifically (problematic file)
crash_reporter=$(find "$app_path" -path "*CrashReportClient.app/Contents/MacOS/CrashReportClient" -type f | head -1)
if [ -n "$crash_reporter" ]; then
echo "Checking CrashReportClient specifically:"
@@ -234,18 +252,33 @@ function sign_recursively() {
fi
}
-# Kütüphaneleri kontrol et ve gerekirse post-processing yap
+# Check libraries and perform post-processing if needed
echo ""
echo "🔍 Performing comprehensive signing and hardening of all binaries..."
if [ -n "$APP_PATH" ] && [ -n "$ENTITLEMENTS_FILE" ]; then
- # Recursive olarak tüm binary dosyaları imzala
- sign_recursively "$APP_PATH" "$ENTITLEMENTS_FILE"
+ # Sign all binary files recursively
+ sign_recursively "$APP_PATH" "$ENTITLEMENTS_FILE" "$CERTIFICATE_NAME"
- # Son olarak ana uygulamayı tekrar imzala
+ # Final signing of the main app bundle
echo "Final signing of main app bundle"
- codesign --force --options runtime --deep --sign - --timestamp --entitlements "$ENTITLEMENTS_FILE" "$APP_PATH"
+ codesign --force --options runtime --deep --sign "$CERTIFICATE_NAME" --timestamp --entitlements "$ENTITLEMENTS_FILE" "$APP_PATH"
echo "✅ All binaries signed successfully with Hardened Runtime enabled"
+
+ # Prepare app for notarization
+ echo ""
+ echo "🔐 Preparing for notarization..."
+
+ # Create a ZIP archive for notarization
+ ZIP_PATH="$ARCHIVE_DIR/LuckyWorld.zip"
+ echo "Creating ZIP archive for notarization: $ZIP_PATH"
+ ditto -c -k --keepParent "$APP_PATH" "$ZIP_PATH"
+
+ echo "✅ ZIP archive created for notarization at: $ZIP_PATH"
+ echo ""
+ echo "To notarize the app, run the following command:"
+ echo "xcrun notarytool submit \"$ZIP_PATH\" --apple-id \"YOUR_APPLE_ID\" --password \"APP_SPECIFIC_PASSWORD\" --team-id \"YOUR_TEAM_ID\" --wait"
+ echo ""
else
echo "❌ App path or entitlements file not found, cannot perform comprehensive signing"
echo "App path: $APP_PATH"