#!/bin/zsh set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$ROOT" command -v xcodebuild >/dev/null || { echo "Xcode is required" >&2; exit 1; } command -v hdiutil >/dev/null || { echo "hdiutil missing" >&2; exit 1; } IDENTITY="${SIGNING_IDENTITY:-$(security find-identity -v -p codesigning | sed -nE 's/.*"(Developer ID Application: [^"]+)".*/\1/p' | head -1)}" [[ -n "$IDENTITY" ]] || { echo "Developer ID Application signing identity required. Set SIGNING_IDENTITY." >&2; exit 1; } PROFILE="${NOTARY_PROFILE:-}" [[ -n "$PROFILE" ]] || { echo "Set NOTARY_PROFILE to an existing notarytool keychain profile." >&2; exit 1; } DERIVED="$ROOT/.build" xcodebuild -project "$ROOT/PHPGuard.xcodeproj" -scheme PHPGuard -configuration Release -derivedDataPath "$DERIVED" CODE_SIGNING_ALLOWED=NO build APP="$DERIVED/Build/Products/Release/PHPGuard.app" [[ -d "$APP" ]] || { echo "Missing Release app" >&2; exit 1; } echo "=== VERIFY APPLICATION ICON ===" APP_ICON_NAME=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIconFile" "$APP/Contents/Info.plist" 2>/dev/null || true) if [[ -z "$APP_ICON_NAME" ]]; then echo "ERROR: Application icon is missing from Info.plist" >&2 exit 1 fi echo "Application icon: $APP_ICON_NAME" if [[ ! -f "$APP/Contents/Resources/Assets.car" ]]; then echo "ERROR: Compiled asset catalog missing" >&2 exit 1 fi VERSION="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$APP/Contents/Info.plist")" mkdir -p "$ROOT/dist" STAGING="$(mktemp -d)" trap 'rm -rf "$STAGING"' EXIT cp -R "$APP" "$STAGING/PHPGuard.app" # No --deep signing: sign embedded executables individually if added in future. codesign --force --options runtime --timestamp --sign "$IDENTITY" "$STAGING/PHPGuard.app" codesign --verify --strict --verbose=2 "$STAGING/PHPGuard.app" DMG="$ROOT/dist/PHPGuard-$VERSION.dmg" rm -f "$DMG" ln -s /Applications "$STAGING/Applications" # Include a branded installer graphic in the disk image. INSTALLER_ICON="$ROOT/PHPGuard/Assets.xcassets/InstallerIcon.imageset/icon.png" if [[ -f "$INSTALLER_ICON" ]]; then mkdir -p "$STAGING/.background" cp "$INSTALLER_ICON" "$STAGING/.background/PHPGuard-Installer.png" fi # Generate a proper macOS installer icon. INSTALLER_PNG="$ROOT/PHPGuard/Assets.xcassets/InstallerIcon.imageset/icon.png" ICONSET="$ROOT/dist/PHPGuardInstaller.iconset" INSTALLER_ICNS="$ROOT/dist/PHPGuardInstaller.icns" if [[ -f "$INSTALLER_PNG" ]]; then rm -rf "$ICONSET" mkdir -p "$ICONSET" for size in 16 32 128 256 512; do sips -s format png -z "$size" "$size" "$INSTALLER_PNG" --out "$ICONSET/icon_${size}x${size}.png" >/dev/null double=$((size * 2)) sips -s format png -z "$double" "$double" "$INSTALLER_PNG" --out "$ICONSET/icon_${size}x${size}@2x.png" >/dev/null done iconutil -c icns "$ICONSET" -o "$INSTALLER_ICNS" rm -rf "$ICONSET" else echo "ERROR: Installer artwork missing" >&2 exit 1 fi hdiutil create -volname "PHPGuard $VERSION" -srcfolder "$STAGING" -ov -format UDZO "$DMG" # Apply custom Finder icon to the DMG. if command -v fileicon >/dev/null 2>&1; then fileicon set "$DMG" "$INSTALLER_ICNS" else echo "WARNING: fileicon is not installed." echo "Install with: brew install fileicon" echo "DMG created without a custom Finder icon." fi xcrun notarytool submit "$DMG" --keychain-profile "$PROFILE" --wait xcrun stapler staple "$DMG" xcrun stapler validate "$DMG" echo "Release ready: $DMG"