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
↓ haven-21cf3906.tar.gzatlas at this save
files changed1 file
bundle_app.sh+58 −21bundle_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