LuckyWorld/.gitea/workflows/test-macos-build.yml
Ozgur Ersoy 2e0a1b8b60
All checks were successful
Test macOS Build Action / test-macos-build (push) Successful in 45m33s
fix(actions): add nested app bundle ID verification and update process in macOS build workflow
2025-04-15 17:06:43 +02:00

345 lines
16 KiB
YAML

name: Test macOS Build Action
on:
workflow_dispatch: # Manual trigger only for testing
push:
branches: [ozgur/build]
jobs:
test-macos-build:
runs-on: macos
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
lfs: true
fetch-depth: 0
# Setup environment for build
- name: Setup environment
run: |
# Get the working directory path for absolute paths
WORKSPACE_DIR="$(pwd)"
echo "WORKSPACE_DIR=$WORKSPACE_DIR" >> "$GITHUB_ENV"
echo "ENTITLEMENTS_FILE=LuckyWorld.entitlements" >> "$GITHUB_ENV"
# Set CI environment variable to true for build script
echo "CI=true" >> "$GITHUB_ENV"
# Create directories for builds
mkdir -p Builds/Mac
mkdir -p PackagedReleases
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
- name: Build for macOS
run: |
if [ -f "./scripts/mac_build.sh" ]; then
chmod +x ./scripts/mac_build.sh
# Set CI environment variable explicitly before running
export CI=true
./scripts/mac_build.sh
# Check if the build succeeded by looking for the app
APP_PATHS=$(find ./Builds -type d -name "*.app" 2>/dev/null || echo "")
if [ -z "$APP_PATHS" ]; then
APP_PATHS=$(find ./Saved/StagedBuilds -type d -name "*.app" 2>/dev/null || echo "")
fi
if [ -z "$APP_PATHS" ]; then
echo "❌ ERROR: Build command appeared to succeed but no app bundle was found!"
echo "This usually means the build failed but didn't properly return an error code."
exit 1
fi
else
echo "ERROR: Build script not found at ./scripts/mac_build.sh"
exit 1
fi
shell: bash
# Find the app bundle
- name: Find app bundle
run: |
# Add error handling
set +e # Don't exit immediately on error for this block
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
# First check Saved/StagedBuilds directory - where Unreal often places built apps
echo "Checking Saved/StagedBuilds directory..."
APP_PATHS=$(find ./Saved/StagedBuilds -type d -name "*.app" 2>/dev/null || echo "")
# If not found, check Builds directory
if [ -z "$APP_PATHS" ]; then
echo "No app found in Saved/StagedBuilds, checking Builds directory..."
APP_PATHS=$(find ./Builds -type d -name "*.app" 2>/dev/null || echo "")
fi
# If still not found, check the whole workspace
if [ -z "$APP_PATHS" ]; then
echo "No app found in Builds, checking entire workspace..."
APP_PATHS=$(find . -type d -name "*.app" -not -path "*/\.*" 2>/dev/null || echo "")
fi
if [ -z "$APP_PATHS" ]; then
echo "❌ ERROR: Could not find any app bundles!"
echo "Listing all directories to help debug:"
find . -type d -maxdepth 3 | sort
exit 1
fi
echo "Found potential app bundles:"
echo "$APP_PATHS"
# Use the first app path found (preferably the main app, not a child app)
MAIN_APP_PATH=$(echo "$APP_PATHS" | grep -v "CrashReportClient" | head -1 || echo "$APP_PATHS" | head -1)
echo "Using app bundle: $MAIN_APP_PATH"
echo "APP_PATH=$MAIN_APP_PATH" >> "$GITHUB_ENV"
# Make sure app exists - using local variable
if [ ! -d "$MAIN_APP_PATH" ]; then
echo "❌ ERROR: App bundle not found at $MAIN_APP_PATH!"
exit 1
fi
# 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
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
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"
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
fi
shell: bash
# Use the macos-notarize action to sign and notarize the app
- name: Sign and Notarize macOS App
uses: ./.gitea/actions/macos-notarize
id: sign-and-notarize
with:
app-path: ${{ env.APP_PATH }}
entitlements-file: ${{ env.ENTITLEMENTS_FILE }}
team-id: ${{ secrets.APPLE_TEAM_ID }}
certificate-base64: ${{ secrets.MACOS_CERTIFICATE }}
certificate-password: ${{ secrets.MACOS_CERTIFICATE_PWD }}
notarization-method: 'api-key'
notary-api-key-id: ${{ secrets.NOTARY_API_KEY_ID }}
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: 'false'
# Upload signed app if available
- name: Upload Signed App
uses: actions/upload-artifact@v3
if: steps.sign-and-notarize.outputs.signed != 'none'
with:
name: ${{ steps.sign-and-notarize.outputs.notarized == 'true' && 'LuckyWorld-macOS-Signed-Notarized' || 'LuckyWorld-macOS-Signed' }}
path: ${{ steps.sign-and-notarize.outputs.package-path }}
retention-days: 30
# 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!"
shell: bash
# Upload ZIP package if DMG was created (as a backup)
- name: Upload ZIP Package
uses: actions/upload-artifact@v3
if: steps.sign-and-notarize.outputs.signed != 'none' && steps.sign-and-notarize.outputs.zip-package-path != ''
with:
name: ${{ steps.sign-and-notarize.outputs.notarized == 'true' && 'LuckyWorld-macOS-Signed-Notarized-ZIP' || 'LuckyWorld-macOS-Signed-ZIP' }}
path: ${{ steps.sign-and-notarize.outputs.zip-package-path }}
retention-days: 30
# Report results
- name: Report Results
run: |
echo "🔐 App signing: ${{ steps.sign-and-notarize.outputs.signed }}"
echo "🔏 App notarization: ${{ steps.sign-and-notarize.outputs.notarized }}"
if [ "${{ steps.sign-and-notarize.outputs.signed }}" != "none" ]; then
echo "✅ Packaging completed successfully!"
echo "Final package: ${{ steps.sign-and-notarize.outputs.package-path }}"
else
echo "⚠️ App was not signed - check the logs for details"
fi
shell: bash