#!/bin/sh set -eu usage() { echo "usage: $0 [env-file]" >&2 exit 64 } [ "$#" -le 1 ] || usage script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) workspace_root=$(CDPATH= cd -- "$script_dir/.." && pwd) env_file=${1:-"$workspace_root/.env.ci"} if [ ! -f "$env_file" ]; then echo "missing integration environment file: $env_file" >&2 exit 66 fi env_file=$(CDPATH= cd -- "$(dirname -- "$env_file")" && pwd)/$(basename -- "$env_file") # .env.ci is generated by the sam_rebuild development Compose helper and is a # shell-compatible, credential-bearing local file. Never print its contents. set -a # shellcheck disable=SC1090 . "$env_file" set +a : "${POSTGRES_HOST:?POSTGRES_HOST is required in $env_file}" : "${POSTGRES_PORT:?POSTGRES_PORT is required in $env_file}" : "${POSTGRES_DB:?POSTGRES_DB is required in $env_file}" : "${POSTGRES_USER:?POSTGRES_USER is required in $env_file}" : "${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required in $env_file}" : "${REDIS_URL:?REDIS_URL is required in $env_file}" integration_schema=${CONDITIONAL_INTEGRATION_SCHEMA:-conditional_integration} scenario_schema=${SCENARIO_SEED_INTEGRATION_SCHEMA:-conditional_scenario_seed} for schema in "$integration_schema" "$scenario_schema"; do case "$schema" in ''|[!a-z_]*|*[!a-z0-9_]*) echo "integration schema must be a lowercase PostgreSQL identifier: $schema" >&2 exit 64 ;; esac done build_database_url() { SCHEMA_NAME=$1 node --input-type=module -e ' const required = [ "POSTGRES_HOST", "POSTGRES_PORT", "POSTGRES_DB", "POSTGRES_USER", "POSTGRES_PASSWORD", "SCHEMA_NAME", ]; for (const name of required) { if (!process.env[name]) { throw new Error(`missing ${name}`); } } const url = new URL("postgresql://localhost"); url.hostname = process.env.POSTGRES_HOST; url.port = process.env.POSTGRES_PORT; url.username = process.env.POSTGRES_USER; url.password = process.env.POSTGRES_PASSWORD; url.pathname = `/${process.env.POSTGRES_DB}`; url.searchParams.set("schema", process.env.SCHEMA_NAME); process.stdout.write(url.href); ' } run_marked_tests() { package_dir=$1 marker=$2 label=$3 test_files=$(cd "$workspace_root/$package_dir" && rg -l "$marker" test -g '*.test.ts' | sort) if [ -z "$test_files" ]; then echo "no $label tests found under $package_dir" >&2 exit 65 fi echo "running $label tests in $package_dir" ( cd "$workspace_root/$package_dir" printf '%s\n' "$test_files" | xargs -r pnpm exec vitest run --no-file-parallelism --maxWorkers=1 ) } cd "$workspace_root" pnpm install --frozen-lockfile pnpm --filter @sammo-ts/infra prisma:generate pnpm --filter @sammo-ts/common build pnpm --filter @sammo-ts/infra build database_url=$(build_database_url "$integration_schema") export POSTGRES_SCHEMA=$integration_schema export DATABASE_URL=$database_url export INPUT_EVENT_DATABASE_URL=$database_url export GENERAL_LIFECYCLE_DATABASE_URL=$database_url export TURN_DAEMON_LEASE_DATABASE_URL=$database_url export TURN_DIFFERENTIAL_DATABASE_URL=$database_url export RESERVED_TURN_DATABASE_URL=$database_url pnpm --filter @sammo-ts/infra prisma:db:push:game database_markers='INPUT_EVENT_DATABASE_URL|GENERAL_LIFECYCLE_DATABASE_URL|TURN_DAEMON_LEASE_DATABASE_URL|RESERVED_TURN_DATABASE_URL' run_marked_tests app/game-api "$database_markers" "PostgreSQL" run_marked_tests app/game-engine "$database_markers" "PostgreSQL" run_marked_tests tools/integration-tests \ 'TURN_DIFFERENTIAL_DATABASE_URL|INPUT_EVENT_DATABASE_URL' \ "PostgreSQL snapshot" if [ "${TURN_DIFFERENTIAL_REFERENCE:-}" = "1" ]; then live_sortie_schema=${LIVE_SORTIE_PERSISTENCE_SCHEMA:-conditional_live_sortie_persistence} case "$live_sortie_schema" in ''|[!a-z_]*|*[!a-z0-9_]*) echo "live sortie persistence schema must be a lowercase PostgreSQL identifier" >&2 exit 64 ;; esac live_sortie_database_url=$(build_database_url "$live_sortie_schema") export POSTGRES_SCHEMA=$live_sortie_schema export DATABASE_URL=$live_sortie_database_url export LIVE_SORTIE_PERSISTENCE_DATABASE_URL=$live_sortie_database_url pnpm --filter @sammo-ts/infra prisma:db:push:game run_marked_tests tools/integration-tests \ 'LIVE_SORTIE_PERSISTENCE_DATABASE_URL' \ "live sortie PostgreSQL persistence" export POSTGRES_SCHEMA=$integration_schema export DATABASE_URL=$database_url fi run_marked_tests app/game-api 'process\.env\.REDIS_URL' "Redis" scenario_database_url=$(build_database_url "$scenario_schema") ( export POSTGRES_SCHEMA=$scenario_schema export DATABASE_URL=$scenario_database_url pnpm --filter @sammo-ts/infra prisma:db:push:game cd "$workspace_root/app/game-engine" pnpm exec vitest run --no-file-parallelism --maxWorkers=1 test/scenarioSeeder.test.ts ) echo "conditional PostgreSQL and Redis integration tests passed"