# docker-compose.test.yml — ephemeral infra for testing # # Integration tests (infra only): # docker compose -f docker-compose.test.yml --profile init up -d # # E2E tests (full stack + browser): # docker compose -f docker-compose.test.yml --profile e2e up -d --build # cd e2e && npx nbb -cp src -m ajet-chat.e2e.runner services: postgres-test: image: postgres:16-alpine ports: - "5433:5432" environment: POSTGRES_DB: ajet_chat_test POSTGRES_USER: ajet POSTGRES_PASSWORD: ajet_test tmpfs: - /var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ajet -d ajet_chat_test"] interval: 3s timeout: 2s retries: 10 nats-test: image: nats:2.10-alpine ports: - "4223:4222" command: ["--js", "-m", "8222"] healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost:8222/healthz"] interval: 3s timeout: 2s retries: 10 minio-test: image: minio/minio:latest ports: - "9002:9000" environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: minioadmin command: server /data tmpfs: - /data healthcheck: test: ["CMD", "mc", "ready", "local"] interval: 3s timeout: 2s retries: 10 minio-test-init: profiles: ["init"] image: minio/mc:latest depends_on: minio-test: condition: service_healthy entrypoint: > /bin/sh -c " mc alias set local http://minio-test:9000 minioadmin minioadmin; mc mb --ignore-existing local/ajet-chat; " # -------------------------------------------------------------------------- # Gitea — self-contained OAuth provider for E2E tests # -------------------------------------------------------------------------- gitea-test: profiles: ["e2e"] image: gitea/gitea:1.22 ports: - "4080:3000" environment: - GITEA__database__DB_TYPE=sqlite3 - GITEA__security__INSTALL_LOCK=true - GITEA__server__ROOT_URL=http://localhost:4080 - GITEA__server__HTTP_PORT=3000 - GITEA__service__DISABLE_REGISTRATION=false - GITEA__service__REQUIRE_SIGNIN_VIEW=false - GITEA__oauth2__ENABLE=true tmpfs: - /data healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/v1/version"] interval: 3s timeout: 2s retries: 20 start_period: 10s gitea-test-init: profiles: ["e2e"] image: curlimages/curl:latest depends_on: gitea-test: condition: service_healthy entrypoint: /bin/sh command: - -c - | set -e GITEA=http://gitea-test:3000 echo "==> Creating Gitea admin user..." curl -sf -X POST "$$GITEA/api/v1/admin/users" \ -H "Content-Type: application/json" \ -u "gitea-admin:gitea-admin-pass" \ -d '{"username":"gitea-admin","password":"gitea-admin-pass","email":"admin@test.local","must_change_password":false,"login_name":"gitea-admin","source_id":0,"visibility":"public"}' \ || true # Gitea with INSTALL_LOCK=true uses the first registered user as admin. # Verify admin access, fall back to sign-up if needed: curl -sf -X POST "$$GITEA/api/v1/user/repos" \ -H "Content-Type: application/json" \ -u "gitea-admin:gitea-admin-pass" \ -d '{"name":"test"}' \ > /dev/null 2>&1 || { echo "==> Admin doesn't exist yet, creating via sign-up..." curl -sf -X POST "$$GITEA/user/sign_up" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "user_name=gitea-admin&password=gitea-admin-pass&retype=gitea-admin-pass&email=admin@test.local" \ || true sleep 2 } echo "==> Getting admin token..." TOKEN=$$(curl -sf -X POST "$$GITEA/api/v1/users/gitea-admin/tokens" \ -u "gitea-admin:gitea-admin-pass" \ -H "Content-Type: application/json" \ -d '{"name":"e2e-setup","scopes":["all"]}' | sed 's/.*"sha1":"//' | sed 's/".*//') echo "Token: $$TOKEN" echo "==> Creating test user A..." curl -sf -X POST "$$GITEA/api/v1/admin/users" \ -H "Content-Type: application/json" \ -H "Authorization: token $$TOKEN" \ -d '{"username":"testuser-a","password":"testpass-a","email":"testuser-a@test.local","must_change_password":false}' \ || true echo "==> Creating test user B..." curl -sf -X POST "$$GITEA/api/v1/admin/users" \ -H "Content-Type: application/json" \ -H "Authorization: token $$TOKEN" \ -d '{"username":"testuser-b","password":"testpass-b","email":"testuser-b@test.local","must_change_password":false}' \ || true echo "==> Gitea init complete! Users: gitea-admin, testuser-a, testuser-b" echo "==> OAuth app will be created by the nbb test runner via Gitea API" # -------------------------------------------------------------------------- # E2E profile — application service containers # -------------------------------------------------------------------------- auth-gw: profiles: ["e2e"] build: context: . dockerfile: auth-gw/Dockerfile ports: - "4000:3000" environment: AJET__DB__HOST: postgres-test AJET__DB__PORT: 5432 AJET__DB__DBNAME: ajet_chat_test AJET__DB__USER: ajet AJET__DB__PASSWORD: ajet_test AJET__SERVICES__API__HOST: api AJET__SERVICES__WEB_SM__HOST: web-sm AJET__SERVICES__TUI_SM__HOST: tui-sm AJET__SESSION__COOKIE_SECURE: "false" AJET__OAUTH__GITEA_SERVER_BASE_URL: "http://host.docker.internal:4080" extra_hosts: - "host.docker.internal:host-gateway" depends_on: postgres-test: condition: service_healthy api: condition: service_healthy web-sm: condition: service_healthy tui-sm: condition: service_healthy gitea-test-init: condition: service_completed_successfully healthcheck: test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"] interval: 5s timeout: 3s retries: 15 start_period: 20s api: profiles: ["e2e"] build: context: . dockerfile: api/Dockerfile ports: - "4001:3001" environment: AJET__DB__HOST: postgres-test AJET__DB__PORT: 5432 AJET__DB__DBNAME: ajet_chat_test AJET__DB__USER: ajet AJET__DB__PASSWORD: ajet_test AJET__NATS__URL: nats://nats-test:4222 AJET__MINIO__ENDPOINT: http://minio-test:9000 AJET__MINIO__ACCESS_KEY: minioadmin AJET__MINIO__SECRET_KEY: minioadmin depends_on: postgres-test: condition: service_healthy nats-test: condition: service_healthy minio-test: condition: service_healthy healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost:3001/api/health"] interval: 5s timeout: 3s retries: 15 start_period: 20s web-sm: profiles: ["e2e"] build: context: . dockerfile: web-sm/Dockerfile ports: - "4002:3002" environment: AJET__API__BASE_URL: http://api:3001 AJET__NATS__URL: nats://nats-test:4222 depends_on: nats-test: condition: service_healthy healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost:3002/web/health"] interval: 5s timeout: 3s retries: 15 start_period: 20s tui-sm: profiles: ["e2e"] build: context: . dockerfile: tui-sm/Dockerfile ports: - "4003:3003" environment: AJET__API__BASE_URL: http://api:3001 AJET__NATS__URL: nats://nats-test:4222 depends_on: nats-test: condition: service_healthy healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost:3003/tui/health"] interval: 5s timeout: 3s retries: 15 start_period: 20s test-runner: profiles: ["e2e-docker"] build: context: . dockerfile: e2e/Dockerfile environment: AJET_TEST_BASE_URL: http://auth-gw:3000 AJET_TEST_DB_HOST: postgres-test AJET_TEST_DB_PORT: 5432 AJET_TEST_DB_DBNAME: ajet_chat_test AJET_TEST_DB_USER: ajet AJET_TEST_DB_PASSWORD: ajet_test AJET_TEST_NATS_URL: nats://nats-test:4222 AJET_TEST_MINIO_ENDPOINT: http://minio-test:9000 AJET_TEST_MINIO_ACCESS_KEY: minioadmin AJET_TEST_MINIO_SECRET_KEY: minioadmin depends_on: auth-gw: condition: service_healthy