#!/usr/bin/env bash # Outside-in checks for bank / exchange / merchant landing stats + alt UI assets. # Usage: ./test-landing-stats.sh # Exit 0 only if all critical checks pass. set -euo pipefail ROOT="$(cd "$(dirname "$0")/../.." && pwd)" PY="${PYTHON:-python3}" BANK="${BANK_PUBLIC:-https://bank.hacktivism.ch}" EX="${EXCHANGE_PUBLIC:-https://exchange.hacktivism.ch}" MER="${MERCHANT_PUBLIC:-https://taler.hacktivism.ch}" fail=0 pass=0 note() { printf ' %s\n' "$*"; } ok() { pass=$((pass + 1)); printf ' [OK] %s\n' "$*"; } bad() { fail=$((fail + 1)); printf ' [FAIL] %s\n' "$*"; } http_code() { curl -skS -m 15 -o /tmp/landing-test.body -w '%{http_code}' "$1" 2>/dev/null || echo 000 } echo "=== local repo checks ===" for f in \ configs/shared/goa-amount.js \ configs/bank-landing/goa-amount.js \ configs/exchange-landing/goa-amount.js \ configs/merchant-landing/goa-amount.js \ configs/bank-landing/index.html \ configs/exchange-landing/index.html \ configs/merchant-landing/index.html \ scripts/taler-landing/goa_amounts.py \ scripts/taler-landing/collect_bank_stats.py do if [ -f "$ROOT/$f" ]; then ok "file $f" else bad "missing $f" fi done for html in bank-landing exchange-landing merchant-landing; do if grep -q 'goa-amount.js' "$ROOT/configs/$html/index.html" \ && grep -q 'GoaAmount' "$ROOT/configs/$html/index.html"; then ok "$html index wires GoaAmount" else bad "$html index missing goa-amount / GoaAmount" fi if grep -q 'Fallback if goa-amount.js' "$ROOT/configs/$html/index.html"; then ok "$html has offline fallback" else bad "$html missing offline GoaAmount fallback" fi done echo echo "=== unit: goa_amounts enrich (all three shapes) ===" if "$PY" - </dev/null; then ok "$name live HTML references goa-amount.js" else note "[WARN] $name live HTML has no goa-amount.js yet (deploy pending)" fi code=$(http_code "$base/intro/stats.json") if [ "$code" = "200" ] && "$PY" -c 'import json,sys; d=json.load(open("/tmp/landing-test.body")); sys.exit(0 if d.get("ok") else 1)'; then gen=$("$PY" -c 'import json; d=json.load(open("/tmp/landing-test.body")); print(d.get("generated_at_human") or d.get("generated_at") or "?")') ok "$name stats.json ok (gen=$gen)" # enrich live payload if "$PY" "$ROOT/scripts/taler-landing/enrich_stats_alt.py" /tmp/landing-test.body -o /tmp/landing-test.enriched.json >/dev/null 2>&1; then ok "$name live stats enrichable with amount_alt" else bad "$name live stats enrich failed" fi # resources / memory block if "$PY" - <<'PY' import json, sys d = json.load(open("/tmp/landing-test.body")) p = d.get("performance") or {} mem = p.get("memory") or {} fail = [] if not p: fail.append("no performance") # latency probes differ per site but config_ms is common if p.get("config_ms") is None and p.get("keys_ms") is None: fail.append("no latency ms") ctr = mem.get("container_rss_human") or "" if not ctr or ctr in ("—", "-", "0"): fail.append("container_rss_human missing") if not isinstance(mem.get("top"), list) or len(mem.get("top") or []) < 1: fail.append("top processes empty") # role groups should exist as keys for k in ("postgres_rss_human", "nginx_rss_human"): if k not in mem: fail.append("missing " + k) if fail: print("resources issues:", ", ".join(fail)) sys.exit(1) print("resources ok container=", ctr, "top_n=", len(mem.get("top") or []), "loadavg=", p.get("loadavg")) sys.exit(0) PY then ok "$name performance.memory present (RSS + top)" else bad "$name performance.memory incomplete" fi # merge dry-run on live stats (re-apply compact labels) if "$PY" "$ROOT/scripts/taler-landing/merge_resources.py" /tmp/landing-test.body \ <("$PY" -c 'import json; d=json.load(open("/tmp/landing-test.body")); p=d.get("performance") or {}; print(json.dumps({"ok":True,"loadavg":p.get("loadavg") or "","memory":p.get("memory") or {}}))') \ -o /tmp/landing-test.resmerged.json 2>/dev/null; then ok "$name resource merge on live payload" else # fallback without process substitution for macOS bash "$PY" -c 'import json; d=json.load(open("/tmp/landing-test.body")); p=d.get("performance") or {}; json.dump({"ok":True,"loadavg":p.get("loadavg") or "","memory":p.get("memory") or {}}, open("/tmp/landing-test.res.json","w"))' if "$PY" "$ROOT/scripts/taler-landing/merge_resources.py" /tmp/landing-test.body /tmp/landing-test.res.json -o /tmp/landing-test.resmerged.json 2>/dev/null; then ok "$name resource merge on live payload" else bad "$name resource merge failed" fi fi else bad "$name stats.json HTTP $code / not ok" fi code=$(http_code "$base/intro/stats-run.json") if [ "$code" = "200" ]; then ok "$name stats-run.json HTTP 200" else bad "$name stats-run.json HTTP $code" fi code=$(http_code "$base/intro/goa-amount.js") if [ "$code" = "200" ] && grep -q 'GoaAmount' /tmp/landing-test.body; then ok "$name goa-amount.js live" else note "[WARN] $name goa-amount.js not live yet (HTTP $code) — deploy-landings.sh needed" fi done echo echo "=== result: pass=$pass fail=$fail ===" if [ "$fail" -gt 0 ]; then exit 1 fi exit 0