name: formation-hub-e2e # Compose stack isolated for Playwright e2e tests. # Boot: docker compose -f docker-compose.e2e.yml up -d --wait # Teardown: docker compose -f docker-compose.e2e.yml down -v networks: e2e-internal: driver: bridge volumes: e2e-postgres-data: e2e-baserow-data: e2e-redis-data: services: # -------------------------------------------------------------------------- # Postgres 16 — DocAdenice (fork Docmost) database # -------------------------------------------------------------------------- e2e-postgres: image: postgres:16 environment: POSTGRES_DB: ${E2E_DOCMOST_DB_NAME:-docmost_e2e} POSTGRES_USER: ${E2E_DOCMOST_DB_USER:-docmost} POSTGRES_PASSWORD: ${E2E_DOCMOST_DB_PASSWORD:-docmost_e2e_password} volumes: - e2e-postgres-data:/var/lib/postgresql/data networks: - e2e-internal healthcheck: test: ["CMD-SHELL", "pg_isready -U ${E2E_DOCMOST_DB_USER:-docmost} -d ${E2E_DOCMOST_DB_NAME:-docmost_e2e}"] interval: 5s timeout: 3s retries: 15 start_period: 10s # -------------------------------------------------------------------------- # Redis 7 — cache + Redis Streams for bridge SSE events # -------------------------------------------------------------------------- e2e-redis: image: redis:7-alpine command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru volumes: - e2e-redis-data:/data networks: - e2e-internal healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 10 start_period: 5s # -------------------------------------------------------------------------- # Baserow — database backend (all-in-one image) # -------------------------------------------------------------------------- e2e-baserow: image: baserow/baserow:1.30.1 environment: BASEROW_PUBLIC_URL: http://localhost:8081 BASEROW_BACKEND_DEBUG: "false" BASEROW_EMAIL_SMTP: "" # Disable email verification for seeding BASEROW_DISABLE_ANONYMOUS_PUBLIC_VIEW_WS_CONNECTIONS: "false" ports: - "8081:80" volumes: - e2e-baserow-data:/baserow/data networks: - e2e-internal # Baserow all-in-one boots several internal services (caddy, backend, worker, frontend) # The health endpoint is served via the internal caddy proxy. healthcheck: test: ["CMD-SHELL", "wget --quiet --tries=1 --spider http://localhost:80/api/health/ || exit 1"] interval: 15s timeout: 10s retries: 20 start_period: 60s # -------------------------------------------------------------------------- # Bridge — custom Node service (R3.1.a + R3.1.b) # -------------------------------------------------------------------------- e2e-bridge: build: context: ./bridge dockerfile: Dockerfile environment: NODE_ENV: production PORT: 4000 LOG_LEVEL: ${E2E_LOG_LEVEL:-info} BASEROW_API_URL: http://e2e-baserow:80 BASEROW_API_TOKEN: ${E2E_BASEROW_API_TOKEN:-e2e_baserow_token_placeholder} DOCMOST_API_URL: http://e2e-docadenice-server:3000 REDIS_URL: redis://e2e-redis:6379 BASEROW_WEBHOOK_SECRET: ${E2E_BASEROW_WEBHOOK_SECRET:-e2e_webhook_secret_32_chars_minimum_x} BRIDGE_API_TOKENS: ${E2E_BRIDGE_API_TOKENS:-[{"token":"brg_e2e_admin","name":"e2e-admin","scopes":["admin:*"]}]} DOCMOST_APP_SECRET: ${E2E_DOCMOST_APP_SECRET:-e2e_docmost_app_secret_32chars_min_xx} DOCMOST_JWT_ISSUER: Docmost RATE_LIMIT_GLOBAL_MAX: "1000" RATE_LIMIT_MUTATION_MAX: "500" ports: - "4001:4000" depends_on: e2e-redis: condition: service_healthy e2e-baserow: condition: service_healthy networks: - e2e-internal healthcheck: test: ["CMD-SHELL", "wget --quiet --tries=1 --spider http://localhost:4000/api/health || exit 1"] interval: 10s timeout: 5s retries: 10 start_period: 20s # -------------------------------------------------------------------------- # DocAdenice server (Docmost fork — backend) # E2E uses the upstream Docmost image since the fork is local-only. # The fork's API surface that matters for e2e (login, pages, JWT) is # identical to upstream — the acadenice-specific features (RBAC claim, views) # are tested via the bridge endpoints directly. # -------------------------------------------------------------------------- e2e-docadenice-server: image: docmost/docmost:latest environment: APP_URL: ${E2E_DOCMOST_URL:-http://localhost:5173} APP_SECRET: ${E2E_DOCMOST_APP_SECRET:-e2e_docmost_app_secret_32chars_min_xx} DATABASE_URL: postgresql://${E2E_DOCMOST_DB_USER:-docmost}:${E2E_DOCMOST_DB_PASSWORD:-docmost_e2e_password}@e2e-postgres:5432/${E2E_DOCMOST_DB_NAME:-docmost_e2e} REDIS_URL: redis://e2e-redis:6379 STORAGE_DRIVER: local # Seed admin account on first boot FIRST_USER_EMAIL: ${E2E_ADMIN_EMAIL:-admin@acadenice-e2e.local} FIRST_USER_PASSWORD: ${E2E_ADMIN_PASSWORD:-E2eAdminPassword123!} FIRST_WORKSPACE_NAME: "E2E Workspace" ports: - "3001:3000" depends_on: e2e-postgres: condition: service_healthy e2e-redis: condition: service_healthy networks: - e2e-internal volumes: - type: tmpfs target: /app/data/storage healthcheck: test: ["CMD-SHELL", "wget --quiet --tries=1 --spider http://localhost:3000/api/health || exit 1"] interval: 10s timeout: 5s retries: 20 start_period: 45s # -------------------------------------------------------------------------- # DocAdenice client (Vite dev server, fork) # In e2e we run the Vite preview build so Playwright has a stable URL. # For local dev the fork is not containerized (convention). Here we use a # purpose-built image that bundles the client for e2e. See e2e/Dockerfile.client. # -------------------------------------------------------------------------- e2e-docadenice-client: build: context: ./docmost dockerfile: apps/client/Dockerfile.e2e environment: VITE_APP_URL: http://localhost:3001 VITE_BRIDGE_URL: http://localhost:4001 ports: - "5173:5173" depends_on: e2e-docadenice-server: condition: service_healthy networks: - e2e-internal healthcheck: test: ["CMD-SHELL", "wget --quiet --tries=1 --spider http://localhost:5173 || exit 1"] interval: 10s timeout: 5s retries: 15 start_period: 30s