mirror of
https://github.com/garrytan/gbrain.git
synced 2026-07-27 21:19:18 +00:00
Three consecutive waves (#1972 → #2015 → #2084) fixed pooler-teardown bugs verified only against one production deployment — CI had no transaction-mode pooler and could never see the class. Now it can: - docker-compose.ci.yml: `pgbouncer` service (transaction pooling) fronting postgres-1, mirroring the production split-pool topology (direct :5432 + pooled :6543). AUTH_TYPE=plain (pg16 SCRAM verifiers need the plaintext password in the userlist) + IGNORE_STARTUP_PARAMETERS for the statement_timeout/idle_in_transaction_session_timeout startup params gbrain's client sets (the Supabase pooler whitelists the same). - test/e2e/pgbouncer-teardown.test.ts: schema + fixture via the DIRECT url into a dedicated `gbrain_pgbouncer` database (never races shard TRUNCATEs), then spawns the real CLI against the POOLED url and asserts: exit 0, stdout intact (the #1959 truncation class), and NO "did not return within 10000ms — force-exiting" banner (pre-#2084 it printed on 100% of query-shaped ops on this topology). Class bound, not exact timing. Skips gracefully without GBRAIN_PGBOUNCER_URL. - scripts/ci-local.sh: threads GBRAIN_PGBOUNCER_URL + GBRAIN_PGBOUNCER_DIRECT_URL into all three e2e phases. Verified live: both tests green against pgbouncer 1.25.2 in transaction mode. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
154 lines
5.4 KiB
YAML
154 lines
5.4 KiB
YAML
# docker-compose.ci.yml
|
|
#
|
|
# Local CI gate with 4-way E2E sharding. Spins up 4 pgvector services + a bun
|
|
# runner that bind-mounts the repo. Used by `bun run ci:local` and
|
|
# `bun run ci:local:diff` (see scripts/ci-local.sh).
|
|
#
|
|
# All services are pulled as `image:` (no build) so `docker compose pull`
|
|
# refreshes everything. The bun version floats with `oven/bun:1` to track CI's
|
|
# `bun-version: latest`. Named volumes isolate the Linux container's deps from
|
|
# the host's darwin-arm64 deps and keep bun + postgres data warm across runs.
|
|
#
|
|
# Why 4 postgres services: bun's E2E suite shares one DB across 36 files and
|
|
# uses TRUNCATE CASCADE in setupDB(). Running files in parallel against ONE DB
|
|
# races (file A's TRUNCATE clobbers file B's fixture import). 4 separate DBs
|
|
# remove the race; we shard the file list 1/4..4/4 and run shards in parallel.
|
|
# Within a shard, files still run sequentially. Total wall-time on a 16-core
|
|
# host: ~6 min sequential -> ~1.5-2 min sharded.
|
|
#
|
|
# Postgres host ports default to 5434-5437 (avoid 5432 manual `gbrain-test-pg`
|
|
# and 5433 sibling-project conflicts). Override BASE port with GBRAIN_CI_PG_PORT;
|
|
# shards take BASE..BASE+3.
|
|
|
|
services:
|
|
postgres-1:
|
|
image: pgvector/pgvector:pg16
|
|
environment:
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres
|
|
POSTGRES_DB: gbrain_test
|
|
ports:
|
|
- "${GBRAIN_CI_PG_PORT:-5434}:5432"
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U postgres -d gbrain_test"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
volumes:
|
|
- gbrain-ci-pg-data-1:/var/lib/postgresql/data
|
|
|
|
postgres-2:
|
|
image: pgvector/pgvector:pg16
|
|
environment:
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres
|
|
POSTGRES_DB: gbrain_test
|
|
ports:
|
|
- "${GBRAIN_CI_PG_PORT_2:-5435}:5432"
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U postgres -d gbrain_test"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
volumes:
|
|
- gbrain-ci-pg-data-2:/var/lib/postgresql/data
|
|
|
|
postgres-3:
|
|
image: pgvector/pgvector:pg16
|
|
environment:
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres
|
|
POSTGRES_DB: gbrain_test
|
|
ports:
|
|
- "${GBRAIN_CI_PG_PORT_3:-5436}:5432"
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U postgres -d gbrain_test"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
volumes:
|
|
- gbrain-ci-pg-data-3:/var/lib/postgresql/data
|
|
|
|
postgres-4:
|
|
image: pgvector/pgvector:pg16
|
|
environment:
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres
|
|
POSTGRES_DB: gbrain_test
|
|
ports:
|
|
- "${GBRAIN_CI_PG_PORT_4:-5437}:5432"
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U postgres -d gbrain_test"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
volumes:
|
|
- gbrain-ci-pg-data-4:/var/lib/postgresql/data
|
|
|
|
# v0.43 (#2084 / eng-review TD1): PgBouncer in TRANSACTION pooling mode
|
|
# fronting postgres-1 — the production topology (Supabase direct :5432 +
|
|
# pooled :6543) behind three consecutive pooler-teardown waves
|
|
# (#1972 → #2015 → #2084) that CI could never reproduce.
|
|
# test/e2e/pgbouncer-teardown.test.ts uses a DEDICATED database
|
|
# (gbrain_pgbouncer) on postgres-1 so it never races shard 1's
|
|
# TRUNCATE-based fixtures; pgbouncer's wildcard [databases] section
|
|
# forwards any dbname to DB_HOST.
|
|
pgbouncer:
|
|
image: edoburu/pgbouncer:latest
|
|
environment:
|
|
DB_HOST: postgres-1
|
|
DB_PORT: "5432"
|
|
DB_USER: postgres
|
|
DB_PASSWORD: postgres
|
|
POOL_MODE: transaction
|
|
# plain (CI-only): pg16 stores SCRAM verifiers, and pgbouncer can only
|
|
# answer the server's SCRAM challenge when its userlist holds the
|
|
# PLAINTEXT password — an md5-hashed userlist fails with
|
|
# "server login failed: wrong password type".
|
|
AUTH_TYPE: plain
|
|
MAX_CLIENT_CONN: "200"
|
|
DEFAULT_POOL_SIZE: "10"
|
|
# gbrain's client sets statement_timeout + idle_in_transaction_session_timeout
|
|
# as startup parameters (db.ts buildConnectionParams); the Supabase pooler
|
|
# whitelists them, so this pooler must too or every connection is refused
|
|
# before the teardown path is even reached.
|
|
IGNORE_STARTUP_PARAMETERS: extra_float_digits,statement_timeout,idle_in_transaction_session_timeout,search_path
|
|
ports:
|
|
- "${GBRAIN_CI_PGBOUNCER_PORT:-6543}:5432"
|
|
depends_on:
|
|
postgres-1:
|
|
condition: service_healthy
|
|
|
|
runner:
|
|
image: oven/bun:1
|
|
working_dir: /app
|
|
depends_on:
|
|
postgres-1:
|
|
condition: service_healthy
|
|
postgres-2:
|
|
condition: service_healthy
|
|
postgres-3:
|
|
condition: service_healthy
|
|
postgres-4:
|
|
condition: service_healthy
|
|
pgbouncer:
|
|
condition: service_started
|
|
# No global DATABASE_URL — scripts/ci-local.sh sets per-shard URL via -e.
|
|
# Unit phase explicitly unsets DATABASE_URL so test/e2e/* gracefully skip.
|
|
volumes:
|
|
- .:/app
|
|
# Linux container's node_modules MUST be isolated from host darwin-arm64.
|
|
# Without this, container `bun install` stomps host node_modules and
|
|
# subsequent `bun test` on host fails with binary-incompat errors.
|
|
- gbrain-ci-node-modules:/app/node_modules
|
|
# Warm install cache across runs.
|
|
- gbrain-ci-bun-cache:/root/.bun/install/cache
|
|
|
|
volumes:
|
|
gbrain-ci-pg-data-1:
|
|
gbrain-ci-pg-data-2:
|
|
gbrain-ci-pg-data-3:
|
|
gbrain-ci-pg-data-4:
|
|
gbrain-ci-node-modules:
|
|
gbrain-ci-bun-cache:
|