Run pinned Endoleap headless runtime against real HTTP and PostgreSQL in CI
Foundry Go checks / check (push) Failing after 4m1s
Foundry Go checks / check (pull_request) Failing after 4m15s

This commit is contained in:
2026-11-09 13:45:40 +08:00
parent 9cf6e4cedf
commit 6d1a5b5c83
3 changed files with 113 additions and 2 deletions
+13 -2
View File
@@ -69,8 +69,19 @@ jobs:
print("Negative control result:", control if control in known else "unclassified")
sys.exit("Slack client preflight could not verify the configured credentials")
PYSLACK
- name: Verify schema migration in an isolated database
run: bash deploy/check-schema.sh
- name: Fetch pinned headless HTTP integration client
env:
HEADLESS_CLIENT_REVISION: 3c5e67c03d944828d0c2e51ecadb4d2dac1c9765
run: |
set -eu
mkdir -p .headless-client
curl --fail --silent --show-error --location \
"https://gitea.entroia.com/Zayden-Jung/Endoleap/archive/$HEADLESS_CLIENT_REVISION.tar.gz" \
| tar -xz --strip-components=1 -C .headless-client
test -f .headless-client/tests/headless/foundry.integration.mjs
printf 'Pinned Endoleap client: %s\n' "$HEADLESS_CLIENT_REVISION"
- name: Verify schema migration and real headless HTTP client in an isolated database
run: HEADLESS_CLIENT_SOURCE="$PWD/.headless-client" bash deploy/check-schema.sh
- name: Smoke test HTTP routes
env:
PUBLIC_ORIGIN: https://api.example.com
+15
View File
@@ -78,3 +78,18 @@ for package in platform auth research; do
-e RESEARCH_TEST_DATABASE_URL=postgres://foundry_research_fixture@127.0.0.1:5432/postgres?sslmode=disable \
--entrypoint /opt/integration-tests postgres:17-alpine -test.v
done
# Run the actual pinned Endoleap runtime against this build's authenticated HTTP
# routes and the same disposable database. Only this remote container needs Node.
if [[ -n "${HEADLESS_CLIENT_SOURCE:-}" ]]; then
test -f "$HEADLESS_CLIENT_SOURCE/tests/headless/foundry.integration.mjs"
docker run --rm --network "container:$container" --user 1000:1000 \
--read-only --cap-drop ALL --security-opt no-new-privileges \
--tmpfs /tmp:rw,nosuid,nodev,noexec,size=32m,mode=1777 \
--mount "type=bind,source=$(pwd)/bin/platform-tests,target=/opt/integration-tests,readonly" \
--mount "type=bind,source=$HEADLESS_CLIENT_SOURCE,target=/opt/headless-client,readonly" \
-e PLATFORM_TEST_DATABASE_URL=postgres://foundry_fixture@127.0.0.1:5432/postgres?sslmode=disable \
-e FOUNDRY_HEADLESS_SOURCE=/opt/headless-client \
--entrypoint /opt/integration-tests node:24-bookworm-slim \
-test.v -test.run '^TestHeadlessClientHTTPIntegration$' -test.timeout 3m
fi
@@ -0,0 +1,85 @@
package platform
import (
"context"
"crypto/rand"
"crypto/sha256"
"database/sql"
"encoding/base64"
"encoding/hex"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"time"
)
// Runs the real Endoleap runtime against authenticated Foundry HTTP and PostgreSQL.
// This opt-in is enabled by the existing remote schema runner, never local builds.
func TestHeadlessClientHTTPIntegration(t *testing.T) {
source, dsn := os.Getenv("FOUNDRY_HEADLESS_SOURCE"), os.Getenv("PLATFORM_TEST_DATABASE_URL")
if source == "" {
t.Skip("requires remote headless checkout")
}
if dsn == "" {
t.Fatal("headless integration requires isolated PostgreSQL")
}
db, err := sql.Open("pgx", dsn)
if err != nil {
t.Fatal(err)
}
defer db.Close()
ctx := context.Background()
var entropy [12]byte
_, _ = rand.Read(entropy[:])
project := "headless-" + hex.EncodeToString(entropy[:])
defer func() {
for _, table := range []string{"canvas_model_operations", "canvas_model_identity_map", "canvas_model_requests", "canvas_model_projects", "canvas_asset_bindings", "canvas_subgraphs", "workspaces", "project_accounts"} {
_, _ = db.ExecContext(ctx, "DELETE FROM "+table+" WHERE project=$1", project)
}
}()
var account, workspace, root string
if err = db.QueryRowContext(ctx, `INSERT INTO project_accounts(project,id) VALUES($1,gen_random_uuid()) RETURNING id::text`, project).Scan(&account); err != nil {
t.Fatal(err)
}
var tokenBytes [32]byte
_, _ = rand.Read(tokenBytes[:])
token := base64.RawURLEncoding.EncodeToString(tokenBytes[:])
hash := sha256.Sum256([]byte(token))
if _, err = db.ExecContext(ctx, `INSERT INTO project_sessions(token_hash,project,account_id,expires_at) VALUES($1,$2,$3,now()+interval '1 hour')`, base64.RawURLEncoding.EncodeToString(hash[:]), project, account); err != nil {
t.Fatal(err)
}
if err = db.QueryRowContext(ctx, `INSERT INTO workspaces(project,name,owner_id) VALUES($1,'Headless integration',$2) RETURNING id::text`, project, account).Scan(&workspace); err != nil {
t.Fatal(err)
}
if _, err = db.ExecContext(ctx, `INSERT INTO workspace_members(project,workspace_id,account_id,role) VALUES($1,$2,$3,'admin')`, project, workspace, account); err != nil {
t.Fatal(err)
}
legacy := json.RawMessage(`{"schema_version":1,"nodes":[` + modelLegacyFrame + `,{"id":"a","type":"plainText","position":{"x":150,"y":260},"width":240,"height":72,"data":{"kind":"plain-text","title":"a","text":"preserved","frameId":"f"}}],"edges":[],"viewport":{"x":0,"y":0,"zoom":1}}`)
if err = db.QueryRowContext(ctx, `INSERT INTO materials(project,workspace_id,kind,title,created_by,canvas_document) VALUES($1,$2,'board','Root',$3,$4) RETURNING id::text`, project, workspace, account, legacy).Scan(&root); err != nil {
t.Fatal(err)
}
mux := http.NewServeMux()
Register(mux, db, map[string]string{project: "https://app.example.com/auth/callback"}, "https://api.example.com", nil)
server := httptest.NewServer(mux)
defer server.Close()
commandContext, cancel := context.WithTimeout(ctx, 2*time.Minute)
defer cancel()
command := exec.CommandContext(commandContext, "node", filepath.Join(source, "tests/headless/foundry.integration.mjs"))
command.Env = append(os.Environ(), "FOUNDRY_HTTP_URL="+server.URL, "FOUNDRY_TEST_PROJECT="+project, "FOUNDRY_TEST_ACCOUNT="+account, "FOUNDRY_TEST_WORKSPACE="+workspace, "FOUNDRY_TEST_ROOT="+root, "FOUNDRY_TEST_TOKEN="+token)
output, err := command.CombinedOutput()
// The fixture token is ephemeral, but never print it even on client failures.
report := strings.ReplaceAll(string(output), token, "[fixture token redacted]")
if err != nil {
t.Fatalf("headless HTTP client failed: %v\n%s", err, report)
}
if !strings.Contains(report, `"status":"ok"`) {
t.Fatalf("headless HTTP client did not return success: %s", report)
}
t.Log(report)
}