crisis/CrisisViz/package-dmg.sh
saymrwulf 7c16d16a05 Add CrisisViz/package-dmg.sh — distributable DMG installer
bundle.sh produces CrisisViz.app but stops there; the standard way
to hand a macOS app to someone on a different machine is a DMG with
the app and an Applications symlink so the user can drag-install.
This script fills the gap, using only macOS-built-in tools
(`hdiutil`, `codesign`, `shasum`) so a fresh checkout doesn't need
Homebrew packages.

What it does, end-to-end:
  1. If CrisisViz.app is missing, calls bundle.sh --no-launch.
  2. Re-codesigns the .app ad-hoc and clears the quarantine xattr.
  3. Stages the .app + a symlink "Applications -> /Applications"
     in a tmpdir.
  4. hdiutil create -format UDZO (compressed, read-only).
  5. Codesigns the DMG itself ad-hoc.
  6. hdiutil verify the result; print size + SHA-256.

Ad-hoc signing is fine for personal / educational distribution —
the user gets a Gatekeeper warning on first open and right-clicks
"Open" once. Notarization would require a paid Apple Developer
account and is not in scope for this artifact.

`*.dmg` added to CrisisViz/.gitignore.

Verified end-to-end: produces a 31 MB DMG that mounts cleanly,
contains CrisisViz.app and the Applications symlink, and passes
`hdiutil verify`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 15:52:14 +02:00

81 lines
2.4 KiB
Bash
Executable file

#!/bin/bash
# Build CrisisViz.dmg — an ad-hoc-signed disk image for distribution.
#
# ./package-dmg.sh
#
# Produces CrisisViz.dmg in the current directory containing the assembled
# CrisisViz.app plus a symlink to /Applications, so the installer can drag
# the app onto the Applications shortcut. The DMG is read-only, compressed
# (UDZO), and ad-hoc signed.
#
# Gatekeeper note: ad-hoc signing means the first launch on a new Mac will
# show "macOS cannot verify the developer of CrisisViz". Right-click the app
# in /Applications → Open → Open in the confirmation dialog. macOS remembers
# the decision; subsequent launches behave normally.
set -euo pipefail
cd "$(dirname "$0")"
APP=CrisisViz.app
DMG=CrisisViz.dmg
VOLNAME=CrisisViz
STAGE=$(mktemp -d -t crisisviz-dmg)
trap 'rm -rf "$STAGE"' EXIT
# 1. Ensure the .app bundle exists. If not, build it without launching.
if [ ! -d "$APP" ]; then
echo "==> $APP not found — running bundle.sh first..."
./bundle.sh --no-launch
fi
# Defensive: confirm the executable is actually inside the bundle.
if [ ! -x "$APP/Contents/MacOS/CrisisViz" ]; then
echo "!! $APP exists but the executable is missing. Run ./bundle.sh manually." >&2
exit 1
fi
# 2. Re-codesign the app (ad-hoc) and clear any quarantine attributes.
echo "==> Codesigning $APP (ad-hoc)..."
codesign --force --deep --sign - "$APP" 2>/dev/null || true
xattr -dr com.apple.quarantine "$APP" 2>/dev/null || true
# 3. Stage the DMG layout: the .app + a symlink to /Applications.
echo "==> Staging DMG layout in $STAGE..."
cp -R "$APP" "$STAGE/"
ln -s /Applications "$STAGE/Applications"
# 4. Build the compressed read-only DMG.
echo "==> Creating $DMG (UDZO, compressed)..."
rm -f "$DMG"
hdiutil create \
-volname "$VOLNAME" \
-srcfolder "$STAGE" \
-fs HFS+ \
-format UDZO \
-ov \
-quiet \
"$DMG"
# 5. Ad-hoc sign the DMG itself so macOS treats it as a signed artifact.
echo "==> Codesigning $DMG (ad-hoc)..."
codesign --force --sign - "$DMG" 2>/dev/null || true
# 6. Verify and report.
echo "==> Verifying $DMG..."
hdiutil verify -quiet "$DMG"
SIZE=$(du -h "$DMG" | awk '{print $1}')
SHA=$(shasum -a 256 "$DMG" | awk '{print $1}')
cat <<INFO
OK Built $DMG ($SIZE)
SHA-256: $SHA
Install on a target Mac:
1. Copy $DMG to the target machine.
2. Double-click to mount the volume.
3. Drag $APP onto the Applications shortcut.
4. Eject the volume.
5. First launch: right-click /Applications/$APP → Open → Open.
INFO