molecule-core/tests/e2e/_lib.sh
Hongming Wang f9803ec55e fix(e2e): comprehensive + activity_e2e + shared lib + CI smoke job
Follow-up to the test_api.sh fix. Same Phase 30.1 + 30.6 staleness
existed in the other E2E scripts; same pattern applied.

## New tests/e2e/_lib.sh
Shared bash helpers so future scripts don't reimplement:
- e2e_extract_token — parse auth_token from register response
- e2e_register       — register + echo token
- e2e_heartbeat      — heartbeat with bearer auth
- e2e_cleanup_all_workspaces — pre-test state reset

## test_comprehensive_e2e.sh (14 fail -> 0 fail)
Root cause was deeper than test_api.sh: the script creates workspaces
at Section 2 but doesn't register them until Section 3. In between,
the platform provisioner spawns the Docker container, whose main.py
calls /registry/register first and claims the single-issue token.
The script's later register gets no auth_token back.

Fix: register each workspace immediately after POST /workspaces,
beating the container to the token. Empirically 5/5 wins in a tight
loop. PM/Dev/QA tokens captured at creation time; bearer auth threaded
through all heartbeat/update-card/discover/peers calls.

Removed the duplicate register calls in Section 3/4 that followed
(tokens already captured).

Result: 53/68 -> 67/67 (one duplicate check dropped).

## test_activity_e2e.sh
Same pattern applied on faith. Script still SKIPs cleanly when no
online agent is present; when an agent IS online, it now re-registers
it to mint a fresh bearer token and threads Authorization: Bearer on
the 3 heartbeat calls.

## test_api.sh refactor
Now sources _lib.sh and uses the shared helpers. No behavior change,
still 62/62.

## .github/workflows/ci.yml — new e2e-api job
Spins up Postgres 16 + Redis 7 as GitHub Actions services, builds the
platform binary, runs it in background with DATABASE_URL/REDIS_URL,
polls /health for 30s, then runs tests/e2e/test_api.sh. On failure
dumps platform.log for triage. 10-min job timeout.

This is the watchdog that would have caught Phase 30.1 auth drift
the day it landed. Picks test_api.sh not test_comprehensive_e2e.sh
because the latter depends on Docker-in-Docker for container
provisioning which is heavier than a PR gate should carry.

## Verification
- bash tests/e2e/test_api.sh                -> 62/62
- bash tests/e2e/test_comprehensive_e2e.sh  -> 67/67
- bash tests/e2e/test_activity_e2e.sh       -> cleanly SKIPs (no agent)
- go build ./...                            -> clean
- .github/workflows/ci.yml                  -> valid YAML, new job added

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 17:08:45 -07:00

47 lines
1.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# Common E2E helpers. Source this from every tests/e2e/*.sh.
#
# Usage:
# source "$(dirname "$0")/_lib.sh"
# e2e_base="http://localhost:8080"
# e2e_cleanup_all_workspaces # call at top of script
# token=$(e2e_register "$ID" "$URL" "$CARD_JSON")
# # then use -H "Authorization: Bearer $token" on heartbeat/update-card
# Emit the auth_token from a /registry/register response. Prints empty
# string (not an error) when no token was issued so callers can still
# exercise the grandfather path.
e2e_extract_token() {
python3 -c "import sys,json; print(json.load(sys.stdin).get('auth_token',''))" 2>/dev/null || true
}
# Register a workspace and echo the bearer token on stdout.
# Args: $1 workspace_id $2 url $3 agent_card JSON
e2e_register() {
curl -s -X POST "$e2e_base/registry/register" \
-H "Content-Type: application/json" \
-d "{\"id\":\"$1\",\"url\":\"$2\",\"agent_card\":$3}" \
| e2e_extract_token
}
# Heartbeat with bearer auth.
# Args: $1 workspace_id $2 token $3 payload_json (without the id)
e2e_heartbeat() {
curl -s -X POST "$e2e_base/registry/heartbeat" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $2" \
-d "$3"
}
# Delete every workspace currently on the platform. Use at the top of a
# script so count-based assertions are reproducible across runs.
e2e_cleanup_all_workspaces() {
for _wid in $(curl -s "$e2e_base/workspaces" | python3 -c "import json,sys
try:
[print(w['id']) for w in json.load(sys.stdin)]
except Exception:
pass" 2>/dev/null); do
curl -s -X DELETE "$e2e_base/workspaces/$_wid?confirm=true" > /dev/null || true
done
}