#!/usr/bin/env bash
#
# website-deploy-commit.sh  -  commit and push the website sync under the identity
# the deploy platform will actually build, then prove the build happened.
#
# Why this is a script and not three lines in the sync doc: the deploy platform
# refuses to build a commit whose author is not a contributor on the project. The
# push still succeeds, the deployment is created and sits at UNKNOWN with a 0ms
# build (API `readyState: BLOCKED`), and the live site keeps serving the previous
# version. v16.4.0 and v16.5.0 were both pushed that way and neither was built,
# while the sync reported the website as synced both times.
#
# Usage:
#   website-deploy-commit.sh <identity-name> <identity-email> <version> [repo-dir]
#
# Env:
#   WEBSITE_SYNC_NO_PUSH=1     commit and verify locally, never push (smoke/dry-run)
#   WEBSITE_SYNC_NO_VERIFY=1   skip the deployment check (offline, or no CLI)
#   WEBSITE_SYNC_WAIT=<sec>    how long to wait for a Ready build (default 45)
#
# Exit: 0 committed+pushed (or nothing to do), 1 wrong author (nothing pushed),
#       2 usage or environment, 3 pushed but no Ready production build.

set -uo pipefail

NAME="${1:-}"
EMAIL="${2:-}"
VERSION="${3:-}"
DIR="${4:-$PWD}"

if [ -z "$NAME" ] || [ -z "$EMAIL" ] || [ -z "$VERSION" ]; then
  echo "usage: website-deploy-commit.sh <identity-name> <identity-email> <version> [repo-dir]" >&2
  exit 2
fi

# An empty fourth argument is a caller bug, not a request for the current
# directory: falling back to $PWD there commits whatever repo the caller happens
# to be standing in.
[ -n "$DIR" ] || { echo "FAIL: empty repo directory argument" >&2; exit 2; }
cd "$DIR" 2>/dev/null || { echo "FAIL: cannot enter $DIR" >&2; exit 2; }
git rev-parse --git-dir >/dev/null 2>&1 || { echo "FAIL: $DIR is not a git repository" >&2; exit 2; }

# Read before writing. The website clone's own config is usually already correct,
# and overwriting it with whatever identity the caller passed is the failure mode
# this guard exists to prevent, not a convenience.
[ "$(git config user.email || true)" = "$EMAIL" ] || git config user.email "$EMAIL"
[ "$(git config user.name || true)" = "$NAME" ] || git config user.name "$NAME"

git add -A
if git diff --cached --quiet; then
  echo "website: already in sync, nothing to commit"
  exit 0
fi

git commit -q -m "chore: sync pipeline v${VERSION}" || { echo "FAIL: commit failed" >&2; exit 2; }

# git config loses to an exported GIT_AUTHOR_EMAIL, so the recorded author is read
# back off the commit itself. Anything else is a hope, not a check.
ACTUAL="$(git log -1 --format=%ae)"
if [ "$ACTUAL" != "$EMAIL" ]; then
  echo "HALT: website commit authored by $ACTUAL, expected $EMAIL." >&2
  echo "Nothing was pushed. Re-author it (git commit --amend --reset-author) and run this again;" >&2
  echo "a commit the deploy platform does not recognise is accepted by the push and never built." >&2
  exit 1
fi

if [ "${WEBSITE_SYNC_NO_PUSH:-0}" = "1" ]; then
  echo "website: committed as $ACTUAL (push skipped)"
  exit 0
fi

git push -q origin HEAD || { echo "FAIL: push rejected" >&2; exit 2; }
echo "website: pushed v${VERSION} as $ACTUAL"

# A push is not a deploy.
if [ "${WEBSITE_SYNC_NO_VERIFY:-0}" = "1" ] || ! command -v vercel >/dev/null 2>&1 \
  || [ ! -f "$DIR/.vercel/project.json" ]; then
  echo "website: deployment not verified (no CLI or verification skipped)"
  exit 0
fi

WAIT="${WEBSITE_SYNC_WAIT:-45}"
ELAPSED=0
while [ "$ELAPSED" -lt "$WAIT" ]; do
  # `vercel ls` prints its table on STDERR, not stdout. Discarding stderr threw
  # away the very rows this grep reads, so ROW was always empty and the check
  # reported "no Ready production build" on every run - including the ones that
  # deployed fine. A guard that cannot pass is worse than no guard: it trains
  # the reader to ignore the one message meant to catch a real failure.
  ROW="$(vercel ls --yes 2>&1 | grep -m1 'Production' || true)"
  case "$ROW" in
    *Ready*) echo "website: production build Ready"; exit 0 ;;
    *Error*) break ;;
  esac
  sleep 5
  ELAPSED=$((ELAPSED + 5))
done

echo "website: no Ready production build after ${WAIT}s -> ${ROW:-no deployment listed}" >&2
echo "UNKNOWN with a 0ms build means the commit author was rejected: fix the author and push again," >&2
echo "or deploy from the CLI with: (cd \"$DIR\" && vercel --prod --yes)" >&2
exit 3
