# Stack efímero para pruebas E2E (Playwright) en CI. # Levantado por Jenkinsfile (stage "E2E (Playwright)") ANTES del deploy a dev, # para validar la imagen recién buildeada contra una DB limpia y servicios aislados. # # Diferencias clave vs docker-compose.prod.yml: # - Sin volúmenes persistidos (todo se descarta en `down -v`). # - Sin `container_name` ni `restart` (efímero, COMPOSE_PROJECT_NAME aísla los nombres). # - Sin `celery_worker` / `celery_beat` (no se ejercitan en los specs actuales). # - Imágenes vía env vars: la del frontend se rebuildea localmente con # VITE_API_URL=http://localhost:8000/api/ (la prod tiene la URL de dev bakeada). # - Puertos fijos: frontend 5173 / backend 8000 (URIs ya registradas en Workspace). # # Variables requeridas en el entorno al invocar docker compose: # E2E_BACKEND_IMAGE — imagen del backend recién pusheada a Harbor # E2E_FRONTEND_IMAGE — imagen temporal del frontend con VITE_API_URL=localhost services: postgres-a76: image: postgres:18-alpine environment: POSTGRES_DB: anexo76_core POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_INITDB_ARGS: "--encoding=UTF8" networks: - e2e-net healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d anexo76_core || exit 1"] interval: 5s timeout: 3s retries: 10 start_period: 20s # Postgres 18+ requiere mount en /var/lib/postgresql (padre), no en /data. # Ver https://github.com/docker-library/postgres/pull/1259 — la imagen detecta # el mount viejo como "unused" y aborta el arranque. tmpfs: - /var/lib/postgresql minio: image: minio/minio:RELEASE.2025-09-07T16-13-09Z command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: minioadmin networks: - e2e-net healthcheck: test: ["CMD-SHELL", "curl -f http://127.0.0.1:9000/minio/health/live || exit 1"] interval: 10s timeout: 5s retries: 5 start_period: 15s tmpfs: - /data valkey: image: valkey/valkey:7.2 networks: - e2e-net backend: image: ${E2E_BACKEND_IMAGE} environment: - DEBUG=False - ENVIRONMENT=e2e - PYTHONUNBUFFERED=1 - PYTHONDONTWRITEBYTECODE=1 - CORE_DB_HOST=postgres-a76 - CORE_DB_PORT=5432 - CORE_DB_NAME=anexo76_core - CORE_DB_USER=postgres - CORE_DB_PASSWORD=postgres # Keycloak — apunta a Workspace real; el cliente anexo76-frontend ya # tiene http://localhost:5173/auth/callback como redirect URI permitida. - KEYCLOAK_SERVER_URL=https://workspace.aduanasoft.com/kcauth - KEYCLOAK_REALM=master - KEYCLOAK_CLIENT_ID=anexo76-frontend - KEYCLOAK_CLIENT_SECRET=${KEYCLOAK_CLIENT_SECRET:-} - CORS_ORIGINS=http://localhost:5173 - VALKEY_URL=redis://valkey:6379/0 - HUB_URL=https://workspace.aduanasoft.com - APP_PUBLIC_URL=http://localhost:5173 # SITAR — proveedor del tipo de cambio (botón "Consultar DOF" del dialog # de ExchangeRateGuard). Sin estas vars el dialog nunca llena el input # y auth.setup.ts falla. Las credenciales se inyectan desde Jenkins. - SITAR_API_URL=${SITAR_API_URL:-} - SITAR_API_USER=${SITAR_API_USER:-} - SITAR_API_PASSWORD=${SITAR_API_PASSWORD:-} - CSV_IMPORT_STORAGE=minio - S3_ENDPOINT_URL=http://minio:9000 - S3_ACCESS_KEY=minioadmin - S3_SECRET_KEY=minioadmin - S3_BUCKET=anexo76 - S3_REGION=us-east-1 - S3_USE_SSL=false - S3_FILE_STORAGE=true ports: - "8000:8000" depends_on: postgres-a76: condition: service_healthy minio: condition: service_healthy networks: - e2e-net # Replica el comando de prod (gunicorn) para que el test ejerza el mismo runtime # que se desplegará. El CMD del Dockerfile usa uvicorn --reload (modo dev). command: - gunicorn - main:app - -k - uvicorn.workers.UvicornWorker - -w - "1" - -b - 0.0.0.0:8000 - --log-level - info - --forwarded-allow-ips - "*" healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8000/api/health || exit 1"] interval: 10s timeout: 5s retries: 10 start_period: 60s frontend: image: ${E2E_FRONTEND_IMAGE} environment: - NODE_ENV=production # VITE_API_URL ya está bakeada en E2E_FRONTEND_IMAGE; este valor solo sirve # para fallback server-side en frontend/src/lib/server/api.ts. - VITE_API_URL=http://localhost:8000/api/ - INTERNAL_API_URL=http://backend:8000/api/ - INTERNAL_HUB_URL=https://workspace.aduanasoft.com - HUB_URL=https://workspace.aduanasoft.com - VITE_HUB_URL=https://workspace.aduanasoft.com - VITE_KEYCLOAK_URL=https://workspace.aduanasoft.com/kcauth - VITE_KEYCLOAK_REALM=master - VITE_KEYCLOAK_CLIENT_ID=anexo76-frontend - KEYCLOAK_URL=https://workspace.aduanasoft.com/kcauth - KEYCLOAK_REALM=master - KEYCLOAK_CLIENT_ID=anexo76-frontend - KEYCLOAK_CLIENT_SECRET=${KEYCLOAK_CLIENT_SECRET:-} # ORIGIN controla url.origin y el flag secure de cookies — debe coincidir con la URL # registrada en Workspace para que el callback de Keycloak resuelva correctamente. - ORIGIN=http://localhost:5173 - SITE_URL=http://localhost:5173 ports: - "5173:5173" depends_on: backend: condition: service_healthy networks: - e2e-net healthcheck: test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:5173/ || exit 1"] interval: 10s timeout: 5s retries: 10 start_period: 30s networks: e2e-net: driver: bridge