docker-compose.ci.yml
Rama main · réplica de lectura del repositorio original.
# CI-only docker compose override — the sandbox E2E backend.
#
# Merged by .github/workflows/e2e-sandbox.yml:
# docker compose -f docker-compose.yml -f docker-compose.ci.yml \
# --env-file .env.production up -d --wait postgres go-api
#
# Do NOT use this on the prod VPS. docker-compose.yml is canonical; this
# file only ever loosens what prod deliberately keeps tight.
#
# SCOPE: postgres + go-api ONLY. next-app runs on the host under
# `next dev` (see the workflow for why), nginx and ws-server never start.
# This file used to carry overrides for `app` and `mongodb` — services
# that were retired from docker-compose.yml at the P9 cutover. Nothing
# noticed for months because no workflow ever merged the two files, and
# `docker compose config` had been failing outright with
# `service "app" has neither an image nor a build context specified`.
# So: no override here for a service CI does not start. An override
# nobody runs is an override nobody maintains.
services:
postgres:
# The sandbox fixtures run on the HOST, outside the compose network.
# e2e/fixtures/pg.ts seeds users / anime_cache / subscriptions over
# localhost:5432, and the base file publishes no port at all.
ports:
- "5432:5432"
go-api:
# `next dev` rewrites /api/:path* to http://localhost:8080
# (next-app/next.config.ts:25 — dev only; under NODE_ENV=production
# it returns [] because nginx owns that hop). That rewrite runs in
# the Next server process on the host, so :8080 has to be published.
ports:
- "8080:8080"
environment:
# storageState is minted once in globalSetup and reused by every
# sandbox worker. The prod default (15m) can expire mid-suite and
# produce "logged out" failures that look like auth regressions.
JWT_EXPIRES_IN: 2h
# Auth limiter is 10 attempts / 15 min per IP by default
# (cmd/server/main.go:335). auth.spec.ts alone does register +
# logout + login + two more logins, and retries replay all of it.
AUTH_RATELIMIT_MAX: "1000"
# 0 disables the global /api/* limiter (cmd/server/main.go:618).
# This is the 2026-06-05 detail-page incident in miniature: go-api
# meters per IP, but behind SSR every read arrives from ONE client
# address, so the bucket is shared by all traffic rather than by
# user. In prod that collapsed /anime/{id} into 429 → 500 and the
# fix was to move rate limiting to the Cloudflare edge. Here the
# single address is the runner, shared by three parallel Playwright
# workers plus every RSC fetch they trigger — leave the limiter on
# and tests fail for a reason unrelated to the code under test.
API_RATELIMIT_BURST: "0"
# .env.production carries real Gmail credentials on the VPS. CI
# generates a throwaway env file with these unset, but pin them
# empty so a locally-run sandbox suite can never send real mail to
# the `@animego.test` fixture addresses either. Empty creds select
# email.NoopSender (cmd/server/main.go:321); ForgotPassword still
# writes the reset token to Postgres before it attempts the send
# (auth/handlers.go:642), which is the only part the spec reads.
GMAIL_USER: ""
GMAIL_APP_PASSWORD: ""
# The image warm job sends every AniList image the database references
# to nginx's internal warm location. nginx never starts here, so there
# is nothing to warm and every pass would only fail to connect. Empty
# turns the job off.
IMAGE_WARM_BASE_URL: ""
# The variant warm job asks the same nginx's internal image location,
# for the same reason off here.
IMAGE_VARIANT_WARM_BASE_URL: ""