From 7c16d16a0556f7efaeefa83a44c9982fae59abe8 Mon Sep 17 00:00:00 2001 From: saymrwulf Date: Thu, 14 May 2026 15:52:14 +0200 Subject: [PATCH] =?UTF-8?q?Add=20CrisisViz/package-dmg.sh=20=E2=80=94=20di?= =?UTF-8?q?stributable=20DMG=20installer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- CrisisViz/.gitignore | 3 ++ CrisisViz/package-dmg.sh | 81 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100755 CrisisViz/package-dmg.sh diff --git a/CrisisViz/.gitignore b/CrisisViz/.gitignore index 6b5ed04..9fc305c 100644 --- a/CrisisViz/.gitignore +++ b/CrisisViz/.gitignore @@ -9,3 +9,6 @@ xcuserdata/ CrisisViz.app/ AppIcon.iconset/ AppIcon.icns + +# Distribution artifacts produced by package-dmg.sh +*.dmg diff --git a/CrisisViz/package-dmg.sh b/CrisisViz/package-dmg.sh new file mode 100755 index 0000000..30d2720 --- /dev/null +++ b/CrisisViz/package-dmg.sh @@ -0,0 +1,81 @@ +#!/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 <