Files
rfc-app/testing/ppe-deploy-and-test.sh
Ben Stull ba37da927a fix(§22.4a): scope RFCView entry-detail fetch to its collection (v0.52.1)
The §9 deployed-environment E2E harness (0.52.0), run against a PPE host
with per-collection-isolated content, surfaced a latent multi-collection
bug: RFCView computed the collection id from the route but called
getRFC(pid, slug) without it, so a named-collection entry was always
fetched via the project default-collection route — which 404s for an entry
that exists only in a named collection ("Error: Not found"; metadata panel
absent). Local/Tier-1 stacks masked it (same slug also reachable via the
default collection). Thread cid through all three getRFC call sites; re-run
the load effect on collection change.

Harness/test-infra (not in the deployed artifact):
- e2e: pre-record cookie consent via addInitScript (lib/fixtures.js) so the
  bottom-fixed consent banner can't intercept catalog row-select clicks on
  the slower deployed edge.
- testing/seed-ppe.sh: fail loudly on any non-2xx Gitea response (a
  swallowed 403 org-repo create had reached the deploy as a 502).
- testing/ppe-deploy-and-test.sh: seed via the Keychain admin token
  (write:organization needed to create the PPE repos); store the E2E secret
  newline-free; read EXPECT_VERSION from VERSION.

Patch bump 0.52.0 → 0.52.1; CHANGELOG updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 06:45:01 -07:00

101 lines
4.6 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# One-shot resume for the §9 PPE deployed-environment E2E stage.
#
# PRECONDITION: the operator has run the interactive Workspace reauth:
# gcloud auth login && gcloud auth application-default login
# (Only they can — the gcloud CLI creds expire under the Workspace session
# policy even when ADC is valid.)
#
# This script then runs the whole pipeline non-interactively:
# 1. read the bot token from Secret Manager (never echoed) and use it to
# create + seed the dedicated PPE registry + content repos;
# 2. ensure the E2E test-auth shared secret exists (generates one if not);
# 3. deploy rfc-app-ppe via flotilla-core (pins .rfc-app-version.ppe=0.52.0);
# 4. wait for /api/health to report the expected version, then for the
# reconciler to sync the seeded bdd collection into the cache;
# 5. run metadata.spec.js (SLICE-3/4/5) against the deployed PPE host.
#
# Idempotent: re-running re-seeds (RESEED=1 restores SLICE-4/5 preconditions),
# reuses the existing E2E secret, and redeploys.
REPO_ROOT="$HOME/git/wiggleverse.org/ben.stull/rfc-app"
FLOTILLA="$HOME/git/wiggleverse.org/wiggleverse/flotilla-core/.venv/bin/flotilla-core"
PPE_HOST="https://rfc-ppe.wiggleverse.org"
EXPECT_VERSION="$(cat "$REPO_ROOT/VERSION")"
BOT_SECRET_PROJECT="wiggleverse-ohm"
BOT_SECRET_ID="ohm-rfc-app-gitea-bot-token"
E2E_SECRET_PROJECT="rfc-app-ppe"
E2E_SECRET_ID="rfc-app-ppe-e2e-test-auth-secret"
E2E_EMAIL="e2e-owner@example.test"
export CLOUDSDK_ACTIVE_CONFIG_NAME="rfc-app-ppe"
echo "== 0. precheck gcloud reauth =="
if ! gcloud secrets list --project="$E2E_SECRET_PROJECT" --limit=1 >/dev/null 2>&1; then
echo "gcloud is not reauthed. Run: gcloud auth login && gcloud auth application-default login" >&2
exit 1
fi
echo "gcloud OK"
echo "== 1. create + seed PPE repos (Keychain admin token; never echoed) =="
# Seeding CREATES the two org repos (rfc-registry-ppe, rfc-app-ppe-content),
# which needs a write:organization-scoped token. The SM bot token is
# write:repository only (org create → 403), so use the operator's Keychain
# admin PAT (wgl-gitea-token-<host>, legacy fallback ohm-gitea-token). The
# token stays in the env var — never echoed (§6.3).
SEED_TOKEN="$(security find-generic-password -s "wgl-gitea-token-git.wiggleverse.org" -w 2>/dev/null \
|| security find-generic-password -s "ohm-gitea-token" -w 2>/dev/null)"
[ -n "$SEED_TOKEN" ] || { echo "no Keychain Gitea token found" >&2; exit 1; }
GITEA_TOKEN="$SEED_TOKEN" \
RESEED="${RESEED:-1}" \
bash "$REPO_ROOT/testing/seed-ppe.sh"
unset SEED_TOKEN GITEA_TOKEN
echo "== 2. ensure E2E test-auth secret exists =="
if gcloud secrets describe "$E2E_SECRET_ID" --project="$E2E_SECRET_PROJECT" >/dev/null 2>&1; then
echo "E2E secret already exists; ensuring binding"
"$FLOTILLA" secret bind rfc-app-ppe E2E_TEST_AUTH_SECRET "$E2E_SECRET_PROJECT/$E2E_SECRET_ID@latest"
else
echo "creating E2E secret (random, via stdin — bytes never echoed)"
# `printf %s "$(...)"` stores EXACTLY 64 hex bytes with NO trailing newline.
# A bare `openssl rand -hex 32 | ...` stores 65 bytes (the trailing \n),
# which then rode into the VM .env and made the server's secret differ from
# the runner's command-substitution-stripped value → /auth/test/login 404
# (compare_digest mismatch). Keep it newline-free.
printf '%s' "$(openssl rand -hex 32)" | "$FLOTILLA" secret set rfc-app-ppe E2E_TEST_AUTH_SECRET
fi
echo "== 3. deploy rfc-app-ppe =="
"$FLOTILLA" deploy rfc-app-ppe
echo "== 4a. verify /api/health reports $EXPECT_VERSION =="
ok=0
for _ in $(seq 1 24); do
body="$(curl -s "$PPE_HOST/api/health" || true)"
echo " health: $body"
if printf '%s' "$body" | grep -q "\"version\":\"$EXPECT_VERSION\""; then ok=1; break; fi
sleep 5
done
[ "$ok" = 1 ] || { echo "health never reported $EXPECT_VERSION" >&2; exit 1; }
echo "== 4b. wait for the seeded bdd collection to sync into the cache =="
ok=0
for _ in $(seq 1 40); do
body="$(curl -s "$PPE_HOST/api/projects/ohm/collections/bdd/rfcs" || true)"
n="$(printf '%s' "$body" | grep -o 'checkout-guest\|checkout-returning\|search-facets' | sort -u | wc -l | tr -d ' ')"
echo " synced entries: $n/3"
if [ "$n" = 3 ]; then ok=1; break; fi
sleep 6
done
[ "$ok" = 1 ] || { echo "bdd collection never synced 3 entries" >&2; exit 1; }
echo "== 5. run metadata.spec.js against PPE =="
E2E_SECRET="$(gcloud secrets versions access latest --secret="$E2E_SECRET_ID" --project="$E2E_SECRET_PROJECT")"
cd "$REPO_ROOT/e2e"
BASE_URL="$PPE_HOST" \
E2E_TEST_AUTH_SECRET="$E2E_SECRET" \
E2E_OWNER_EMAIL="$E2E_EMAIL" \
npx playwright test metadata.spec.js
echo "== DONE: PPE E2E complete =="