From 619d4d82981e8fb157861a196e9f61c282ee7a10 Mon Sep 17 00:00:00 2001 From: Ozgur Ersoy Date: Tue, 15 Apr 2025 20:48:33 +0200 Subject: [PATCH] fix(actions): simplify macOS build workflow by removing redundant bundle ID checks and enhancing notarization issue verification --- .gitea/workflows/test-macos-build.yml | 216 +++----------------------- Config/DefaultEngine.ini | 10 ++ scripts/mac_build.sh | 141 ++--------------- 3 files changed, 47 insertions(+), 320 deletions(-) diff --git a/.gitea/workflows/test-macos-build.yml b/.gitea/workflows/test-macos-build.yml index 826c285d..3146c53b 100644 --- a/.gitea/workflows/test-macos-build.yml +++ b/.gitea/workflows/test-macos-build.yml @@ -29,48 +29,12 @@ jobs: # Create directories for builds mkdir -p Builds/Mac mkdir -p PackagedReleases + mkdir -p ArchivedApps echo "Environment setup complete" shell: bash - - # Verify bundle identifier is correctly set - - name: Verify bundle identifier - run: | - # Set the constant bundle ID for the workflow - echo "BUNDLE_ID=com.luckyrobots.luckyworld" >> "$GITHUB_ENV" - - # Verify the bundle ID is correctly set in DefaultGame.ini - CONFIG_FILE="Config/DefaultGame.ini" - if [ -f "$CONFIG_FILE" ]; then - if grep -q "\[/Script/MacTargetPlatform\.MacTargetSettings\]" "$CONFIG_FILE" && grep -q "BundleIdentifier=com.luckyrobots.luckyworld" "$CONFIG_FILE"; then - echo "✅ Bundle ID correctly set in DefaultGame.ini" - else - echo "⚠️ Warning: Bundle ID may not be correctly set in DefaultGame.ini" - echo "Please make sure the following section exists:" - echo "[/Script/MacTargetPlatform.MacTargetSettings]" - echo "BundleIdentifier=com.luckyrobots.luckyworld" - fi - else - echo "⚠️ DefaultGame.ini not found!" - fi - shell: bash - # Check Unreal Engine Project settings - - name: Inspect Unreal Settings - run: | - # Check for any potential issues in UE project settings - if [ -f "Config/DefaultEngine.ini" ]; then - echo "Checking DefaultEngine.ini for settings that might affect bundle ID..." - grep -i "bundle\|identifier\|package" Config/DefaultEngine.ini || echo "No relevant settings found" - fi - - if [ -f "Config/DefaultGame.ini" ]; then - echo "Checking DefaultGame.ini for settings that might affect bundle ID..." - grep -i "bundle\|identifier\|package" Config/DefaultGame.ini || echo "No relevant settings found" - fi - shell: bash - - # Build for macOS - use your own build script or create a test app if needed + # Build for macOS - use your own build script - name: Build for macOS run: | if [ -f "./scripts/mac_build.sh" ]; then @@ -105,27 +69,6 @@ jobs: echo "Build status check..." if [ ! -d "./Builds" ] && [ ! -d "./Saved/StagedBuilds" ]; then echo "❌ ERROR: Build directories do not exist. Build likely failed." - echo "Checking build logs for common issues..." - - # Check for the specific GlobalDefinitions error - if grep -q "GlobalDefinitions.*This is not allowed" "$GITHUB_WORKSPACE"/*.log 2>/dev/null || grep -q "BuildEnvironment\|bOverrideBuildEnvironment" "$GITHUB_WORKSPACE"/*.log 2>/dev/null; then - echo "🔍 Found issue with GlobalDefinitions in build target." - echo "⚠️ Fix required in LuckyWorld.Target.cs - need to add bOverrideBuildEnvironment = true;" - echo "Fix suggestion for LuckyWorld.Target.cs:" - echo "Add this line in the constructor:" - echo " bOverrideBuildEnvironment = true;" - echo "" - echo "Example:" - echo " public LuckyWorldTarget(TargetInfo Target) : base(Target)" - echo " {" - echo " Type = TargetType.Game;" - echo " DefaultBuildSettings = BuildSettingsVersion.V5;" - echo " bOverrideBuildEnvironment = true; // Add this line" - echo " " - echo " // Rest of your constructor..." - echo " }" - fi - exit 1 fi @@ -170,96 +113,35 @@ jobs: # Export APP_PATH for next steps to use echo "APP_PATH=$MAIN_APP_PATH" >> "$GITHUB_ENV" - # Note: While bundle ID should be set by Unreal Engine build system based on DefaultGame.ini - # and LuckyWorld.Build.cs settings, we still check and fix if needed as a safety measure, - # since UE builds can sometimes have issues with bundle ID propagation - echo "Checking bundle IDs (fallback fix in case UE didn't properly apply settings)..." - - # Fix bundle ID in Info.plist before signing + # Get bundle ID from Info.plist for reference (not modifying) if [ -f "$MAIN_APP_PATH/Contents/Info.plist" ]; then - echo "Checking current bundle identifier..." - CURRENT_BUNDLE_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$MAIN_APP_PATH/Contents/Info.plist") - echo "Current bundle ID: $CURRENT_BUNDLE_ID" - - if [ "$CURRENT_BUNDLE_ID" != "$BUNDLE_ID" ]; then - echo "Bundle ID mismatch - fixing it!" - 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 "✅ Bundle ID is already correct: $BUNDLE_ID" - fi - else - 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 | grep -v "^$MAIN_APP_PATH$") - if [ -n "$NESTED_APPS" ]; then - echo "Found nested app bundles, checking 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" - CURRENT_NESTED_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$NESTED_APP/Contents/Info.plist") - - if [ "$CURRENT_NESTED_ID" != "$NESTED_BUNDLE_ID" ]; then - 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" - - # Verify the change - UPDATED_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$NESTED_APP/Contents/Info.plist") - echo "Updated nested app bundle ID: $UPDATED_ID" - else - echo "✅ Nested app $NESTED_NAME already has correct bundle ID: $CURRENT_NESTED_ID" - fi - fi - done + BUNDLE_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$MAIN_APP_PATH/Contents/Info.plist") + echo "Detected bundle ID: $BUNDLE_ID" + echo "BUNDLE_ID=$BUNDLE_ID" >> "$GITHUB_ENV" fi shell: bash - # Fix common issues that may cause notarization failure - - name: Fix common issues for notarization + # Basic pre-notarization checks + - name: Check for notarization issues run: | - echo "🛠️ Fixing common issues that may cause notarization failure..." + echo "🔍 Checking app for potential notarization issues..." 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 + # Verify code signature already exists (from Unreal build) + echo "Checking existing signature..." + codesign -vvv "$APP_PATH" || echo "⚠️ App may not be properly signed by Unreal Engine" - # 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 + # Check for any ad-hoc signatures that would cause issues + if codesign -dvv "$APP_PATH" 2>&1 | grep -q "adhoc"; then + echo "⚠️ Warning: Ad-hoc signature detected. This will be replaced with a proper signature." 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" - CURRENT_CRASH_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$CRASH_REPORTER/Contents/Info.plist") - - if [ "$CURRENT_CRASH_ID" != "$CRASH_BUNDLE_ID" ]; then - echo "Setting CrashReportClient bundle ID to $CRASH_BUNDLE_ID" - /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $CRASH_BUNDLE_ID" "$CRASH_REPORTER/Contents/Info.plist" - echo "Updated CrashReportClient bundle ID: $(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$CRASH_REPORTER/Contents/Info.plist")" - else - echo "✅ CrashReportClient already has correct bundle ID: $CURRENT_CRASH_ID" - fi - fi + # Verify entitlements file exists + if [ ! -f "${{ env.ENTITLEMENTS_FILE }}" ]; then + echo "⚠️ Entitlements file not found. Will use default entitlements." + else + echo "Found entitlements file: ${{ env.ENTITLEMENTS_FILE }}" fi shell: bash @@ -280,69 +162,13 @@ jobs: bundle-id: ${{ env.BUNDLE_ID }} fallback-to-adhoc: 'false' - # Additional verification and stapling to ensure the app opens without warning - - name: Verify and Staple App - if: steps.sign-and-notarize.outputs.notarized == 'true' && steps.sign-and-notarize.outputs.signed != 'none' - run: | - echo "🔒 Performing additional verification and stapling..." - APP_PATH="${{ env.APP_PATH }}" - - # Make sure the app is properly stapled - echo "Stapling notarization ticket to the app..." - xcrun stapler staple "$APP_PATH" - - # Verify the stapling - echo "Verifying stapling..." - xcrun stapler validate "$APP_PATH" - - # Perform deep verification of code signing - echo "Verifying code signature (deep)..." - codesign -vvv --deep "$APP_PATH" - - # Additional check for quarantine attributes - echo "Checking for quarantine attributes..." - if [ -n "$(xattr -l "$APP_PATH" | grep quarantine)" ]; then - echo "Removing quarantine attribute..." - xattr -d com.apple.quarantine "$APP_PATH" - else - echo "No quarantine attribute found, good!" - fi - - echo "✅ Verification and stapling completed!" - - # Export STAPLED_APP_PATH for later use - echo "STAPLED_APP_PATH=$APP_PATH" >> "$GITHUB_ENV" - shell: bash - - # Create a DMG file (macOS disk image) for easy distribution - - name: Create DMG for Distribution - if: steps.sign-and-notarize.outputs.notarized == 'true' && steps.sign-and-notarize.outputs.signed != 'none' - run: | - STAPLED_APP_PATH="${{ env.STAPLED_APP_PATH }}" - APP_NAME=$(basename "$STAPLED_APP_PATH" .app) - ARCHIVE_DIR="./ArchivedApps" - DMG_FILE="$ARCHIVE_DIR/$APP_NAME.dmg" - - # Note: The actual DMG creation, signing, notarization and stapling - # are now handled by the macos-notarize action - - # Just ensure we have the correct path for outputs - if [ -f "${{ steps.sign-and-notarize.outputs.package-path }}" ]; then - echo "Using DMG created by the macos-notarize action" - echo "DMG file location: ${{ steps.sign-and-notarize.outputs.package-path }}" - echo "STAPLED_APP_DMG=${{ steps.sign-and-notarize.outputs.package-path }}" >> "$GITHUB_ENV" - else - echo "⚠️ DMG not found from the macos-notarize action output" - fi - shell: bash - # Upload stapled app directly (this is the most reliable approach) - name: Upload Stapled App Bundle uses: actions/upload-artifact@v3 if: steps.sign-and-notarize.outputs.notarized == 'true' && steps.sign-and-notarize.outputs.signed != 'none' with: name: LuckyWorld-macOS-Stapled-App-Bundle - path: ${{ env.STAPLED_APP_PATH }} + path: ${{ env.APP_PATH }} retention-days: 30 # Create a properly archived ZIP of the stapled app (preserves stapling) diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 2861d450..fcda2735 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -361,3 +361,13 @@ EnableCodeCoverage=False EnableCodeCoveragePath=(Path="") ForwardShading=False UseFastCopyToResolve=True + +[/Script/MacTargetPlatform.XcodeProjectSettings] +bMacSignToRunLocally=False +CodeSigningPrefix=com.luckyrobots +ApplicationDisplayName=LuckyWorld +CodeSigningTeam=937UD94CX2 +bUseAutomaticCodeSigning=False +ShippingSpecificMacEntitlements=(FilePath="../LuckyWorld.entitlements") +MacSigningIdentity=Developer ID Application + diff --git a/scripts/mac_build.sh b/scripts/mac_build.sh index 10b45411..11eac0c8 100755 --- a/scripts/mac_build.sh +++ b/scripts/mac_build.sh @@ -16,24 +16,26 @@ ARCHIVE_DIR="$PROJECT_ROOT/Builds" # Check for entitlements file if [ -f "$PROJECT_ROOT/LuckyWorld.entitlements" ]; then ENTITLEMENTS_FILE="$PROJECT_ROOT/LuckyWorld.entitlements" + echo "✅ Using entitlements file: $ENTITLEMENTS_FILE" else - echo "Warning: No entitlements file found. This might affect notarization." + echo "⚠️ Warning: No entitlements file found. This might affect notarization." ENTITLEMENTS_FILE="" fi -# For debugging: print paths and config +# Print paths and config for debugging echo "Project root: $PROJECT_ROOT" echo "Project file: $PROJECT_FILE" echo "Archive directory: $ARCHIVE_DIR" -echo "Entitlements file: $ENTITLEMENTS_FILE" # Clean up previous build artifacts rm -rf DerivedDataCache Intermediate Binaries Saved # Generate project files +echo "📝 Generating project files..." "$UE_ROOT/Engine/Build/BatchFiles/Mac/GenerateProjectFiles.sh" -project="$PROJECT_FILE" -game -engine # Run the build command +echo "🔨 Starting build process..." "$UE_UAT" -ScriptsForProject="$PROJECT_FILE" Turnkey \ -command=VerifySdk \ -platform=Mac \ @@ -61,20 +63,11 @@ rm -rf DerivedDataCache Intermediate Binaries Saved -prereqs \ -archivedirectory="$ARCHIVE_DIR" \ -CrashReporter \ - -clientconfig=Shipping \ - # -nocompile \ - # -nocompileuat \ - # -nocompileeditor \ - # -skipbuildeditor \ - - # enable these if you want to test build without pak and iostore (you're just testing the build) - # -skipiostore \ - # -skippak \ (disable -pak and -iostore) + -clientconfig=Shipping echo "" -echo "🦾 Build completed. Application path:" +echo "🔍 Looking for built application..." APP_PATH=$(find "$ARCHIVE_DIR" -name "*.app" -type d | head -n 1) -echo "$APP_PATH" # Check if the build actually succeeded by verifying the app exists if [ -z "$APP_PATH" ] || [ ! -d "$APP_PATH" ]; then @@ -86,9 +79,12 @@ if [ -z "$APP_PATH" ] || [ ! -d "$APP_PATH" ]; then exit 1 fi +echo "✅ Build completed successfully! Application path:" +echo "$APP_PATH" + if [ -n "$APP_PATH" ]; then echo "" - echo "🔍 Binary files that will need signing:" + echo "🔍 Binary files summary:" DYLIB_COUNT=$(find "$APP_PATH" -name "*.dylib" | wc -l) SO_COUNT=$(find "$APP_PATH" -name "*.so" | wc -l) FRAMEWORKS=$(find "$APP_PATH" -path "*.framework/*" -type f -perm +111 | wc -l) @@ -100,120 +96,15 @@ if [ -n "$APP_PATH" ]; then echo "- $EXECUTABLES other executables" echo "Total binary files: $((DYLIB_COUNT + SO_COUNT + FRAMEWORKS + EXECUTABLES))" - echo "" - echo "🔍 Checking for PhysX and other special libraries (often need special handling):" - find "$APP_PATH" -name "*PhysX*" -o -name "*APEX*" -fi - -# Update bundle ID in project settings -echo "" -echo "🔧 Checking for bundle ID in UE config..." -CONFIG_FILE="$PROJECT_ROOT/Config/DefaultGame.ini" -if [ -f "$CONFIG_FILE" ]; then - if grep -q "\[/Script/MacTargetPlatform\.MacTargetSettings\]" "$CONFIG_FILE" && grep -q "BundleIdentifier=com.luckyrobots.luckyworld" "$CONFIG_FILE"; then - echo "Bundle ID already correctly set in project config ✅" - else - echo "⚠️ Warning: Bundle ID may not be correctly set in DefaultGame.ini" - echo "Please ensure [/Script/MacTargetPlatform.MacTargetSettings] section exists with BundleIdentifier=com.luckyrobots.luckyworld" - fi -else - echo "⚠️ Config file not found at $CONFIG_FILE" -fi - -# Post-build process - set bundle ID -echo "" -echo "🔍 Checking bundle ID in built app..." -echo "Note: Bundle ID should be automatically set by Unreal Engine based on DefaultGame.ini and" -echo "LuckyWorld.Build.cs settings, but UE sometimes fails to apply it correctly." -echo "Therefore, we keep this check and fix as a safety measure." - -if [ -n "$APP_PATH" ]; then + # Check bundle ID (for information only, no modifications) INFO_PLIST="$APP_PATH/Contents/Info.plist" if [ -f "$INFO_PLIST" ]; then - CURRENT_BUNDLE_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$INFO_PLIST") - echo "Current bundle ID: $CURRENT_BUNDLE_ID" - - if [ "$CURRENT_BUNDLE_ID" != "com.luckyrobots.luckyworld" ]; then - echo "Bundle ID mismatch - fixing it!" - echo "Setting bundle identifier to com.luckyrobots.luckyworld" - /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier com.luckyrobots.luckyworld" "$INFO_PLIST" - echo "Updated bundle ID: $(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$INFO_PLIST")" - else - echo "✅ Bundle ID is already correct: com.luckyrobots.luckyworld" - fi - else - echo "⚠️ Info.plist not found at $INFO_PLIST" + BUNDLE_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$INFO_PLIST") + echo "" + echo "📦 App Bundle ID: $BUNDLE_ID" fi fi -# If this is a manual build (not in CI), attempt to sign the app locally -if [ -z "$CI" ] && [ -n "$APP_PATH" ]; then - echo "" - echo "🔐 Attempting local code signing and stapling..." - - # Check if we have a valid Apple Developer identity - IDENTITY=$(security find-identity -v -p codesigning | grep "Developer ID Application" | head -1 | sed -E 's/.*\) ([A-F0-9]+) "(.*)"/\2/') - - if [ -n "$IDENTITY" ]; then - echo "Found signing identity: $IDENTITY" - - # Sign the app - echo "Signing application..." - if [ -f "$PROJECT_ROOT/LuckyWorld.entitlements" ]; then - echo "Using entitlements file: $PROJECT_ROOT/LuckyWorld.entitlements" - codesign --force --options runtime --entitlements "$PROJECT_ROOT/LuckyWorld.entitlements" --sign "$IDENTITY" --deep "$APP_PATH" - else - codesign --force --options runtime --sign "$IDENTITY" --deep "$APP_PATH" - fi - - # Verify signature - echo "Verifying signature..." - codesign -vvv --deep "$APP_PATH" - - # Staple the app if notarization is successful - echo "Checking if notarization is needed..." - if xcrun altool --notarization-info $(uuidgen) -u "YOUR_APPLE_ID" 2>&1 | grep -q "success"; then - echo "App is notarized, stapling the ticket..." - xcrun stapler staple "$APP_PATH" - xcrun stapler validate "$APP_PATH" - - # Remove quarantine attribute if present - if [ -n "$(xattr -l "$APP_PATH" | grep quarantine)" ]; then - echo "Removing quarantine attribute..." - xattr -d com.apple.quarantine "$APP_PATH" - fi - else - echo "App is not notarized yet. Upload to Apple's notary service for full verification." - fi - else - echo "⚠️ No Developer ID Application certificate found for signing." - echo "Run 'security find-identity -v -p codesigning' to view available certificates." - fi -else - echo "Skipping local signing (running in CI or app not found)" -fi - -# Find and check nested app bundles (like CrashReportClient.app) -NESTED_APPS=$(find "$APP_PATH" -name "*.app" -type d | grep -v "^$APP_PATH$") -if [ -n "$NESTED_APPS" ]; then - echo "Checking nested app bundles:" - 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="com.luckyrobots.luckyworld.$NESTED_NAME" - CURRENT_NESTED_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$NESTED_APP/Contents/Info.plist") - - if [ "$CURRENT_NESTED_ID" != "$NESTED_BUNDLE_ID" ]; then - 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" - echo "Updated nested app bundle ID: $(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$NESTED_APP/Contents/Info.plist")" - else - echo "Nested app bundle ID already correct: $CURRENT_NESTED_ID" - fi - fi - done -fi - echo "" -echo "✅ Build and post-processing completed!" +echo "✅ Build complete!" echo "App location: $APP_PATH"