fix(actions): enhance notarization script with improved submission handling and detailed logging
Some checks failed
Test macOS Build Action / test-macos-build (push) Has been cancelled
Some checks failed
Test macOS Build Action / test-macos-build (push) Has been cancelled
This commit is contained in:
parent
67a9934251
commit
84a8a0876b
@ -244,48 +244,91 @@ runs:
|
|||||||
ditto -c -k --keepParent "${{ inputs.app-path }}" "$ZIP_PATH"
|
ditto -c -k --keepParent "${{ inputs.app-path }}" "$ZIP_PATH"
|
||||||
|
|
||||||
echo "Submitting for notarization with API key..."
|
echo "Submitting for notarization with API key..."
|
||||||
# Capture output and exit status of notarization
|
|
||||||
NOTARY_OUTPUT=$(xcrun notarytool submit "$ZIP_PATH" \
|
# First, submit without waiting for completion
|
||||||
|
SUBMIT_OUTPUT=$(xcrun notarytool submit "$ZIP_PATH" \
|
||||||
--key ~/private_keys/AuthKey_${API_KEY_ID}.p8 \
|
--key ~/private_keys/AuthKey_${API_KEY_ID}.p8 \
|
||||||
--key-id "$API_KEY_ID" \
|
--key-id "$API_KEY_ID" \
|
||||||
--issuer "$API_ISSUER_ID" \
|
--issuer "$API_ISSUER_ID" 2>&1)
|
||||||
--wait 2>&1)
|
SUBMIT_STATUS=$?
|
||||||
NOTARY_STATUS=$?
|
|
||||||
|
|
||||||
# Display output for debugging
|
# Display output for debugging
|
||||||
echo "Notarization command output:"
|
echo "Notarization submission output:"
|
||||||
echo "$NOTARY_OUTPUT"
|
echo "$SUBMIT_OUTPUT"
|
||||||
echo "Notarization exit status: $NOTARY_STATUS"
|
echo "Submission exit status: $SUBMIT_STATUS"
|
||||||
|
|
||||||
# Extract submission ID for log retrieval if needed
|
# Check if submission was successful
|
||||||
SUBMISSION_ID=$(echo "$NOTARY_OUTPUT" | grep -o "id: [a-f0-9\-]*" | head -1 | cut -d ' ' -f 2)
|
if [ $SUBMIT_STATUS -ne 0 ]; then
|
||||||
echo "Submission ID: $SUBMISSION_ID"
|
echo "❌ Failed to submit for notarization. Exit code: $SUBMIT_STATUS"
|
||||||
|
exit 1
|
||||||
# Check for invalid status and get detailed logs
|
|
||||||
if [ $NOTARY_STATUS -eq 0 ] && echo "$NOTARY_OUTPUT" | grep -q "Invalid"; then
|
|
||||||
echo "⚠️ Notarization returned Invalid status. Checking detailed logs..."
|
|
||||||
if [ -n "$SUBMISSION_ID" ]; then
|
|
||||||
echo "📋 Fetching detailed logs for submission ID: $SUBMISSION_ID"
|
|
||||||
LOGS_OUTPUT=$(xcrun notarytool log "$SUBMISSION_ID" \
|
|
||||||
--key ~/private_keys/AuthKey_${API_KEY_ID}.p8 \
|
|
||||||
--key-id "$API_KEY_ID" \
|
|
||||||
--issuer "$API_ISSUER_ID" 2>&1)
|
|
||||||
|
|
||||||
echo "==== DETAILED NOTARIZATION LOGS ===="
|
|
||||||
echo "$LOGS_OUTPUT"
|
|
||||||
echo "=================================="
|
|
||||||
|
|
||||||
# Extract specific issues for easier debugging
|
|
||||||
echo "🔍 Extracting specific issues from logs..."
|
|
||||||
echo "$LOGS_OUTPUT" | grep -A 3 "issues"
|
|
||||||
else
|
|
||||||
echo "❌ Could not extract submission ID from notarization output"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Enhanced check for notarization success
|
# Extract submission ID for log retrieval
|
||||||
if [ $NOTARY_STATUS -eq 0 ] && echo "$NOTARY_OUTPUT" | grep -q -E "success|accepted"; then
|
SUBMISSION_ID=$(echo "$SUBMIT_OUTPUT" | grep -o "id: [a-f0-9\-]*" | head -1 | cut -d ' ' -f 2)
|
||||||
echo "✅ Notarization completed successfully!"
|
|
||||||
|
if [ -z "$SUBMISSION_ID" ]; then
|
||||||
|
echo "❌ Could not extract submission ID from output. Notarization failed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Submission ID: $SUBMISSION_ID"
|
||||||
|
echo "Waiting for notarization to complete..."
|
||||||
|
|
||||||
|
# Now wait for the processing to complete
|
||||||
|
COMPLETE=false
|
||||||
|
MAX_ATTEMPTS=60 # Maximum number of attempts (60 * 30 seconds = 30 minutes max)
|
||||||
|
ATTEMPT=1
|
||||||
|
|
||||||
|
while [ "$COMPLETE" = "false" ] && [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
|
||||||
|
echo "Checking notarization status (attempt $ATTEMPT of $MAX_ATTEMPTS)..."
|
||||||
|
|
||||||
|
INFO_OUTPUT=$(xcrun notarytool info "$SUBMISSION_ID" \
|
||||||
|
--key ~/private_keys/AuthKey_${API_KEY_ID}.p8 \
|
||||||
|
--key-id "$API_KEY_ID" \
|
||||||
|
--issuer "$API_ISSUER_ID" 2>&1)
|
||||||
|
INFO_STATUS=$?
|
||||||
|
|
||||||
|
echo "Status check output:"
|
||||||
|
echo "$INFO_OUTPUT"
|
||||||
|
|
||||||
|
# Check if the notarization is complete
|
||||||
|
if echo "$INFO_OUTPUT" | grep -q "status: Accepted"; then
|
||||||
|
echo "✅ Notarization completed successfully!"
|
||||||
|
COMPLETE=true
|
||||||
|
FINAL_STATUS="Accepted"
|
||||||
|
elif echo "$INFO_OUTPUT" | grep -q "status: Invalid"; then
|
||||||
|
echo "❌ Notarization failed with status: Invalid"
|
||||||
|
COMPLETE=true
|
||||||
|
FINAL_STATUS="Invalid"
|
||||||
|
elif echo "$INFO_OUTPUT" | grep -q "status: Rejected"; then
|
||||||
|
echo "❌ Notarization failed with status: Rejected"
|
||||||
|
COMPLETE=true
|
||||||
|
FINAL_STATUS="Rejected"
|
||||||
|
else
|
||||||
|
echo "Notarization still in progress. Waiting 30 seconds before checking again..."
|
||||||
|
sleep 30
|
||||||
|
ATTEMPT=$((ATTEMPT + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Handle timeout
|
||||||
|
if [ "$COMPLETE" = "false" ]; then
|
||||||
|
echo "❌ Notarization timed out after $MAX_ATTEMPTS attempts."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle completed notarization
|
||||||
|
if [ "$FINAL_STATUS" = "Accepted" ]; then
|
||||||
|
# Get logs for information (even though successful)
|
||||||
|
echo "📋 Getting notarization logs for information..."
|
||||||
|
LOGS_OUTPUT=$(xcrun notarytool log "$SUBMISSION_ID" \
|
||||||
|
--key ~/private_keys/AuthKey_${API_KEY_ID}.p8 \
|
||||||
|
--key-id "$API_KEY_ID" \
|
||||||
|
--issuer "$API_ISSUER_ID" 2>&1)
|
||||||
|
|
||||||
|
echo "==== NOTARIZATION LOG SUMMARY ===="
|
||||||
|
echo "$LOGS_OUTPUT" | head -20
|
||||||
|
echo "=================================="
|
||||||
|
|
||||||
# Staple the notarization ticket
|
# Staple the notarization ticket
|
||||||
echo "Stapling notarization ticket..."
|
echo "Stapling notarization ticket..."
|
||||||
@ -304,8 +347,20 @@ runs:
|
|||||||
|
|
||||||
echo "::set-output name=notarized::true"
|
echo "::set-output name=notarized::true"
|
||||||
else
|
else
|
||||||
echo "❌ Notarization failed or did not complete properly"
|
# Get detailed logs for failed notarization
|
||||||
echo "Please check the notarization logs above for details"
|
echo "📋 Fetching detailed logs for submission ID: $SUBMISSION_ID"
|
||||||
|
LOGS_OUTPUT=$(xcrun notarytool log "$SUBMISSION_ID" \
|
||||||
|
--key ~/private_keys/AuthKey_${API_KEY_ID}.p8 \
|
||||||
|
--key-id "$API_KEY_ID" \
|
||||||
|
--issuer "$API_ISSUER_ID" 2>&1)
|
||||||
|
|
||||||
|
echo "==== DETAILED NOTARIZATION LOGS ===="
|
||||||
|
echo "$LOGS_OUTPUT"
|
||||||
|
echo "=================================="
|
||||||
|
|
||||||
|
# Extract specific issues for easier debugging
|
||||||
|
echo "🔍 Extracting specific issues from logs..."
|
||||||
|
echo "$LOGS_OUTPUT" | grep -A 3 "issues"
|
||||||
|
|
||||||
# Show current bundle ID in Info.plist
|
# Show current bundle ID in Info.plist
|
||||||
echo "📋 Current bundle ID information:"
|
echo "📋 Current bundle ID information:"
|
||||||
@ -332,6 +387,9 @@ runs:
|
|||||||
echo "Checking signature on: $lib"
|
echo "Checking signature on: $lib"
|
||||||
codesign -vvv "$lib" || echo "⚠️ Signature issue with: $lib"
|
codesign -vvv "$lib" || echo "⚠️ Signature issue with: $lib"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
echo "❌ Notarization failed with status: $FINAL_STATUS"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
@ -346,48 +404,91 @@ runs:
|
|||||||
ditto -c -k --keepParent "${{ inputs.app-path }}" "$ZIP_PATH"
|
ditto -c -k --keepParent "${{ inputs.app-path }}" "$ZIP_PATH"
|
||||||
|
|
||||||
echo "Submitting for notarization..."
|
echo "Submitting for notarization..."
|
||||||
# Capture output and exit status of notarization
|
|
||||||
NOTARY_OUTPUT=$(xcrun notarytool submit "$ZIP_PATH" \
|
# First, submit without waiting for completion
|
||||||
|
SUBMIT_OUTPUT=$(xcrun notarytool submit "$ZIP_PATH" \
|
||||||
--apple-id "$APPLE_ID" \
|
--apple-id "$APPLE_ID" \
|
||||||
--password "$APP_PASSWORD" \
|
--password "$APP_PASSWORD" \
|
||||||
--team-id "$APPLE_TEAM_ID" \
|
--team-id "$APPLE_TEAM_ID" 2>&1)
|
||||||
--wait 2>&1)
|
SUBMIT_STATUS=$?
|
||||||
NOTARY_STATUS=$?
|
|
||||||
|
|
||||||
# Display output for debugging
|
# Display output for debugging
|
||||||
echo "Notarization command output:"
|
echo "Notarization submission output:"
|
||||||
echo "$NOTARY_OUTPUT"
|
echo "$SUBMIT_OUTPUT"
|
||||||
echo "Notarization exit status: $NOTARY_STATUS"
|
echo "Submission exit status: $SUBMIT_STATUS"
|
||||||
|
|
||||||
# Extract submission ID for log retrieval if needed
|
# Check if submission was successful
|
||||||
SUBMISSION_ID=$(echo "$NOTARY_OUTPUT" | grep -o "id: [a-f0-9\-]*" | head -1 | cut -d ' ' -f 2)
|
if [ $SUBMIT_STATUS -ne 0 ]; then
|
||||||
echo "Submission ID: $SUBMISSION_ID"
|
echo "❌ Failed to submit for notarization. Exit code: $SUBMIT_STATUS"
|
||||||
|
exit 1
|
||||||
# Check for invalid status and get detailed logs
|
|
||||||
if [ $NOTARY_STATUS -eq 0 ] && echo "$NOTARY_OUTPUT" | grep -q "Invalid"; then
|
|
||||||
echo "⚠️ Notarization returned Invalid status. Checking detailed logs..."
|
|
||||||
if [ -n "$SUBMISSION_ID" ]; then
|
|
||||||
echo "📋 Fetching detailed logs for submission ID: $SUBMISSION_ID"
|
|
||||||
LOGS_OUTPUT=$(xcrun notarytool log "$SUBMISSION_ID" \
|
|
||||||
--apple-id "$APPLE_ID" \
|
|
||||||
--password "$APP_PASSWORD" \
|
|
||||||
--team-id "$APPLE_TEAM_ID" 2>&1)
|
|
||||||
|
|
||||||
echo "==== DETAILED NOTARIZATION LOGS ===="
|
|
||||||
echo "$LOGS_OUTPUT"
|
|
||||||
echo "=================================="
|
|
||||||
|
|
||||||
# Extract specific issues for easier debugging
|
|
||||||
echo "🔍 Extracting specific issues from logs..."
|
|
||||||
echo "$LOGS_OUTPUT" | grep -A 3 "issues"
|
|
||||||
else
|
|
||||||
echo "❌ Could not extract submission ID from notarization output"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Enhanced check for notarization success
|
# Extract submission ID for log retrieval
|
||||||
if [ $NOTARY_STATUS -eq 0 ] && echo "$NOTARY_OUTPUT" | grep -q -E "success|accepted"; then
|
SUBMISSION_ID=$(echo "$SUBMIT_OUTPUT" | grep -o "id: [a-f0-9\-]*" | head -1 | cut -d ' ' -f 2)
|
||||||
echo "✅ Notarization completed successfully!"
|
|
||||||
|
if [ -z "$SUBMISSION_ID" ]; then
|
||||||
|
echo "❌ Could not extract submission ID from output. Notarization failed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Submission ID: $SUBMISSION_ID"
|
||||||
|
echo "Waiting for notarization to complete..."
|
||||||
|
|
||||||
|
# Now wait for the processing to complete
|
||||||
|
COMPLETE=false
|
||||||
|
MAX_ATTEMPTS=60 # Maximum number of attempts (60 * 30 seconds = 30 minutes max)
|
||||||
|
ATTEMPT=1
|
||||||
|
|
||||||
|
while [ "$COMPLETE" = "false" ] && [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
|
||||||
|
echo "Checking notarization status (attempt $ATTEMPT of $MAX_ATTEMPTS)..."
|
||||||
|
|
||||||
|
INFO_OUTPUT=$(xcrun notarytool info "$SUBMISSION_ID" \
|
||||||
|
--apple-id "$APPLE_ID" \
|
||||||
|
--password "$APP_PASSWORD" \
|
||||||
|
--team-id "$APPLE_TEAM_ID" 2>&1)
|
||||||
|
INFO_STATUS=$?
|
||||||
|
|
||||||
|
echo "Status check output:"
|
||||||
|
echo "$INFO_OUTPUT"
|
||||||
|
|
||||||
|
# Check if the notarization is complete
|
||||||
|
if echo "$INFO_OUTPUT" | grep -q "status: Accepted"; then
|
||||||
|
echo "✅ Notarization completed successfully!"
|
||||||
|
COMPLETE=true
|
||||||
|
FINAL_STATUS="Accepted"
|
||||||
|
elif echo "$INFO_OUTPUT" | grep -q "status: Invalid"; then
|
||||||
|
echo "❌ Notarization failed with status: Invalid"
|
||||||
|
COMPLETE=true
|
||||||
|
FINAL_STATUS="Invalid"
|
||||||
|
elif echo "$INFO_OUTPUT" | grep -q "status: Rejected"; then
|
||||||
|
echo "❌ Notarization failed with status: Rejected"
|
||||||
|
COMPLETE=true
|
||||||
|
FINAL_STATUS="Rejected"
|
||||||
|
else
|
||||||
|
echo "Notarization still in progress. Waiting 30 seconds before checking again..."
|
||||||
|
sleep 30
|
||||||
|
ATTEMPT=$((ATTEMPT + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Handle timeout
|
||||||
|
if [ "$COMPLETE" = "false" ]; then
|
||||||
|
echo "❌ Notarization timed out after $MAX_ATTEMPTS attempts."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle completed notarization
|
||||||
|
if [ "$FINAL_STATUS" = "Accepted" ]; then
|
||||||
|
# Get logs for information (even though successful)
|
||||||
|
echo "📋 Getting notarization logs for information..."
|
||||||
|
LOGS_OUTPUT=$(xcrun notarytool log "$SUBMISSION_ID" \
|
||||||
|
--apple-id "$APPLE_ID" \
|
||||||
|
--password "$APP_PASSWORD" \
|
||||||
|
--team-id "$APPLE_TEAM_ID" 2>&1)
|
||||||
|
|
||||||
|
echo "==== NOTARIZATION LOG SUMMARY ===="
|
||||||
|
echo "$LOGS_OUTPUT" | head -20
|
||||||
|
echo "=================================="
|
||||||
|
|
||||||
# Staple the notarization ticket
|
# Staple the notarization ticket
|
||||||
echo "Stapling notarization ticket..."
|
echo "Stapling notarization ticket..."
|
||||||
@ -406,8 +507,20 @@ runs:
|
|||||||
|
|
||||||
echo "::set-output name=notarized::true"
|
echo "::set-output name=notarized::true"
|
||||||
else
|
else
|
||||||
echo "❌ Notarization failed or did not complete properly"
|
# Get detailed logs for failed notarization
|
||||||
echo "Please check the notarization logs above for details"
|
echo "📋 Fetching detailed logs for submission ID: $SUBMISSION_ID"
|
||||||
|
LOGS_OUTPUT=$(xcrun notarytool log "$SUBMISSION_ID" \
|
||||||
|
--apple-id "$APPLE_ID" \
|
||||||
|
--password "$APP_PASSWORD" \
|
||||||
|
--team-id "$APPLE_TEAM_ID" 2>&1)
|
||||||
|
|
||||||
|
echo "==== DETAILED NOTARIZATION LOGS ===="
|
||||||
|
echo "$LOGS_OUTPUT"
|
||||||
|
echo "=================================="
|
||||||
|
|
||||||
|
# Extract specific issues for easier debugging
|
||||||
|
echo "🔍 Extracting specific issues from logs..."
|
||||||
|
echo "$LOGS_OUTPUT" | grep -A 3 "issues"
|
||||||
|
|
||||||
# Show current bundle ID in Info.plist
|
# Show current bundle ID in Info.plist
|
||||||
echo "📋 Current bundle ID information:"
|
echo "📋 Current bundle ID information:"
|
||||||
@ -419,6 +532,9 @@ runs:
|
|||||||
else
|
else
|
||||||
echo "Info.plist not found at expected location: ${{ inputs.app-path }}/Contents/Info.plist"
|
echo "Info.plist not found at expected location: ${{ inputs.app-path }}/Contents/Info.plist"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "❌ Notarization failed with status: $FINAL_STATUS"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "⚠️ Missing notarization credentials. Skipping notarization."
|
echo "⚠️ Missing notarization credentials. Skipping notarization."
|
||||||
|
@ -96,3 +96,63 @@ if [ -n "$APP_PATH" ]; then
|
|||||||
echo "🔍 Checking for PhysX and other special libraries (often need special handling):"
|
echo "🔍 Checking for PhysX and other special libraries (often need special handling):"
|
||||||
find "$APP_PATH" -name "*PhysX*" -o -name "*APEX*"
|
find "$APP_PATH" -name "*PhysX*" -o -name "*APEX*"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Bundle ID'yi proje ayarlarında güncelle
|
||||||
|
echo ""
|
||||||
|
echo "🔧 Updating bundle ID in UE config..."
|
||||||
|
CONFIG_FILE="$PROJECT_ROOT/Config/DefaultGame.ini"
|
||||||
|
if [ -f "$CONFIG_FILE" ]; then
|
||||||
|
# Mevcut bölümü kontrol et veya ekle
|
||||||
|
if grep -q "\[/Script/MacTargetPlatform\.MacTargetSettings\]" "$CONFIG_FILE"; then
|
||||||
|
# Bölüm var, ayarı güncelleyebiliriz
|
||||||
|
sed -i '' 's/BundleIdentifier=.*/BundleIdentifier=com.luckyrobots.luckyworld/g' "$CONFIG_FILE"
|
||||||
|
else
|
||||||
|
# Bölüm yok, eklememiz gerekiyor
|
||||||
|
echo "" >> "$CONFIG_FILE"
|
||||||
|
echo "[/Script/MacTargetPlatform.MacTargetSettings]" >> "$CONFIG_FILE"
|
||||||
|
echo "BundleIdentifier=com.luckyrobots.luckyworld" >> "$CONFIG_FILE"
|
||||||
|
fi
|
||||||
|
echo "Updated bundle ID in project config"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build sonrası işlemler - bundle ID ayarlama
|
||||||
|
echo ""
|
||||||
|
echo "🔧 Performing post-build fix for bundle ID..."
|
||||||
|
if [ -n "$APP_PATH" ]; then
|
||||||
|
INFO_PLIST="$APP_PATH/Contents/Info.plist"
|
||||||
|
if [ -f "$INFO_PLIST" ]; then
|
||||||
|
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 "⚠️ Info.plist not found at $INFO_PLIST"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Kütüphaneleri kontrol et ve gerekirse post-processing yap
|
||||||
|
echo ""
|
||||||
|
echo "🔍 Checking for unsigned libraries..."
|
||||||
|
if [ -n "$APP_PATH" ]; then
|
||||||
|
# Uygulamanın tüm executable ve kütüphanelerini bul
|
||||||
|
find "$APP_PATH" -type f -perm +111 | while read -r binary; do
|
||||||
|
# Codesign durumunu kontrol et
|
||||||
|
if ! codesign -v "$binary" &>/dev/null; then
|
||||||
|
echo "⚠️ Unsigned binary found: $binary"
|
||||||
|
# Bu dosyayı imzalamak için entitlements kullan
|
||||||
|
if [ -n "$ENTITLEMENTS_FILE" ]; then
|
||||||
|
echo "Re-signing binary with ad-hoc signature..."
|
||||||
|
codesign --force --options runtime --deep --sign - --timestamp --entitlements "$ENTITLEMENTS_FILE" "$binary"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Hardened Runtime için ek kontroller
|
||||||
|
echo "Ensuring Hardened Runtime flags are set for main executable..."
|
||||||
|
MAIN_EXECUTABLE="$APP_PATH/Contents/MacOS/$(basename "$APP_PATH" .app)"
|
||||||
|
if [ -f "$MAIN_EXECUTABLE" ]; then
|
||||||
|
codesign --force --options runtime --deep --sign - --timestamp --entitlements "$ENTITLEMENTS_FILE" "$MAIN_EXECUTABLE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ Build and post-processing completed successfully!"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user