Skip to content

Add facilitator-server Postgres e2e CI pipeline#34

Merged
ponderingdemocritus merged 4 commits intomainfrom
ponderingdemocritus/create-pr
Feb 8, 2026
Merged

Add facilitator-server Postgres e2e CI pipeline#34
ponderingdemocritus merged 4 commits intomainfrom
ponderingdemocritus/create-pr

Conversation

@ponderingdemocritus
Copy link
Contributor

@ponderingdemocritus ponderingdemocritus commented Feb 7, 2026

This adds a dedicated facilitator-server e2e job in CI with a Postgres service.\nIt builds core + facilitator-server, starts the real server, exercises /verify, and asserts tracking rows persist in resource_call_records.\nIt also makes DB fallback behavior explicit in server startup so migration failures are visible.

Summary by CodeRabbit

  • New Features

    • In-memory tracking fallback allows the server to start and operate when database initialization fails.
    • Added an npm script to run end-to-end tests locally/CI.
  • Improvements

    • Clearer database migration failure messaging and optional fallback recovery.
    • Per-tracking error callbacks for improved diagnostics.
    • Normalization/validation of E2E private key inputs for consistent test behavior.
  • Tests & CI

    • Added robust end-to-end tests and a CI job to run them in pipeline.

@coderabbitai
Copy link

coderabbitai bot commented Feb 7, 2026

📝 Walkthrough

Walkthrough

Adds a CI job and Bun-based end-to-end tests for the facilitator-server; makes PostgreSQL optional at startup via TRACKING_ALLOW_IN_MEMORY_FALLBACK and updates tracking initialization to accept an onTrackingError callback. Adds key-normalization helpers and tests for E2E private keys.

Changes

Cohort / File(s) Summary
CI Configuration
\.github/workflows/ci.yml
Adds facilitator_e2e job that provisions PostgreSQL 16, builds core and facilitator-server with Bun, and runs E2E tests with DB, EVM, OTEL, and tracking env vars.
Package Script
examples/facilitator-server/package.json
Adds test:e2e script to run Bun-based E2E test entry.
E2E Tests & Helpers
examples/facilitator-server/tests/e2e-ci.ts, examples/facilitator-server/tests/e2e-env.ts, examples/facilitator-server/tests/e2e-env.test.ts
New orchestration test that launches the server, waits for Postgres and HTTP readiness, issues /verify, polls resource_call_records, and validates tracking. Adds private-key normalization helper and unit tests.
Server Startup / Tracking
examples/facilitator-server/src/index.ts
Introduces TRACKING_ALLOW_IN_MEMORY_FALLBACK to permit startup with in-memory tracking on DB/migration failure. Changes createTracking signature to accept { onTrackingError } and conditions startup/logging on DB availability.

Sequence Diagram

sequenceDiagram
    participant CI as CI Runner
    participant Server as Facilitator Server
    participant DB as PostgreSQL
    participant HTTP as HTTP Endpoint
    participant Track as Tracking System

    CI->>Server: spawn server (env: DATABASE_URL, PORT, TRACKING_ALLOW_IN_MEMORY_FALLBACK, OTEL, EVM_*)
    activate Server

    Server->>DB: attempt connection & run migrations
    activate DB
    alt migrations succeed
        DB-->>Server: ready
        Server->>Track: init PostgreSQL-backed tracking
    else migrations fail
        DB-->>Server: error
        Server->>Server: check TRACKING_ALLOW_IN_MEMORY_FALLBACK
        alt fallback enabled
            Server->>Track: init in-memory tracking
        else fallback disabled
            Server-->>CI: exit with error
        end
    end
    deactivate DB

    CI->>DB: poll DB readiness
    CI->>HTTP: poll /supported until 200
    CI->>HTTP: POST /verify with invalid payload
    HTTP-->>Server: request received
    Server->>Track: record request (path=/verify, status=400)
    Track->>DB: insert record (if PG-backed)
    DB-->>CI: query finds /verify row
    CI->>Server: terminate process
    deactivate Server
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hopped to CI with a tiny cheer,

Postgres or memory, the path draws near,
Bun spawns the server, tests knock on the door,
/verify leaves footprints the tracker stores,
A carrot for logs — the rabbit claps once more!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add facilitator-server Postgres e2e CI pipeline' accurately summarizes the main change: adding an end-to-end CI pipeline for the facilitator-server with PostgreSQL support.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ponderingdemocritus/create-pr

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
examples/facilitator-server/tests/e2e-ci.ts (2)

88-103: Consider failing fast if the server process exits unexpectedly.

If the spawned server crashes immediately (e.g., missing dependency, config error), waitForServer will spin for the full 30 seconds before timing out. You could race server.exited against the readiness poll to surface startup failures sooner.

Example approach
+    // Fail fast if the server process dies before becoming ready
+    const serverCrashed = server.exited.then((code) => {
+      if (code !== 0) throw new Error(`Server exited early with code ${code}`);
+    });
+
     await waitForDatabase(pool);
-    await waitForServer(baseUrl);
+    await Promise.race([waitForServer(baseUrl), serverCrashed]);

104-105: Bun-specific stream consumption pattern — document or guard.

