#!/bin/zsh set -euo pipefail SCRIPT_DIR="${0:A:h}" ROOT="${SCRIPT_DIR:h}" PROJECT="$ROOT/PegasusMonitor.xcodeproj" SCHEME="PegasusMonitor" DERIVED="$ROOT/.build/ReleaseDerivedData" APP="$DERIVED/Build/Products/Release/PegasusMonitor.app" DIST="$ROOT/dist" [[ -d "$PROJECT" ]] || { print -u2 "Missing Xcode project: $PROJECT"; exit 1; } for cmd in xcodebuild codesign hdiutil; do command -v "$cmd" >/dev/null || { print -u2 "Missing command: $cmd"; exit 1; } done # Choose a Developer ID Application identity unless explicitly provided. IDENTITY="${SIGNING_IDENTITY:-}" if [[ -z "$IDENTITY" ]]; then IDENTITY="$(security find-identity -v -p codesigning 2>/dev/null | awk '/Developer ID Application:/ {print $2; exit}')" fi if [[ -z "$IDENTITY" && "${ALLOW_UNSIGNED:-0}" != 1 ]]; then print -u2 'No Developer ID Application identity found. Set SIGNING_IDENTITY or use ALLOW_UNSIGNED=1 for a local test package.' exit 1 fi print "Building $SCHEME (Release)..." xcodebuild -project "$PROJECT" -scheme "$SCHEME" -configuration Release \ -derivedDataPath "$DERIVED" -destination 'platform=macOS' \ CODE_SIGNING_ALLOWED=NO build [[ -d "$APP" ]] || { print -u2 "Missing built application: $APP"; exit 1; } VERSION="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$APP/Contents/Info.plist")" BUILD="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$APP/Contents/Info.plist")" NAME="PegasusMonitor-${VERSION}-${BUILD}" mkdir -p "$DIST" DMG="$DIST/$NAME.dmg" if [[ -n "$IDENTITY" ]]; then print "Signing application with: $IDENTITY" codesign --force --deep --options runtime --timestamp --sign "$IDENTITY" "$APP" codesign --verify --deep --strict --verbose=2 "$APP" else print 'WARNING: creating unsigned local-test release; distribution outside this Mac is not recommended.' fi STAGE="$(mktemp -d)" trap 'rm -rf "$STAGE"' EXIT cp -R "$APP" "$STAGE/PegasusMonitor.app" ln -s /Applications "$STAGE/Applications" rm -f "$DMG" hdiutil create -volname "Pegasus Monitor" -srcfolder "$STAGE" -format UDZO -ov "$DMG" >/dev/null # Assign the application icon to the DMG file in Finder. ICON="$APP/Contents/Resources/AppIcon.icns" if [[ -f "$ICON" ]]; then /usr/bin/swift - "$ICON" "$DMG" <<'SWIFT' import AppKit import Foundation let iconPath = CommandLine.arguments[1] let dmgPath = CommandLine.arguments[2] guard let image = NSImage(contentsOfFile: iconPath) else { fatalError("Unable to load DMG icon") } guard NSWorkspace.shared.setIcon( image, forFile: dmgPath, options: [] ) else { fatalError("Unable to assign DMG icon") } print("Custom DMG icon applied.") SWIFT fi # Optional Apple notary profile, previously saved with `xcrun notarytool store-credentials`. if [[ -z "${NOTARY_PROFILE:-}" ]]; then NOTARY_PROFILE="orion-notary" fi if [[ -n "$NOTARY_PROFILE" ]]; then [[ -n "$IDENTITY" ]] || { print -u2 'Notarization requires a signed app.'; exit 1; } print "Submitting for notarization with profile: $NOTARY_PROFILE" xcrun notarytool submit "$DMG" --keychain-profile "$NOTARY_PROFILE" --wait xcrun stapler staple "$DMG" xcrun stapler validate "$DMG" fi print "Release: $DMG" print "Version: $VERSION ($BUILD)"