Files
member-console/test/reset-test-db.sh
T
cgalo5758 b7447bea28 Isolate tests in per-purpose databases
Guard cluster-global CREATE ROLE in all five migration streams with
pg_roles checks so multiple databases can migrate in one cluster, and
tolerate still-referenced roles on Down.

Add test/reset-test-db.sh to drop and recreate member_console_test and
member_console_e2e per run, emit their DSNs from bootstrap, and add a
make test target that resets then runs the suite serialized; parallel
unit packages sharing one database still interfered even after the e2e
split.

Fix customdomain_db_test.go, stale since 0affda7 and previously passing
only through pollution. Bootstrap and the Makefile carry small forward
references to the compose-profile knob introduced next.

Archives the test-db-isolation change.
2026-08-01 04:13:57 -05:00

92 lines
3.2 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# test/reset-test-db.sh — return the test databases to a pristine state.
#
# Drops and recreates every database the Go test suites use, then migrates
# each one, so a run starts from exactly what the migration streams create.
# The application's own database (MC_DB_DSN) is never touched: it belongs to
# whatever `member-console start` is running, and keeping the two apart is
# the point of this script.
#
# Two test databases, not one: package tests use TEST_DATABASE_URL, while the
# in-process e2e suite (test/e2e/plan-management) uses E2E_DATABASE_URL,
# because it commits org-type defaults that package tests assert the absence
# of. The browser walkthroughs (test/e2e/operator-walkthroughs) drive the live
# app and stay on the app database.
#
# Migrating here is load-bearing, not a convenience: each test package calls
# db.RunMigrations itself, and goose takes no advisory lock, so a genuinely
# empty database would have a dozen parallel packages racing to create the
# same schemas. Pre-migrating leaves every one of those calls a no-op.
#
# Usage: ./test/reset-test-db.sh (or `make test`, which runs it first)
set -euo pipefail
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "$here/.." && pwd)"
env_file="$here/.env"
if [[ ! -f "$env_file" ]]; then
echo "error: $env_file not found. Run ./bootstrap-stack.sh first." >&2
exit 1
fi
set -a
# shellcheck source=/dev/null
source "$env_file"
set +a
# An .env generated before this script existed carries none of these keys.
# Fail loudly rather than falling back to a default, which would mean
# resetting the application's database.
for var in POSTGRES_ADMIN_DSN TEST_DATABASE_URL E2E_DATABASE_URL; do
if [[ -z "${!var:-}" ]]; then
cat >&2 <<EOF
error: $var is not set in $env_file.
This .env predates the test-database split. Regenerate it:
cd test && rm .env && ./bootstrap-stack.sh
Existing containers and volumes survive; only the env file is rewritten.
EOF
exit 1
fi
done
# Extract the database name from a DSN's path component.
db_name_from_dsn() {
local dsn="$1"
local path="${dsn#*://}" # strip scheme
path="${path#*/}" # strip credentials@host:port
printf '%s' "${path%%\?*}" # strip query string
}
reset_one() {
local dsn="$1" label="$2"
local name
name="$(db_name_from_dsn "$dsn")"
if [[ -z "$name" || "$name" == "member_console" ]]; then
echo "error: refusing to reset '${name:-<empty>}' — that is the application database." >&2
exit 1
fi
echo "Resetting ${label} database '${name}'..."
# WITH (FORCE) terminates sessions still attached from a previous run;
# without it a leftover connection makes the DROP wait indefinitely.
psql "$POSTGRES_ADMIN_DSN" -v ON_ERROR_STOP=1 --quiet <<SQL
DROP DATABASE IF EXISTS ${name} WITH (FORCE);
CREATE DATABASE ${name} OWNER member_console;
SQL
echo " migrating..."
(cd "$repo_root" && MC_DB_DSN="$dsn" go run . migrate up --config test/mc-config.yaml >/dev/null)
}
reset_one "$TEST_DATABASE_URL" "package-test"
reset_one "$E2E_DATABASE_URL" "e2e"
echo "Test databases are pristine. The application database is untouched."