21cf39065e7f

rewrite bundle_app.sh to build release, bundle, sign, and zip into Haven.app.zip via ditto

time
2026-07-15 23:11 UTC · 3 months ago
machine
koh2
agent
claude-opus-4
session
macos .app build
parent
2ff9b8e9fbe2
1 file bundle_app.sh+58 −21
bundle_app.sh+58 −21
@@ -1,31 +1,68 @@11 #!/bin/bash2-set -e2+# Bundle Haven into a signed .app and zip it for distribution.3+#4+# Driven by koh offer --builds via kepr.build, which sets KEPR_PLATFORM5+# per-platform. macos-aarch64 builds natively; macos-x86_64 cross-compiles6+# from Apple Silicon via Swift's --triple flag.7+#8+# Output: Haven.app.zip in the repo root, ready for koh to upload as the9+# release artifact for this platform.10+set -euo pipefail311 412 APP_NAME="Haven"5-BUILD_DIR=".build/arm64-apple-macosx/debug"6-APP_BUNDLE="$APP_NAME.app"13+BUNDLE="${APP_NAME}.app"14+ZIP="${APP_NAME}.app.zip"15+ENTITLEMENTS="${APP_NAME}.entitlements"716 8-# 1. Build9-echo "Building..."10-swift build17+# Wipe stale outputs so re-runs are idempotent and we never ship a18+# half-codesigned bundle left over from a previous attempt.19+rm -rf "${BUNDLE}" "${ZIP}"1120 12-# 2. Create Structure13-echo "Bundling..."14-mkdir -p "$APP_BUNDLE/Contents/MacOS"15-mkdir -p "$APP_BUNDLE/Contents/Resources"21+# Build the executable in release mode. Package.swift declares the product22+# as `Haven` (capital H); .build/release is a symlink to23+# <arch>-apple-macosx/release so this path works for both native and24+# cross-compiled builds.25+case "${KEPR_PLATFORM:-}" in26+    macos-x86_64)27+        echo "  → swift build -c release --triple x86_64-apple-macosx"28+        swift build -c release --triple x86_64-apple-macosx29+        ;;30+    macos-aarch64|"")31+        echo "  → swift build -c release"32+        swift build -c release33+        ;;34+    *)35+        echo "  → swift build -c release (unknown KEPR_PLATFORM='${KEPR_PLATFORM}', defaulting to native)"36+        swift build -c release37+        ;;38+esac1639 17-# 3. Copy Binary18-cp "$BUILD_DIR/$APP_NAME" "$APP_BUNDLE/Contents/MacOS/"40+# Verify the binary actually materialised where we expect it. Catching this41+# here beats waiting for koh's "output binary not found" message at the42+# upload step.43+if [ ! -f ".build/release/${APP_NAME}" ]; then44+    echo "✗ .build/release/${APP_NAME} not produced" >&245+    exit 146+fi1947 20-# 4. Copy Info.plist21-cp Info.plist "$APP_BUNDLE/Contents/"22-23-# 4b. Copy Icon24-if [ -f "AppIcon.icns" ]; then25-    cp AppIcon.icns "$APP_BUNDLE/Contents/Resources/"48+# Assemble the bundle. The directory shape is what Finder + codesign expect:49+# Contents/MacOS/<executable>, Contents/Info.plist, Contents/Resources/.50+mkdir -p "${BUNDLE}/Contents/MacOS"51+mkdir -p "${BUNDLE}/Contents/Resources"52+cp ".build/release/${APP_NAME}" "${BUNDLE}/Contents/MacOS/"53+cp Info.plist "${BUNDLE}/Contents/"54+if [ -f AppIcon.icns ]; then55+    cp AppIcon.icns "${BUNDLE}/Contents/Resources/"2656 fi2757 28-# 5. Codesign (Ad-hoc) to satisfy some APIs29-codesign --force --deep --entitlements Haven.entitlements --sign - "$APP_BUNDLE"58+# Ad-hoc sign with the project's entitlements. Some macOS APIs require even59+# an ad-hoc signature to recognise the bundle as runnable.60+codesign --force --deep --entitlements "${ENTITLEMENTS}" --sign - "${BUNDLE}"3061 31-echo "$APP_NAME.app is ready."62+# Zip with ditto — the canonical Apple tool. It preserves resource forks63+# and extended attributes, which plain `zip` would mangle, and --keepParent64+# stores Haven.app/ at the top of the archive so unzip reproduces the65+# standard layout.66+ditto -c -k --sequesterRsrc --keepParent "${BUNDLE}" "${ZIP}"67+68+echo "${ZIP} is ready."\ No newline at end of file

view file