#!/usr/bin/env bash set -euo pipefail cd "$(dirname "$0")" echo "==> Stopping any running Pommedoro..." pkill -9 -f Pommedoro 2>/dev/null || true sleep 0.5 echo "==> Cleaning previous build..." rm -rf .build/Pommedoro.app .build/Pommedoro.dmg echo "==> Building release (DMG + SHA256)..." make release echo "==> Verifying SHA256 file was generated..." if [ ! -f releases/Pommedoro.dmg.sha256 ]; then echo "==> FAIL: releases/Pommedoro.dmg.sha256 not found." exit 1 fi SHA_CONTENT="$(cat releases/Pommedoro.dmg.sha256)" if [ ${#SHA_CONTENT} -ne 64 ]; then echo "==> FAIL: SHA256 file content is not a valid 64-char hex hash." exit 1 fi echo "==> OK: SHA256 = ${SHA_CONTENT}" echo "==> Verifying SHA256 matches DMG..." ACTUAL_SHA="$(shasum -a 256 releases/Pommedoro.dmg | awk '{print $1}')" if [ "${SHA_CONTENT}" != "${ACTUAL_SHA}" ]; then echo "==> FAIL: SHA256 mismatch (file: ${SHA_CONTENT}, actual: ${ACTUAL_SHA})." exit 1 fi echo "==> OK: SHA256 matches DMG." echo "==> Simulating download quarantine on DMG..." xattr -w com.apple.quarantine "0081;67890abc;Safari;12345678-1234-1234-1234-123456789012" .build/Pommedoro.dmg echo "==> Mounting quarantined DMG..." hdiutil attach .build/Pommedoro.dmg -nobrowse -quiet echo "==> Running Install.command from DMG..." bash /Volumes/Pommedoro/Install.command sleep 2 echo "==> Verifying app is running..." if pgrep -x Pommedoro > /dev/null; then echo "==> SUCCESS: Pommedoro is running." else echo "==> FAIL: Pommedoro did not launch." hdiutil detach /Volumes/Pommedoro -quiet 2>/dev/null || true exit 1 fi echo "==> Verifying quarantine is stripped..." if xattr /Applications/Pommedoro.app 2>&1 | grep -q "com.apple.quarantine"; then echo "==> FAIL: quarantine attribute still present." hdiutil detach /Volumes/Pommedoro -quiet 2>/dev/null || true exit 1 else echo "==> OK: no quarantine attribute." fi echo "==> Verifying state (SHA + timestamp) was stamped locally..." SHA_FILE="${HOME}/Library/Application Support/Pommedoro/current.sha256" if [ ! -f "${SHA_FILE}" ]; then echo "==> FAIL: local state file not found at ${SHA_FILE}." hdiutil detach /Volumes/Pommedoro -quiet 2>/dev/null || true exit 1 fi LOCAL_SHA="$(head -1 "${SHA_FILE}")" EXPECTED_SHA="$(cat releases/Pommedoro.dmg.sha256)" if [ "${LOCAL_SHA}" != "${EXPECTED_SHA}" ]; then echo "==> FAIL: local SHA ${LOCAL_SHA} != expected ${EXPECTED_SHA}." hdiutil detach /Volumes/Pommedoro -quiet 2>/dev/null || true exit 1 fi echo "==> OK: local state SHA = ${LOCAL_SHA}" hdiutil detach /Volumes/Pommedoro -quiet 2>/dev/null || true echo "" echo "==> All checks passed." echo "==> DMG at: .build/Pommedoro.dmg" echo "==> Release at: releases/Pommedoro.dmg + releases/Pommedoro.dmg.sha256" # Optional: push release and prove remote matches launched app if [ "${1:-}" = "--push" ]; then echo "" echo "==> Pushing release to remote..." git add releases/Pommedoro.dmg releases/Pommedoro.dmg.sha256 if git diff --staged --quiet 2>/dev/null; then echo "==> No release changes to push." else RELEASE_SHA="$(cat releases/Pommedoro.dmg.sha256)" git commit -m "Release: ${RELEASE_SHA}" git push fi echo "==> Proving remote matches launched app..." REMOTE_SHA="$(curl -sL "https://git.nixc.us/colin/pommedoro/raw/branch/main/releases/Pommedoro.dmg.sha256" | tr -d '\r\n' | head -c 64)" LOCAL_SHA="$(head -1 "${SHA_FILE}" | tr -d '\r\n' | head -c 64)" if [ -z "${REMOTE_SHA}" ] || [ "${REMOTE_SHA}" != "${LOCAL_SHA}" ]; then echo "==> FAIL: remote SHA (${REMOTE_SHA}) != local state (${LOCAL_SHA}). Update check would not show Up to Date." exit 1 fi echo "==> PROVEN: remote SHA = local state. Launched app is identical to release; Check for Updates will show Up to Date." fi