new Response(server.stdout).text() relies on Bun's ReadableStream-backed stdout. This is fine since the project uses Bun as the test runner, but a brief comment would help future readers unfamiliar with this pattern.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@examples/facilitator-server/src/index.ts`:
- Around line 71-79: The current log under the condition where pgClient is falsy
but DATABASE_URL is set emits a confusing message about setting
TRACKING_ALLOW_IN_MEMORY_FALLBACK=true; update that console.log to clearly state
that in-memory tracking is active because TRACKING_ALLOW_IN_MEMORY_FALLBACK is
enabled (i.e., the explicit fallback was allowed). Locate the block checking
pgClient and DATABASE_URL and change the message for the case where DATABASE_URL
is truthy and pgClient is falsy to something like "Resource tracking: In-memory
(DB init failed; TRACKING_ALLOW_IN_MEMORY_FALLBACK=true enabled fallback)" so it
accurately reflects that TRACKING_ALLOW_IN_MEMORY_FALLBACK is already true.
🧹 Nitpick comments (2)
examples/facilitator-server/tests/e2e-ci.ts (2)

80-97: Verify node availability vs. using bun to run the server.

The server is spawned via ["node", "dist/index.js"] while the test itself runs under Bun. This works on GitHub Actions (ubuntu-latest ships with Node pre-installed), and aligns with the #!/usr/bin/env node shebang in the source. However, if anyone runs this test locally without Node installed (e.g., in a Bun-only setup), it will fail without a clear error message.

Consider documenting this dependency or falling back to bun run dist/index.js if Node isn't available — though this is low-priority since the test is clearly CI-oriented.


55-73: waitForRecord query will throw (not retry) on SQL errors.

Unlike waitForDatabase and waitForServer, waitForRecord does not wrap pool.query in a try/catch. If the resource_call_records table doesn't exist yet (e.g., a slow migration), the query will throw immediately instead of retrying. In practice this is unlikely since waitForServer already gates on server readiness (which implies migrations completed), but the inconsistency in error handling across the three waitFor* functions is worth noting.

Proposed fix for consistency
   while (Date.now() < deadline) {
-    const result = await pool.query<{ count: string }>(
-      `SELECT COUNT(*) AS count
-       FROM resource_call_records
-       WHERE path = '/verify' AND response_status = 400`
-    );
-
-    if (Number(result.rows[0]?.count ?? "0") > 0) {
-      return;
+    try {
+      const result = await pool.query<{ count: string }>(
+        `SELECT COUNT(*) AS count
+         FROM resource_call_records
+         WHERE path = '/verify' AND response_status = 400`
+      );
+
+      if (Number(result.rows[0]?.count ?? "0") > 0) {
+        return;
+      }
+    } catch {
+      // Table may not exist yet if migrations are still running.
     }
 
     await sleep(300);

Comment on lines +71 to 79
if (pgClient) {
console.log(`Resource tracking: PostgreSQL (Drizzle)`);
} else if (DATABASE_URL) {
console.log(
`Resource tracking: In-memory (DB init failed; set TRACKING_ALLOW_IN_MEMORY_FALLBACK=true to allow this explicitly)`
);
} else {
console.log(`Resource tracking: In-memory (set DATABASE_URL for persistence)`);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Misleading log message when in-memory fallback is active.

When execution reaches Line 73, TRACKING_ALLOW_IN_MEMORY_FALLBACK is necessarily true (otherwise the process would have exited at Line 48). The message telling the user to "set TRACKING_ALLOW_IN_MEMORY_FALLBACK=true to allow this explicitly" is confusing because they already did.

Proposed fix
 } else if (DATABASE_URL) {
   console.log(
-    `Resource tracking: In-memory (DB init failed; set TRACKING_ALLOW_IN_MEMORY_FALLBACK=true to allow this explicitly)`
+    `Resource tracking: In-memory (DB init failed; running with in-memory fallback)`
   );
 } else {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (pgClient) {
console.log(`Resource tracking: PostgreSQL (Drizzle)`);
} else if (DATABASE_URL) {
console.log(
`Resource tracking: In-memory (DB init failed; set TRACKING_ALLOW_IN_MEMORY_FALLBACK=true to allow this explicitly)`
);
} else {
console.log(`Resource tracking: In-memory (set DATABASE_URL for persistence)`);
}
if (pgClient) {
console.log(`Resource tracking: PostgreSQL (Drizzle)`);
} else if (DATABASE_URL) {
console.log(
`Resource tracking: In-memory (DB init failed; running with in-memory fallback)`
);
} else {
console.log(`Resource tracking: In-memory (set DATABASE_URL for persistence)`);
}
🤖 Prompt for AI Agents
In `@examples/facilitator-server/src/index.ts` around lines 71 - 79, The current
log under the condition where pgClient is falsy but DATABASE_URL is set emits a
confusing message about setting TRACKING_ALLOW_IN_MEMORY_FALLBACK=true; update
that console.log to clearly state that in-memory tracking is active because
TRACKING_ALLOW_IN_MEMORY_FALLBACK is enabled (i.e., the explicit fallback was
allowed). Locate the block checking pgClient and DATABASE_URL and change the
message for the case where DATABASE_URL is truthy and pgClient is falsy to
something like "Resource tracking: In-memory (DB init failed;
TRACKING_ALLOW_IN_MEMORY_FALLBACK=true enabled fallback)" so it accurately
reflects that TRACKING_ALLOW_IN_MEMORY_FALLBACK is already true.

@ponderingdemocritus ponderingdemocritus merged commit 6342226 into main Feb 8, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant