367 lines
16 KiB
YAML
367 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
|
|
|
|
# Cache Unreal Engine build artifacts to speed up builds
|
|
- name: Cache UE build artifacts
|
|
uses: actions/cache@v3
|
|
with:
|
|
path: |
|
|
./Intermediate
|
|
./DerivedDataCache
|
|
./Saved/StagedBuilds
|
|
key: ${{ runner.os }}-ue-build-${{ hashFiles('LuckyWorld.uproject') }}-${{ hashFiles('Config/**/*.ini') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-ue-build-${{ hashFiles('LuckyWorld.uproject') }}-
|
|
${{ runner.os }}-ue-build-
|
|
|
|
# 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
|
|
|
|
# Verify Build.cs and Target.cs files
|
|
BUILD_CS="Source/LuckyWorld/LuckyWorld.Build.cs"
|
|
TARGET_CS="Source/LuckyWorld.Target.cs"
|
|
|
|
if [ -f "$BUILD_CS" ]; then
|
|
if grep -q "APP_BUNDLE_IDENTIFIER=com.luckyrobots.luckyworld" "$BUILD_CS"; then
|
|
echo "✅ Bundle ID correctly set in LuckyWorld.Build.cs"
|
|
else
|
|
echo "⚠️ Warning: Bundle ID may not be correctly set in LuckyWorld.Build.cs"
|
|
fi
|
|
else
|
|
echo "⚠️ LuckyWorld.Build.cs not found!"
|
|
fi
|
|
|
|
if [ -f "$TARGET_CS" ]; then
|
|
if grep -q "APP_BUNDLE_IDENTIFIER=com.luckyrobots.luckyworld" "$TARGET_CS"; then
|
|
echo "✅ Bundle ID correctly set in LuckyWorld.Target.cs"
|
|
else
|
|
echo "⚠️ Warning: Bundle ID may not be correctly set in LuckyWorld.Target.cs"
|
|
fi
|
|
else
|
|
echo "⚠️ LuckyWorld.Target.cs 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
|
|
id: build-app
|
|
continue-on-error: true # Continue even if build fails, to collect debug info
|
|
run: |
|
|
if [ -f "./scripts/mac_build.sh" ]; then
|
|
echo "🔨 Running mac_build.sh and capturing output to build_log.txt..."
|
|
chmod +x ./scripts/mac_build.sh
|
|
# Set CI environment variable explicitly before running
|
|
export CI=true
|
|
# Run build script and capture all output to a log file
|
|
./scripts/mac_build.sh 2>&1 | tee build_log.txt
|
|
|
|
# Check if build succeeded based on exit code
|
|
if [ ${PIPESTATUS[0]} -ne 0 ]; then
|
|
echo "❌ Build script failed with exit code ${PIPESTATUS[0]}"
|
|
echo "See build_log.txt for details"
|
|
# Set output to indicate failure
|
|
echo "::set-output name=build_success::false"
|
|
else
|
|
echo "✅ Build script completed successfully"
|
|
echo "::set-output name=build_success::true"
|
|
fi
|
|
else
|
|
echo "❌ ERROR: Build script not found at ./scripts/mac_build.sh"
|
|
echo "::set-output name=build_success::false"
|
|
exit 1
|
|
fi
|
|
shell: bash
|
|
|
|
# Upload build logs regardless of success
|
|
- name: Upload Build Logs
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: build-logs
|
|
path: |
|
|
build_log.txt
|
|
./Saved/Logs/*.log
|
|
retention-days: 7
|
|
if-no-files-found: warn
|
|
|
|
# Find the app bundle - this may fail if build failed
|
|
- name: Find app bundle
|
|
id: find-app
|
|
continue-on-error: ${{ steps.build-app.outputs.build_success != 'true' }} # Only stop if build succeeded but app not found
|
|
run: |
|
|
# Debug: Show directory structure to help diagnose issues
|
|
echo "📂 Current directory structure:"
|
|
ls -la ./
|
|
|
|
# Debug: Show if the build directory exists
|
|
echo "📂 Checking if Builds directory exists:"
|
|
ls -la ./ | grep Builds || echo "Builds directory not found!"
|
|
|
|
# Debug: Show if Saved directory exists
|
|
echo "📂 Checking if Saved directory exists:"
|
|
ls -la ./ | grep Saved || echo "Saved directory not found!"
|
|
|
|
# First check Saved/StagedBuilds directory - where Unreal often places built apps
|
|
echo "📂 Checking Saved/StagedBuilds directory..."
|
|
if [ -d "./Saved/StagedBuilds" ]; then
|
|
echo "Saved/StagedBuilds exists, checking content:"
|
|
ls -la ./Saved/StagedBuilds
|
|
APP_PATHS=$(find ./Saved/StagedBuilds -type d -name "*.app" 2>/dev/null)
|
|
else
|
|
echo "⚠️ Saved/StagedBuilds directory doesn't exist!"
|
|
APP_PATHS=""
|
|
fi
|
|
|
|
# If not found, check Saved directory
|
|
if [ -z "$APP_PATHS" ]; then
|
|
echo "📂 Checking Saved directory..."
|
|
if [ -d "./Saved" ]; then
|
|
echo "Saved exists, looking for app bundles:"
|
|
ls -la ./Saved
|
|
APP_PATHS=$(find ./Saved -type d -name "*.app" 2>/dev/null)
|
|
else
|
|
echo "⚠️ Saved directory doesn't exist!"
|
|
fi
|
|
fi
|
|
|
|
# If not found, check Builds directory
|
|
if [ -z "$APP_PATHS" ]; then
|
|
echo "📂 Checking Builds directory..."
|
|
if [ -d "./Builds" ]; then
|
|
echo "Builds exists, looking for app bundles:"
|
|
ls -la ./Builds
|
|
ls -la ./Builds/Mac 2>/dev/null || echo "No Builds/Mac directory found"
|
|
APP_PATHS=$(find ./Builds -type d -name "*.app" 2>/dev/null)
|
|
else
|
|
echo "⚠️ Builds directory doesn't exist!"
|
|
fi
|
|
fi
|
|
|
|
# If still not found, check the whole workspace
|
|
if [ -z "$APP_PATHS" ]; then
|
|
echo "📂 Checking entire workspace for .app bundles..."
|
|
APP_PATHS=$(find . -type d -name "*.app" -not -path "*/\.*" 2>/dev/null)
|
|
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
|
|
|
|
echo "Build process likely failed. Checking mac_build.sh log:"
|
|
cat build_log.txt 2>/dev/null || echo "No build log found"
|
|
|
|
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"
|
|
|
|
# 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
|
|
|
|
# Set the application name to "LuckyWorld" instead of "LuckyWorld-Mac-Shipping"
|
|
echo "Setting application display name to LuckyWorld..."
|
|
/usr/libexec/PlistBuddy -c "Set :CFBundleName LuckyWorld" "$MAIN_APP_PATH/Contents/Info.plist"
|
|
echo "Updated app name: $(/usr/libexec/PlistBuddy -c "Print :CFBundleName" "$MAIN_APP_PATH/Contents/Info.plist")"
|
|
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)
|
|
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"
|
|
|
|
# Verify the change
|
|
UPDATED_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$NESTED_APP/Contents/Info.plist")
|
|
echo "Updated nested app bundle ID: $UPDATED_ID"
|
|
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
|
|
|
|
# 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
|
|
|
|
# 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
|
|
|