Files
2026-10-01 10:48:59 +01:00

251 lines
4.9 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
PROJECT_ROOT="$(cd "$(dirname "$0")" && pwd)"
cd "$PROJECT_ROOT"
APP_NAME="SonarDesk"
PROJECT="SonarDesk.xcodeproj"
SCHEME="SonarDesk"
CONFIGURATION="Release"
TEAM_ID="39R6U3437D"
SIGN_IDENTITY="B99D353C88996866C49E4389B375645F76870A3F"
PROFILE_NAME="SonarDesk"
NOTARY_PROFILE="sonardesk-notary"
BUILD_DIR="$PROJECT_ROOT/build"
ARCHIVE="$BUILD_DIR/SonarDesk.xcarchive"
APP="$ARCHIVE/Products/Applications/SonarDesk.app"
STAGE="$BUILD_DIR/dmg-stage"
RELEASE_DIR="$PROJECT_ROOT/release"
echo
echo "========================================"
echo " SonarDesk Release Build"
echo "========================================"
echo
echo "===== CLEAN ====="
rm -rf "$ARCHIVE" "$STAGE"
mkdir -p "$BUILD_DIR" "$RELEASE_DIR"
echo
echo "===== ARCHIVE ====="
xcodebuild \
-project "$PROJECT" \
-scheme "$SCHEME" \
-configuration "$CONFIGURATION" \
-archivePath "$ARCHIVE" \
-destination 'generic/platform=macOS' \
CODE_SIGN_STYLE=Manual \
CODE_SIGN_IDENTITY="$SIGN_IDENTITY" \
DEVELOPMENT_TEAM="$TEAM_ID" \
PROVISIONING_PROFILE_SPECIFIER="$PROFILE_NAME" \
ENABLE_HARDENED_RUNTIME=YES \
clean archive
echo
echo "===== VERIFY APP SIGNATURE ====="
codesign --verify --deep --strict --verbose=2 "$APP"
SIGN_INFO="$(codesign -dv --verbose=4 "$APP" 2>&1)"
echo "$SIGN_INFO" | grep \
"Authority=Developer ID Application: Mark Gregory (39R6U3437D)"
echo "$SIGN_INFO" | grep \
"TeamIdentifier=$TEAM_ID"
echo "$SIGN_INFO" | grep \
"Runtime Version="
echo
echo "===== VERIFY EMBEDDED PROFILE ====="
PROFILE_PLIST="$(mktemp)"
trap 'rm -f "$PROFILE_PLIST"' EXIT
security cms -D \
-i "$APP/Contents/embedded.provisionprofile" \
> "$PROFILE_PLIST"
PROFILE_NAME_ACTUAL=$(
/usr/libexec/PlistBuddy \
-c 'Print :Name' \
"$PROFILE_PLIST"
)
PROFILE_UUID=$(
/usr/libexec/PlistBuddy \
-c 'Print :UUID' \
"$PROFILE_PLIST"
)
ICLOUD_ENV=$(
/usr/libexec/PlistBuddy \
-c 'Print :Entitlements:com.apple.developer.icloud-container-environment' \
"$PROFILE_PLIST"
)
echo "Profile: $PROFILE_NAME_ACTUAL"
echo "UUID: $PROFILE_UUID"
echo "iCloud Environment: $ICLOUD_ENV"
if [[ "$ICLOUD_ENV" != "Production" ]]; then
echo "ERROR: iCloud environment is not Production."
exit 1
fi
echo
echo "===== VERIFY SIGNED ENTITLEMENTS ====="
ENTITLEMENTS="$(codesign -d --entitlements :- "$APP" 2>/dev/null)"
echo "$ENTITLEMENTS" | grep -q \
'iCloud.net.absdev.SonarDesk'
echo "$ENTITLEMENTS" | grep -q \
'CloudDocuments'
echo "$ENTITLEMENTS" | grep -q \
'39R6U3437D.net.absdev.SonarDesk'
echo "iCloud entitlements verified."
echo
echo "===== DETERMINE VERSION ====="
VERSION=$(
/usr/libexec/PlistBuddy \
-c 'Print :CFBundleShortVersionString' \
"$APP/Contents/Info.plist"
)
BUILD=$(
/usr/libexec/PlistBuddy \
-c 'Print :CFBundleVersion' \
"$APP/Contents/Info.plist"
)
DMG="$RELEASE_DIR/SonarDesk-${VERSION}.dmg"
echo "Version: $VERSION"
echo "Build: $BUILD"
echo "DMG: $DMG"
echo
echo "===== PREPARE DMG ====="
rm -rf "$STAGE"
rm -f "$DMG"
mkdir -p "$STAGE"
ditto "$APP" "$STAGE/SonarDesk.app"
ln -s /Applications "$STAGE/Applications"
echo
echo "===== CREATE DMG ====="
hdiutil create \
-volname "SonarDesk" \
-srcfolder "$STAGE" \
-ov \
-format UDZO \
"$DMG"
echo
echo "===== SIGN DMG ====="
codesign \
--force \
--timestamp \
--sign "$SIGN_IDENTITY" \
"$DMG"
echo
echo "===== VERIFY DMG SIGNATURE ====="
codesign --verify --verbose=2 "$DMG"
echo
echo "===== NOTARIZE ====="
xcrun notarytool submit "$DMG" \
--keychain-profile "$NOTARY_PROFILE" \
--wait
echo
echo "===== STAPLE ====="
xcrun stapler staple "$DMG"
echo
echo "===== VALIDATE STAPLE ====="
xcrun stapler validate "$DMG"
echo
echo "===== GATEKEEPER CHECK ====="
spctl \
--assess \
--type open \
--context context:primary-signature \
--verbose=4 \
"$DMG"
echo
echo "===== VERIFY APP INSIDE DMG ====="
MOUNT_DIR="$(mktemp -d)"
cleanup_mount() {
hdiutil detach "$MOUNT_DIR" >/dev/null 2>&1 || true
rmdir "$MOUNT_DIR" >/dev/null 2>&1 || true
}
trap 'cleanup_mount; rm -f "$PROFILE_PLIST"' EXIT
hdiutil attach "$DMG" \
-nobrowse \
-readonly \
-mountpoint "$MOUNT_DIR" \
>/dev/null
codesign \
--verify \
--deep \
--strict \
--verbose=2 \
"$MOUNT_DIR/SonarDesk.app"
spctl \
--assess \
--type execute \
--verbose=4 \
"$MOUNT_DIR/SonarDesk.app"
cleanup_mount
rm -rf "$STAGE"
echo
echo "========================================"
echo " RELEASE COMPLETE"
echo "========================================"
echo
echo "Application: SonarDesk"
echo "Version: $VERSION"
echo "Build: $BUILD"
echo "DMG: $DMG"
echo
echo "Signed: YES"
echo "Notarized: YES"
echo "Stapled: YES"
echo "Gatekeeper: PASSED"
echo
echo "========================================"