Add advanced monitoring and release infrastructure
Build and test / macos (push) Canceled after 0s
Signed release / release (push) Canceled after 0s

This commit is contained in:
2026-08-15 18:23:35 -04:00
parent a67bb5fdf3
commit 0da94715be
38 changed files with 4219 additions and 406 deletions
+103
View File
@@ -0,0 +1,103 @@
#!/bin/zsh
set -euo pipefail
PROJECT_DIR="${0:A:h:h}"
APP_PATH="${1:-$PROJECT_DIR/dist/puter.app}"
DMG_PATH="${2:-$PROJECT_DIR/dist/puter-macOS.dmg}"
RELEASE_VALIDATION="${PUTER_RELEASE_BUILD:-0}"
MOUNT_DIR=""
MOUNT_DEVICE=""
cleanup() {
if [[ -n "$MOUNT_DEVICE" ]]; then
hdiutil detach "$MOUNT_DEVICE" >/dev/null 2>&1 || true
fi
if [[ -n "$MOUNT_DIR" && -d "$MOUNT_DIR" ]]; then
rmdir "$MOUNT_DIR" >/dev/null 2>&1 || true
fi
}
trap cleanup EXIT
fail() {
print -u2 "Package validation failed: $1"
exit 2
}
validate_app() {
local app="$1"
local contents="$app/Contents"
local info="$contents/Info.plist"
[[ -d "$app" ]] || fail "app bundle not found at $app"
[[ -x "$contents/MacOS/puter" ]] || fail "main executable is missing"
[[ -x "$contents/Resources/puter-helper" ]] || fail "privileged helper is missing"
if [[ "$RELEASE_VALIDATION" == "1" ]]; then
[[ -x "$contents/Resources/smc" ]] || fail "release SMC backend is missing"
[[ -f "$contents/Resources/Stats-SMC-LICENSE.txt" ]] || fail "release SMC license is missing"
elif [[ -e "$contents/Resources/smc" ]]; then
[[ -x "$contents/Resources/smc" ]] || fail "bundled SMC backend is not executable"
[[ -f "$contents/Resources/Stats-SMC-LICENSE.txt" ]] || fail "bundled SMC license is missing"
fi
[[ -f "$contents/Library/LaunchDaemons/dev.soconnor.puter.helper.plist" ]] || fail "helper launch daemon plist is missing"
[[ -d "$contents/Frameworks/Sparkle.framework" ]] || fail "Sparkle framework is missing"
[[ -f "$contents/Resources/Assets.car" ]] || fail "Icon Composer asset catalog is missing"
plutil -lint "$info" "$contents/Library/LaunchDaemons/dev.soconnor.puter.helper.plist" >/dev/null
[[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$info")" == "dev.soconnor.puter" ]] \
|| fail "unexpected bundle identifier"
[[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIconName' "$info")" == "puter" ]] \
|| fail "Icon Composer asset is not configured"
[[ "$(/usr/libexec/PlistBuddy -c 'Print :LSMinimumSystemVersion' "$info")" == "14.0" ]] \
|| fail "unexpected deployment target"
if /usr/libexec/PlistBuddy -c 'Print :CFBundleIconFile' "$info" >/dev/null 2>&1; then
fail "legacy CFBundleIconFile overrides the Icon Composer asset"
fi
[[ "$(otool -l "$contents/MacOS/puter")" == *'@executable_path/../Frameworks'* ]] \
|| fail "framework runtime search path is missing"
[[ "$(otool -L "$contents/MacOS/puter")" == *'Sparkle.framework'* ]] \
|| fail "main executable is not linked to Sparkle"
codesign --verify --deep --strict "$app"
local signature
signature="$(codesign -dvv "$app" 2>&1)"
[[ "$signature" == *'runtime'* ]] || fail "Hardened Runtime is missing"
if [[ "$RELEASE_VALIDATION" == "1" ]]; then
[[ "$signature" == *'Authority=Developer ID Application:'* ]] \
|| fail "release app is not Developer ID Application signed"
[[ -n "$(print -r -- "$signature" | sed -n 's/^TeamIdentifier=//p')" ]] \
|| fail "release app has no Team Identifier"
/usr/libexec/PlistBuddy -c 'Print :SUFeedURL' "$info" >/dev/null 2>&1 \
|| fail "release app has no Sparkle feed"
/usr/libexec/PlistBuddy -c 'Print :SUPublicEDKey' "$info" >/dev/null 2>&1 \
|| fail "release app has no Sparkle public key"
local entitlements
entitlements="$(codesign -d --entitlements - "$app" 2>/dev/null || true)"
[[ "$entitlements" != *'com.apple.security.get-task-allow'* ]] \
|| fail "release app contains get-task-allow"
[[ "$entitlements" != *'com.apple.security.cs.disable-library-validation'* ]] \
|| fail "release app disables library validation"
fi
}
validate_app "$APP_PATH"
if [[ -f "$DMG_PATH" ]]; then
hdiutil verify "$DMG_PATH" >/dev/null
if [[ "$RELEASE_VALIDATION" == "1" ]]; then
codesign --verify --strict "$DMG_PATH"
fi
MOUNT_DIR="$(mktemp -d /tmp/puter-package.XXXXXX)"
MOUNT_DEVICE="$(hdiutil attach -readonly -nobrowse -mountpoint "$MOUNT_DIR" "$DMG_PATH" | awk '/Apple_APFS/ {print $1; exit}')"
[[ -n "$MOUNT_DEVICE" ]] || fail "DMG did not mount"
[[ -L "$MOUNT_DIR/Applications" ]] || fail "DMG Applications shortcut is missing"
[[ "$(readlink "$MOUNT_DIR/Applications")" == "/Applications" ]] \
|| fail "DMG Applications shortcut has the wrong target"
validate_app "$MOUNT_DIR/puter.app"
fi
if [[ -f "$DMG_PATH" ]]; then
print "Validated $APP_PATH and $DMG_PATH"
else
print "Validated $APP_PATH"
fi