ci / lint-test (push) Successful in 1m5s
setup-test-db.sh wrote .env.test once with the Postgres container's bridge IP baked in, and Docker reassigns those on recreation. The file rotted silently: its stored 172.22.0.18 belongs to **gitea** as of today, and an earlier drift had the suite pointing its TRUNCATE at **postgres-pantry** — which it would have wiped had the credentials happened to match. Root-cause fix: stop persisting a host at all. - scripts/resolve-test-db.sh re-derives the DSN from the live container and rewrites .env.test. Resolution order is TEST_DATABASE_URL, then the container's published host port, then the bridge IP. `docker port postgres-personal` reports 127.0.0.1:5432 since the 2026-08-17 PG17 migration, so loopback is what gets used here — and a loopback address cannot be reassigned to another container, which is the whole point. (Note this supersedes the smarthome CLAUDE.md's "postgres-personal publishes no host port"; that is now stale.) The bridge-IP fallback is kept for a host where the port is not published, and the script never prints the password. - Wired as `pretest:integration`, so npm runs it before every integration run. .env.test becomes a generated artifact rather than stored configuration. - setup-test-db.sh now only creates the database and copies the schema, then delegates to the resolver. - helpers.ts::assertTestDatabase stays and its message now points at the resolver rather than at `docker inspect`. It still earns its place: running vitest directly bypasses the pretest hook, and a stale .env.test would then still be read. Docs: CLAUDE.md gains a Testing section carrying this, the prisma-generate trap for a fresh checkout or worktree, and the frozen-clock rule for tests whose subject is defined relative to "now". AGENTS.md updated for the same, and for lint now being blocking.
67 lines
2.5 KiB
Bash
Executable File
67 lines
2.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# Resolve the integration-test DSN at run time and (re)write .env.test.
|
|
#
|
|
# Why this exists (#161): .env.test used to be written ONCE by
|
|
# setup-test-db.sh with the Postgres container's bridge IP baked in. Container
|
|
# IPs are reassigned on recreation, so the file rotted silently — by
|
|
# 2026-08-21 its 172.22.0.18 belonged to *gitea*, and an earlier drift had the
|
|
# suite pointing its TRUNCATE at postgres-pantry. It only failed safe because
|
|
# the credentials happened not to match.
|
|
#
|
|
# The fix is to stop persisting a host at all: this runs as `pretest:integration`,
|
|
# so the DSN is re-derived from the live container immediately before every run.
|
|
#
|
|
# Resolution order:
|
|
# 1. An explicit TEST_DATABASE_URL in the environment wins (CI, remote DB).
|
|
# 2. The container's published host port (`docker port`) — postgres-personal
|
|
# publishes 127.0.0.1:5432 since the 2026-08-17 PG17 migration. Preferred
|
|
# because a loopback address cannot be reassigned to another container.
|
|
# 3. The container's bridge IP, for a host where the port is not published.
|
|
#
|
|
# helpers.ts::assertTestDatabase is the backstop: it refuses to TRUNCATE
|
|
# anything whose current_database() is not `personal_test`.
|
|
|
|
set -euo pipefail
|
|
|
|
PG_CONTAINER=${PG_CONTAINER:-postgres-personal}
|
|
PG_USER=${PG_USER:-personal}
|
|
PG_PASS=${PG_PASS:-personalpassword123}
|
|
TEST_DB=${TEST_DB:-personal_test}
|
|
|
|
ENV_FILE="$(cd "$(dirname "$0")/.." && pwd)/.env.test"
|
|
|
|
if [ -n "${TEST_DATABASE_URL:-}" ]; then
|
|
DSN="$TEST_DATABASE_URL"
|
|
SOURCE="TEST_DATABASE_URL"
|
|
else
|
|
if ! docker inspect "$PG_CONTAINER" >/dev/null 2>&1; then
|
|
echo "ERROR: container '$PG_CONTAINER' not found. Start it, or set TEST_DATABASE_URL." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# `docker port` prints e.g. "127.0.0.1:5432" (possibly several lines).
|
|
PUBLISHED=$(docker port "$PG_CONTAINER" 5432/tcp 2>/dev/null | head -1 || true)
|
|
|
|
if [ -n "$PUBLISHED" ]; then
|
|
HOSTPORT="$PUBLISHED"
|
|
SOURCE="published port"
|
|
else
|
|
IP=$(docker inspect "$PG_CONTAINER" \
|
|
--format '{{range .NetworkSettings.Networks}}{{.IPAddress}} {{end}}' 2>/dev/null \
|
|
| tr ' ' '\n' | grep -v '^$' | head -1)
|
|
if [ -z "$IP" ]; then
|
|
echo "ERROR: '$PG_CONTAINER' has neither a published 5432 nor a bridge IP." >&2
|
|
exit 1
|
|
fi
|
|
HOSTPORT="$IP:5432"
|
|
SOURCE="bridge IP"
|
|
fi
|
|
|
|
DSN="postgresql://$PG_USER:$PG_PASS@$HOSTPORT/$TEST_DB"
|
|
fi
|
|
|
|
printf 'DATABASE_URL=%s\n' "$DSN" > "$ENV_FILE"
|
|
|
|
# Never print the password.
|
|
echo "resolve-test-db: ${DSN%%://*}://***@${DSN#*@} (via $SOURCE)"
|