Two findings from the FRE-1695 review (approved atdf788cb6). 1. The mirrored deploy activates a destructive cron the deploy docs never mentioned. vercel.json carries two crons: /api/the-nook/lifecycle (13:00 UTC), already on the tree Vercel builds, and /api/analytics-retention (12:00 UTC,1d9287a/ FRE-369), which exists only on Gitea master. The first deploy that follows the mirror starts calling it, and the next 12:00 UTC deletes every VisitorAnalytics row older than the window — ANALYTICS_RETENTION_DAYS, 365 by default — irreversibly and unstaged. The behaviour is intended; the silence was not, because the operator is the one who presses the button. docs/deploy-source.md "Failure modes" now names the cron, the ANALYTICS_RETENTION_SECRET ?? CRON_SECRET bearer check, the 365-day default, the fails-closed-without-a-secret path, and that the first run after enabling prunes at that default. 2. scripts/verify-deploy.sh could read green with a broken root deploy: it probed nook.freno.me, nessa.freno.me/terms and the two remotes, never freno.me itself — and FRE-1695's acceptance names the root domain. Adds a ROOT_HOST (default https://freno.me) status check ahead of the subdomain probes: expects a direct 200, no -L, so a redirect reads as a failure. It deliberately does not probe https://freno.me/terms — SITEMAP_ROUTES.main has no /terms; Terms of Use is a Nessa surface, so a root /terms 404 is the design. The script stays read-only and credential-free.
102 lines
4.0 KiB
Bash
Executable File
102 lines
4.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Live probe for the freno-dev deploy path (FRE-1695). Read-only; no credentials.
|
|
#
|
|
# Proves, in one run:
|
|
# 1. Gitea master and GitHub master are the same commit (the mirror converged).
|
|
# 2. The root domain answers on its own terms: https://freno.me/ returns a direct 200,
|
|
# so a broken root deploy cannot read as green while the subdomains look fine.
|
|
# 3. The live site serves copy that only exists on the reconciled line:
|
|
# NOOK-1038's scoped remote claim (GitHub-only before the merge) *and*
|
|
# FRE-997's "Supported agents" (Gitea-only before the merge). Both at once
|
|
# can only come from the merge commit.
|
|
# 4. The served tree therefore contains FRE-371 (`2fd2a4a`), which is an
|
|
# ancestor of that merge — checked locally when the commit is in the object
|
|
# store, so run this from a freno-dev checkout.
|
|
#
|
|
# Usage: scripts/verify-deploy.sh [expected-gitea-sha]
|
|
|
|
set -uo pipefail
|
|
|
|
GITEA_REMOTE="${GITEA_REMOTE:-https://git.freno.me/Mike/freno-dev.git}"
|
|
GITHUB_REMOTE="${GITHUB_REMOTE:-https://github.com/mikefreno/freno-dev.git}"
|
|
ROOT_HOST="${ROOT_HOST:-https://freno.me}"
|
|
NOOK_HOST="${NOOK_HOST:-https://nook.freno.me}"
|
|
NESSA_HOST="${NESSA_HOST:-https://nessa.freno.me}"
|
|
|
|
fail=0
|
|
ok() { printf 'ok %s\n' "$1"; }
|
|
bad() { printf 'FAIL %s\n' "$1"; fail=1; }
|
|
|
|
echo "== remotes =="
|
|
gitea_sha=$(git ls-remote "$GITEA_REMOTE" refs/heads/master | cut -f1)
|
|
github_sha=$(git ls-remote "$GITHUB_REMOTE" refs/heads/master | cut -f1)
|
|
printf 'gitea master %s\ngithub master %s\n' "${gitea_sha:-<none>}" "${github_sha:-<none>}"
|
|
|
|
[ -n "$gitea_sha" ] && ok "gitea master readable" || bad "gitea master unreadable"
|
|
if [ -n "$gitea_sha" ] && [ "$gitea_sha" = "$github_sha" ]; then
|
|
ok "github master is the same commit (mirror converged)"
|
|
else
|
|
bad "github master differs from gitea master — the mirror has not run"
|
|
fi
|
|
|
|
if [ -n "${1:-}" ]; then
|
|
if [ "$1" = "$gitea_sha" ]; then ok "gitea master is the expected commit $1"
|
|
else bad "gitea master is $gitea_sha, expected $1"; fi
|
|
fi
|
|
|
|
echo
|
|
echo "== live copy =="
|
|
# The root is every other surface's entry point and deploys from the same tree, so it is
|
|
# probed first. No -L: a redirect away from 200 is the failure we want to see, not a pass.
|
|
root_code=$(curl -sS -o /dev/null -w '%{http_code}' "$ROOT_HOST/" 2>/dev/null)
|
|
if [ "$root_code" = "200" ]; then
|
|
ok "$ROOT_HOST/ serves 200"
|
|
elif [ -z "$root_code" ] || [ "$root_code" = "000" ]; then
|
|
bad "$ROOT_HOST/ gave no response, expected 200"
|
|
else
|
|
bad "$ROOT_HOST/ returned $root_code, expected 200 (green subdomains do not cover the root)"
|
|
fi
|
|
|
|
page=$(curl -sS "$NOOK_HOST/" 2>/dev/null)
|
|
case "$page" in
|
|
*"One-click setup for Tailscale and authorized known hosts"*)
|
|
ok "nook landing carries NOOK-1038's scoped remote claim" ;;
|
|
*) bad "nook landing is missing NOOK-1038's scoped remote claim" ;;
|
|
esac
|
|
|
|
agents=$(curl -sS "$NOOK_HOST/agents" 2>/dev/null)
|
|
case "$agents" in
|
|
*"Supported agents"*) ok "nook /agents carries FRE-997's restored coverage title" ;;
|
|
*) bad "nook /agents still serves the pre-FRE-997 title" ;;
|
|
esac
|
|
|
|
terms_code=$(curl -sS -o /tmp/verify-deploy-terms.$$ -w '%{http_code}' "$NESSA_HOST/terms" 2>/dev/null)
|
|
if [ "$terms_code" = "200" ] && grep -q 'nessa-support@freno.me' /tmp/verify-deploy-terms.$$; then
|
|
ok "nessa /terms is published and names the support address (FRE-1670)"
|
|
else
|
|
bad "nessa /terms returned $terms_code without the support address (FRE-1670 undeployed)"
|
|
fi
|
|
rm -f /tmp/verify-deploy-terms.$$
|
|
|
|
echo
|
|
echo "== ancestry =="
|
|
for commit in 2fd2a4a 7fde259; do
|
|
if git cat-file -e "${commit}^{commit}" 2>/dev/null; then
|
|
if git merge-base --is-ancestor "$commit" "$gitea_sha" 2>/dev/null; then
|
|
ok "$commit is an ancestor of gitea master"
|
|
else
|
|
bad "$commit is NOT an ancestor of gitea master"
|
|
fi
|
|
else
|
|
printf 'skip %s not in this clone; run from a freno-dev checkout to check ancestry\n' "$commit"
|
|
fi
|
|
done
|
|
|
|
echo
|
|
if [ "$fail" -eq 0 ]; then
|
|
echo "PASS — the deploy follows gitea master and the served tree contains FRE-371."
|
|
else
|
|
echo "FAIL — see the lines above."
|
|
fi
|
|
exit "$fail"
|