From 80b9aafa69eebb45684518190200b8bca43e625f Mon Sep 17 00:00:00 2001 From: Ozgur Ersoy Date: Mon, 14 Apr 2025 00:28:06 +0200 Subject: [PATCH] fix(workflows): refine macOS build workflow with improved certificate handling and ad-hoc signing fallback --- .gitea/workflows/test-macos-build.yml | 263 ++++++++------------------ 1 file changed, 82 insertions(+), 181 deletions(-) diff --git a/.gitea/workflows/test-macos-build.yml b/.gitea/workflows/test-macos-build.yml index 2dda1929..8d2fa513 100644 --- a/.gitea/workflows/test-macos-build.yml +++ b/.gitea/workflows/test-macos-build.yml @@ -85,8 +85,8 @@ jobs: fi shell: bash - # Step 3: Create keychain and import certificate - SIMPLIFIED for debugging - - name: Create keychain and import certificate + # Step 3: Try both certificate & Ad-Hoc signing + - name: Prepare certificate or use Ad-Hoc signing env: CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE }} CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PWD }} @@ -94,215 +94,116 @@ jobs: run: | # Debug: Print working directory and available resources echo "Current working directory: $(pwd)" - echo "Contents of Builds directory:" - find Builds -type d | sort - echo "Contents of Saved/StagedBuilds directory (if exists):" - find ./Saved -type d -name "*.app" 2>/dev/null || echo "No .app bundles found in Saved/" - - # Decode certificate to working directory for simplicity - echo "Decoding certificate..." - echo "$CERTIFICATE_BASE64" | base64 --decode > certificate.p12 - ls -la certificate.p12 - - # Create a simple local keychain - echo "Creating login keychain..." - KEYCHAIN_PATH="$HOME/Library/Keychains/build.keychain-db" - KEYCHAIN_PASSWORD="temp$(date +%s)" - - security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - security default-keychain -s "$KEYCHAIN_PATH" - security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - - # Debug import step - echo "Importing certificate with flags: -P [PWD] -k $KEYCHAIN_PATH" - security import certificate.p12 -P "$CERTIFICATE_PASSWORD" -k "$KEYCHAIN_PATH" -T /usr/bin/codesign - - # Set partition list for automation - echo "Setting key partition list..." - security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - - # Check for identities - DEBUG - echo "Listing identities after import:" - security find-identity -v -p codesigning "$KEYCHAIN_PATH" - - # Verify Apple Team ID matches certificate - echo "Expected Apple Team ID: $APPLE_TEAM_ID" - - # Get a more detailed certificate info for debugging - echo "Certificate details:" - security find-certificate -a -c "Developer ID" -p "$KEYCHAIN_PATH" | openssl x509 -text | grep -E "Subject:|Issuer:|Not Before:|Not After :|Serial Number:" || echo "No certificate details found" - - # Use alternative approach to get signing identity - SIGNING_IDENTITY=$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" | grep "Developer ID Application" | sed -E 's/.*\"Developer ID Application: ([^\"]+).*/\1/g' || echo "") - if [ -z "$SIGNING_IDENTITY" ]; then - # Try with certificate CN directly - SIGNING_IDENTITY="Developer ID Application: $APPLE_TEAM_ID" - echo "Using APPLE_TEAM_ID directly: $SIGNING_IDENTITY" - else - echo "Found signing identity: $SIGNING_IDENTITY" - fi - - echo "KEYCHAIN_PATH=$KEYCHAIN_PATH" >> "$GITHUB_ENV" - echo "SIGNING_IDENTITY=$SIGNING_IDENTITY" >> "$GITHUB_ENV" - echo "KEYCHAIN_PASSWORD=$KEYCHAIN_PASSWORD" >> "$GITHUB_ENV" - - # Add to search list if needed - security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | sed s/\"//g) - shell: bash - - # Step 4: Find and prep app for signing - - name: Find and prep app for signing - run: | - # First check Saved/StagedBuilds directory - where Unreal often places built apps - echo "Checking Saved/StagedBuilds directory..." + # Find the app bundle to sign APP_PATHS=$(find ./Saved/StagedBuilds -type d -name "*.app" 2>/dev/null) - - # If not found, check Builds directory if [ -z "$APP_PATHS" ]; then - echo "Checking Builds directory..." APP_PATHS=$(find ./Builds -type d -name "*.app" 2>/dev/null) fi - - # If still not found, check the whole workspace if [ -z "$APP_PATHS" ]; then - echo "Checking entire workspace..." - 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 "ERROR: No .app bundle found to sign!" 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) - - # Get app name for later use APP_NAME=$(basename "$MAIN_APP_PATH") echo "Using app bundle: $MAIN_APP_PATH" - echo "App name: $APP_NAME" - echo "APP_PATH=$MAIN_APP_PATH" >> "$GITHUB_ENV" echo "APP_NAME=$APP_NAME" >> "$GITHUB_ENV" + + # Create a simple keychain + KEYCHAIN_PASSWORD="temp$(date +%s)" + KEYCHAIN_PATH="$HOME/Library/Keychains/build-temp.keychain-db" + + # First, try to use the provided certificate + echo "Attempting to use provided certificate..." + if [ -n "$CERTIFICATE_BASE64" ] && [ -n "$CERTIFICATE_PASSWORD" ]; then + echo "Certificate data provided, attempting import..." + + # Decode certificate and check format + echo "$CERTIFICATE_BASE64" | base64 --decode > temp-cert.p12 + echo "Certificate file info:" + file temp-cert.p12 + + # Create keychain + security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + security default-keychain -s "$KEYCHAIN_PATH" + security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + + # Import with debugging info + echo "Importing certificate into keychain..." + if security import temp-cert.p12 -k "$KEYCHAIN_PATH" -P "$CERTIFICATE_PASSWORD" -T /usr/bin/codesign; then + echo "Certificate imported successfully!" + + # Set partition list + security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + + # Check certificate details + echo "Certificate details:" + security find-identity -v -p codesigning "$KEYCHAIN_PATH" + + # If we have a valid identity, use it + if security find-identity -v -p codesigning "$KEYCHAIN_PATH" | grep -q "valid identities found"; then + IDENTITY=$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" | grep -o '"[^"]*"' | head -1 | sed 's/"//g') + echo "Using certificate identity: $IDENTITY" + echo "SIGNING_METHOD=certificate" >> "$GITHUB_ENV" + echo "SIGNING_IDENTITY=$IDENTITY" >> "$GITHUB_ENV" + else + echo "No valid identities found in keychain" + echo "SIGNING_METHOD=ad-hoc" >> "$GITHUB_ENV" + fi + else + echo "Failed to import certificate, will use ad-hoc signing instead" + echo "SIGNING_METHOD=ad-hoc" >> "$GITHUB_ENV" + fi + + # Cleanup certificate file + rm -f temp-cert.p12 + else + echo "Certificate data not provided, will use ad-hoc signing" + echo "SIGNING_METHOD=ad-hoc" >> "$GITHUB_ENV" + fi + + echo "KEYCHAIN_PATH=$KEYCHAIN_PATH" >> "$GITHUB_ENV" + echo "KEYCHAIN_PASSWORD=$KEYCHAIN_PASSWORD" >> "$GITHUB_ENV" shell: bash - # Step 5: Sign application with codesign - DIRECT METHOD + # Step 4: Sign application (with certificate or ad-hoc) - name: Sign application - env: - APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} run: | # Debug info echo "Signing app bundle: $APP_PATH" echo "Using entitlements file: $ENTITLEMENTS_FILE" - echo "Using signing identity: $SIGNING_IDENTITY" + echo "Signing method: $SIGNING_METHOD" - # Make sure keychain is accessible - echo "Unlocking keychains..." - security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" || true - - # Verify signing identity accessibility - echo "Verifying codesigning identities..." - security find-identity -v -p codesigning "$KEYCHAIN_PATH" - - # Sign the app directly, with a more direct approach - echo "🔍 Signing the app bundle with its contents..." - /usr/bin/codesign --force --options runtime --sign "$SIGNING_IDENTITY" --entitlements "$WORKSPACE_DIR/$ENTITLEMENTS_FILE" --deep --verbose "$APP_PATH" - - # Verify signature - echo "Verifying signature..." - /usr/bin/codesign --verify --verbose "$APP_PATH" - - # Check the result - if [ $? -eq 0 ]; then - echo "✅ Code signing was successful" - else - echo "⚠️ Code signing verification had issues, but continuing with notarization..." - fi - shell: bash - - # Step 6: Notarize application - - name: Notarize application - env: - API_KEY_PATH: ${{ secrets.NOTARY_API_KEY_PATH }} - API_KEY_ID: ${{ secrets.NOTARY_API_KEY_ID }} - API_KEY_ISSUER_ID: ${{ secrets.NOTARY_API_KEY_ISSUER_ID }} - run: | - echo "Preparing for notarization..." - - # Create API key file - echo "$API_KEY_PATH" | base64 --decode > api_key.p8 - API_KEY_FILE="$(pwd)/api_key.p8" - - # Create a zip archive for notarization - NOTARIZE_APP_PATH="LuckyWorld-notarize.zip" - echo "Creating archive for notarization: $NOTARIZE_APP_PATH" - - # Use ditto to preserve bundle structure - ditto -c -k --keepParent "$APP_PATH" "$NOTARIZE_APP_PATH" - - # Check if zip file was created successfully - if [ ! -f "$NOTARIZE_APP_PATH" ]; then - echo "❌ Failed to create notarization archive" - exit 1 - fi - - echo "Submitting for notarization..." - echo "API Key ID: $API_KEY_ID" - echo "API Key File: $API_KEY_FILE" - - # Submit for notarization using API key - NOTARIZE_OUTPUT=$(xcrun notarytool submit "$NOTARIZE_APP_PATH" --key "$API_KEY_FILE" --key-id "$API_KEY_ID" --issuer "$API_KEY_ISSUER_ID" --wait) - - echo "Notarization response:" - echo "$NOTARIZE_OUTPUT" - - # Check if notarization was successful - if [[ "$NOTARIZE_OUTPUT" =~ "status: Accepted" ]]; then - echo "✅ Notarization successful" - else - echo "⚠️ Notarization may have failed. Checking status..." + if [ "$SIGNING_METHOD" = "certificate" ]; then + # Certificate signing + echo "Using certificate signing with identity: $SIGNING_IDENTITY" - # Extract submission ID if available - SUBMISSION_ID=$(echo "$NOTARIZE_OUTPUT" | grep "id:" | awk '{print $2}') + # Unlock keychain + security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - if [ -n "$SUBMISSION_ID" ]; then - echo "Checking submission $SUBMISSION_ID..." - xcrun notarytool info "$SUBMISSION_ID" --key "$API_KEY_FILE" --key-id "$API_KEY_ID" --issuer "$API_KEY_ISSUER_ID" - - # Continue even if notarization failed - we'll staple if possible - echo "⚠️ Continuing despite potential notarization issues..." + # Sign the app + if /usr/bin/codesign --force --options runtime --sign "$SIGNING_IDENTITY" --entitlements "$WORKSPACE_DIR/$ENTITLEMENTS_FILE" --deep --verbose "$APP_PATH"; then + echo "✅ Code signing with certificate was successful" else - echo "⚠️ No submission ID found. Continuing anyway..." + echo "⚠️ Certificate signing failed, falling back to ad-hoc signing" + /usr/bin/codesign --force --options runtime --sign - --entitlements "$WORKSPACE_DIR/$ENTITLEMENTS_FILE" --deep --verbose "$APP_PATH" fi - fi - - # Staple the notarization ticket to the app - echo "Stapling notarization ticket to app..." - xcrun stapler staple "$APP_PATH" - - # Verify stapling - echo "Verifying stapling..." - stapler validate "$APP_PATH" - - if [ $? -eq 0 ]; then - echo "✅ Stapling successful" else - echo "⚠️ Stapling verification may have failed. This is sometimes expected for new apps." - echo "⚠️ Continuing with packaging..." + # Ad-hoc signing + echo "Using ad-hoc signing (for testing only)" + /usr/bin/codesign --force --options runtime --sign - --entitlements "$WORKSPACE_DIR/$ENTITLEMENTS_FILE" --deep --verbose "$APP_PATH" fi - # Clean up - rm -f "$NOTARIZE_APP_PATH" "$API_KEY_FILE" + # Verify signature (ignore errors) + echo "Verifying signature..." + /usr/bin/codesign --verify --verbose "$APP_PATH" || echo "Verification errors are expected with ad-hoc signing" shell: bash - # Step 7: Package macOS App + # Step 5: Package macOS App - name: Package macOS App run: | echo "Packaging signed app bundle: $APP_PATH" @@ -315,7 +216,7 @@ jobs: ls -la PackagedReleases/ shell: bash - # Step 8: Upload macOS Build Artifact + # Step 6: Upload macOS Build Artifact - name: Upload macOS Build Artifact uses: actions/upload-artifact@v3 if: success() @@ -324,7 +225,7 @@ jobs: path: PackagedReleases/LuckyWorld-macOS.zip retention-days: 365 - # Step 9: Cleanup + # Step 7: Cleanup - name: Cleanup if: always() run: | @@ -334,7 +235,7 @@ jobs: fi # Clean up certificate files - rm -f certificate.p12 api_key.p8 || true + rm -f certificate.p12 api_key.p8 temp-cert.p12 || true echo "Cleanup complete" shell: bash