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 mkdir -p ArchivedApps echo "Environment setup complete" shell: bash # Build for macOS - use your own build script - 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." 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" # Get bundle ID from Info.plist for reference (not modifying) 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: $BUNDLE_ID" echo "BUNDLE_ID=$BUNDLE_ID" >> "$GITHUB_ENV" fi shell: bash # Basic pre-notarization checks - name: Check for notarization issues run: | echo "πŸ” Checking app for potential notarization issues..." APP_PATH="${{ env.APP_PATH }}" # 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 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 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 # Make install scripts executable chmod +x ./scripts/install_luckyworld.sh chmod +x ./scripts/create_dmg.sh 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 only the DMG file from the macos-notarize action - name: Upload Standard DMG uses: actions/upload-artifact@v3 if: steps.sign-and-notarize.outputs.notarized == 'true' && steps.sign-and-notarize.outputs.signed != 'none' with: name: LuckyWorld-macOS-Signed-Notarized-DMG path: ${{ steps.sign-and-notarize.outputs.package-path }} retention-days: 30 # Install create-dmg tool - name: Install create-dmg tool run: | if ! command -v brew &> /dev/null; then echo "Homebrew is not installed. Installing now..." /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # Homebrew path'i environment'a ekle (Apple Silicon Mac iΓ§in) if [[ -d "/opt/homebrew/bin/" ]]; then echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile eval "$(/opt/homebrew/bin/brew shellenv)" fi # Intel Mac iΓ§in if [[ -d "/usr/local/bin/" ]]; then echo 'eval "$(/usr/local/bin/brew shellenv)"' >> ~/.zprofile eval "$(/usr/local/bin/brew shellenv)" fi echo "Homebrew installed successfully!" fi brew install create-dmg shell: bash # Set CI environment variables - name: Set CI Environment Variables run: | echo "Setting CI environment variables" echo "CI=true" >> $GITHUB_ENV echo "GITEA_ACTIONS=true" >> $GITHUB_ENV shell: bash # Create custom DMG with installer script - name: Create Custom DMG with Installer if: steps.sign-and-notarize.outputs.notarized == 'true' && steps.sign-and-notarize.outputs.signed != 'none' run: | echo "πŸ”§ Creating custom DMG with installer script..." # Ensure app is in the expected location after notarization APP_PATH="${{ env.APP_PATH }}" # Setup directories mkdir -p "./PackagedReleases/Install" rm -rf "./PackagedReleases/Install/*" 2>/dev/null || true # Copy the app and installer to package directory cp -R "$APP_PATH" "./PackagedReleases/Install/" cp "./scripts/install_luckyworld.sh" "./PackagedReleases/Install/" chmod +x "./PackagedReleases/Install/install_luckyworld.sh" # Create a simple README cat > "./PackagedReleases/Install/README.txt" << EOF LuckyWorld Installer =================== 1. Double-click 'install_luckyworld.sh' to install 2. Follow on-screen instructions For help: https://luckyrobots.io EOF # Create DMG using direct hdiutil approach (native macOS command) CUSTOM_DMG_PATH="./PackagedReleases/LuckyWorld-Installer.dmg" rm -f "$CUSTOM_DMG_PATH" 2>/dev/null || true hdiutil create -volname "LuckyWorld Installer" -srcfolder "./PackagedReleases/Install" -ov -format UDZO "$CUSTOM_DMG_PATH" if [ $? -ne 0 ]; then echo "❌ DMG creation failed! Creating a ZIP file as fallback..." ( cd "./PackagedReleases" && zip -r "LuckyWorld-Installer.zip" "Install" ) CUSTOM_DMG_PATH="./PackagedReleases/LuckyWorld-Installer.zip" fi if [ -f "$CUSTOM_DMG_PATH" ]; then echo "βœ… Package created successfully: $CUSTOM_DMG_PATH" echo "Size: $(du -h "$CUSTOM_DMG_PATH" | cut -f1)" echo "CUSTOM_DMG_PATH=$CUSTOM_DMG_PATH" >> $GITHUB_ENV else echo "❌ Failed to create installation package" exit 1 fi # Clean up temporary directory rm -rf "./PackagedReleases/Install" shell: bash # Upload the custom DMG with installer script - name: Upload Custom DMG with Installer uses: actions/upload-artifact@v3 if: steps.sign-and-notarize.outputs.notarized == 'true' && steps.sign-and-notarize.outputs.signed != 'none' && env.CUSTOM_DMG_PATH != '' with: name: LuckyWorld-macOS-Installer-DMG path: ${{ env.CUSTOM_DMG_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 standard package: ${{ steps.sign-and-notarize.outputs.package-path }}" if [ -n "$CUSTOM_DMG_PATH" ] && [ -f "$CUSTOM_DMG_PATH" ]; then echo "Final installer package: $CUSTOM_DMG_PATH" fi else echo "⚠️ App was not signed - check the logs for details" fi shell: bash