test(e2e): diagnostic burst on step-2 provisioning failure (CP #285)

Closes the molecule-core-side ask of controlplane #285. CP #289 already
landed migration 022 + the handler change exposing \`last_error\` in
/cp/admin/orgs responses. This makes the canary harness actually USE
that field — pre-fix the harness exited with just "Tenant provisioning
failed for <slug>" and forced operators to scrape CP server logs to
learn WHY.

The diagnostic burst dumps the matched org row from the LIST_JSON
already in scope (no extra HTTP call), pretty-printed and prefixed,
right before \`fail\`. Mirrors the TLS-readiness burst pattern from
PR #2107 at step 4. Includes a not-found fallback for DB-drift cases.

No redaction needed — adminOrgSummary is already ops-safe (id, slug,
name, plan, member_count, instance_status, last_error, timestamps;
no tokens, no encrypted fields).

Verification: smoke-tested both branches (org found with last_error +
slug-not-found fallback) with synthetic JSON; bash syntax OK; the only
shellcheck warning is pre-existing on line 93.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hongming Wang 2026-04-27 07:22:12 -07:00
parent 3d617ec421
commit 3c345f5674

View File

@ -186,7 +186,29 @@ print('')
fi
case "$STATUS" in
running) break ;;
failed) fail "Tenant provisioning failed for $SLUG" ;;
failed)
# Diagnostic burst: dump the org row so the operator sees
# `last_error` (CP migration 022 / handler #289 — issue #285).
# Pre-fix the harness only logged "Tenant provisioning failed",
# forcing whoever debugs canary to scrape CP server logs to
# learn WHY. Same shape as the TLS-readiness burst at step 4
# (PR #2107). Redacts nothing because /cp/admin/orgs already
# returns a narrow, ops-safe shape (id/slug/name/plan/
# member_count/instance_status/last_error/timestamps —
# no tokens, no encrypted fields).
log "── DIAGNOSTIC BURST (step 2 — tenant provisioning failed) ──"
echo "$LIST_JSON" | python3 -c "
import json, sys
d = json.load(sys.stdin)
for o in d.get('orgs', []):
if o.get('slug') == '$SLUG':
print(json.dumps(o, indent=2))
sys.exit(0)
print('(no org row found for slug=$SLUG — DB drift?)')
" 2>&1 | sed 's/^/ /'
log "── END DIAGNOSTIC ──"
fail "Tenant provisioning failed for $SLUG (see diagnostic above for last_error)"
;;
*) sleep 15 ;;
esac
done