#!/bin/bash
# A notarized download, independent of the tarballs used by app updates.
# Requires create-dmg (brew install create-dmg), jq, and Apple's command line tools.
# Uses the same APPLE_CERTIFICATE_* and APPLE_API_* secrets as mac-sign/notary-test.
set -euo pipefail

app=${1:?usage: mac-dmg signed-Herdr.app output.dmg}
out=${2:?usage: mac-dmg signed-Herdr.app output.dmg}
[[ $(uname -s) == Darwin ]] || { echo 'mac-dmg requires macOS' >&2; exit 1; }
[[ $(basename "$app") == Herdr.app && -d $app ]] || { echo 'expected a signed Herdr.app' >&2; exit 1; }
[[ $out == *.dmg && ! -e $out ]] || { echo 'output must be a new .dmg file' >&2; exit 1; }
: "${APPLE_CERTIFICATE_P12:?missing certificate}"
: "${APPLE_CERTIFICATE_PASSWORD:?missing certificate password}"
: "${APPLE_API_KEY:?missing notary API private key}"
: "${APPLE_API_KEY_ID:?missing notary API key ID}"
: "${APPLE_API_ISSUER:?missing notary API issuer}"
for tool in create-dmg jq tiffutil xcrun; do command -v "$tool" >/dev/null; done
root=$(cd "$(dirname "$0")/.." && pwd)
umask 077
work=$(mktemp -d "${TMPDIR:-/tmp}/herdr-dmg.XXXXXX")
# hdiutil reports physical paths (e.g. /private/tmp instead of /tmp).
work=$(cd "$work" && pwd -P)
start=$(date -u +%Y-%m-%dT%H:%M:%SZ)
started=$SECONDS
build_seconds=0
notary_seconds=0
finish() {
  result=$?
  # create-dmg normally detaches itself, but may fail before reaching that step.
  while IFS= read -r device; do
    hdiutil detach "$device" || true
  done < <(hdiutil info -plist | plutil -convert json -o - - | jq -r --arg prefix "$work/" \
    '.images[] | select(.["image-path"] | startswith($prefix)) | .["system-entities"][] | select(has("mount-point")) | .["dev-entry"]')
  {
    echo '### macOS DMG (does not gate update publishing)'
    echo "- Started: $start"
    echo "- Finished: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
    echo "- Build/sign: $build_seconds seconds"
    echo "- Notarization: $notary_seconds seconds"
    echo "- Total: $((SECONDS - started)) seconds; exit status: $result"
  } | tee -a "${GITHUB_STEP_SUMMARY:-/dev/null}"
  rm -rf "$work"
}
trap finish EXIT
trap 'exit 130' INT
trap 'exit 143' TERM

codesign --verify --deep --strict "$app"
signature=$(codesign -dvv "$app" 2>&1)
[[ $signature == *"Authority=Developer ID Application:"* ]] || { echo 'DMG requires a Developer ID signed app' >&2; exit 1; }
mkdir "$work/source"
ditto "$app" "$work/source/Herdr.app"
tiffutil -cathidpicheck "$root/distribution/macos/dmg/background.png" \
  "$root/distribution/macos/dmg/background@2x.png" -out "$work/background.tiff"
# create-dmg handles Finder's layout on macOS CI runners too. Do not use
# --skip-jenkins: it silently drops the background and icon positions.
create-dmg --volname Herdr --volicon "$root/assets/icons/Herdr.icns" \
  --window-size 660 400 --background "$work/background.tiff" \
  --icon-size 128 --icon Herdr.app 165 190 --hide-extension Herdr.app \
  --app-drop-link 495 190 "$work/Herdr.dmg" "$work/source"
"$root/scripts/mac-sign" "$work/Herdr.dmg"
build_seconds=$((SECONDS - started))
printf '%s' "$APPLE_API_KEY" > "$work/key.p8"
auth=(--key "$work/key.p8" --key-id "$APPLE_API_KEY_ID" --issuer "$APPLE_API_ISSUER")
notary_started=$SECONDS
status=0
xcrun notarytool submit "$work/Herdr.dmg" "${auth[@]}" --wait --timeout 30m \
  --output-format json | tee "$work/submission.json" || status=$?
notary_seconds=$((SECONDS - notary_started))
if [[ $status != 0 ]] || ! jq -e '.status == "Accepted"' "$work/submission.json" >/dev/null; then
  id=$(jq -r '.id // empty' "$work/submission.json")
  if [[ -n $id ]]; then
    xcrun notarytool log "$id" "${auth[@]}" "$work/notary-log.json" && jq . "$work/notary-log.json"
  fi
  echo 'DMG notarization failed' >&2
  exit 1
fi
xcrun stapler staple "$work/Herdr.dmg"
xcrun stapler validate "$work/Herdr.dmg"
spctl --assess --type open --context context:primary-signature --verbose=2 "$work/Herdr.dmg"
mkdir -p "$(dirname "$out")"
mv "$work/Herdr.dmg" "$out"
echo "mac-dmg: $out"
