mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
171 lines
6.7 KiB
YAML
171 lines
6.7 KiB
YAML
# EDR Freight — API integration stack (headless).
|
|
#
|
|
# Overlay on docker-compose.e2e.yaml. Same base services (postgres, minio,
|
|
# mocks, freight-api), except the payment microservice is REAL here instead of
|
|
# `payment-mock-e2e`, and only the bank gateways are stubbed:
|
|
#
|
|
# freight-api-it ──HTTP──> payment-api-it ──HTTP──> gateway-mock-it
|
|
# ^ │
|
|
# └────── RabbitMQ ───────┘ (outbox → payment.events → consumer)
|
|
#
|
|
# Its own compose project (`name:` below overrides the base) and its own host
|
|
# ports, so it can run side by side with the Cypress e2e stack.
|
|
#
|
|
# node integration/scripts/it.mjs up|test|down|logs
|
|
#
|
|
# Never start it with plain `docker compose -f docker-compose.it.yaml` — it is
|
|
# an OVERLAY and needs the base file first:
|
|
# docker compose -f docker-compose.e2e.yaml -f docker-compose.it.yaml ...
|
|
name: edr-freight-it
|
|
|
|
services:
|
|
# Outbox transport. The payment API publishes payment.succeeded/failed here
|
|
# and freight consumes it — the production path. Copied from the passenger
|
|
# harness (e2e/docker-compose.yml).
|
|
rabbitmq-it:
|
|
image: rabbitmq:3-management
|
|
environment:
|
|
RABBITMQ_DEFAULT_USER: edr
|
|
RABBITMQ_DEFAULT_PASS: edr_secret
|
|
RABBITMQ_DEFAULT_VHOST: payment
|
|
ports:
|
|
- "${IT_RABBIT_PORT:-5772}:5672"
|
|
- "${IT_RABBIT_UI_PORT:-15772}:15672"
|
|
healthcheck:
|
|
test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 20
|
|
|
|
# Stand-in for every bank/wallet gateway the payment API talks to, plus a
|
|
# control plane the tests drive (force a provider to fail/hang, fire a
|
|
# correctly-signed webhook, read back what was called). See
|
|
# integration/gateway-mock/server.js.
|
|
gateway-mock-it:
|
|
image: node:20-alpine
|
|
volumes:
|
|
- ./integration/gateway-mock:/app:ro
|
|
working_dir: /app
|
|
environment:
|
|
PORT: "4600"
|
|
# Same secrets the payment API gets — so webhooks the mock signs pass the
|
|
# API's REAL signature verification instead of bypassing it.
|
|
CBE_SECRET_KEY: it-cbe-secret
|
|
CBE_MERCHANT_ID: it-cbe-merchant
|
|
PAYMENT_API_URL: http://payment-api-it:3003
|
|
command: ["node", "server.js"]
|
|
ports:
|
|
- "${IT_GATEWAY_PORT:-4600}:4600"
|
|
healthcheck:
|
|
test:
|
|
[
|
|
"CMD",
|
|
"node",
|
|
"-e",
|
|
"fetch('http://localhost:4600/__control/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
|
|
]
|
|
interval: 3s
|
|
timeout: 3s
|
|
retries: 10
|
|
|
|
payment-api-it:
|
|
build:
|
|
context: .
|
|
dockerfile: apps/edr-payment-api/Dockerfile
|
|
secrets:
|
|
- npmrc
|
|
depends_on:
|
|
postgres-freight-e2e:
|
|
condition: service_healthy
|
|
rabbitmq-it:
|
|
condition: service_healthy
|
|
gateway-mock-it:
|
|
condition: service_healthy
|
|
environment:
|
|
PORT: "3003"
|
|
NODE_ENV: test
|
|
# Payment tables live in their own schema of the same throwaway DB;
|
|
# main.ts ensurePaymentSchema() creates it, migrationsRun does the rest.
|
|
DB_HOST: postgres-freight-e2e
|
|
DB_PORT: "5432"
|
|
DB_USER: edr_e2e
|
|
DB_PASSWORD: edr_e2e
|
|
DB_NAME: edr_freight_e2e
|
|
DB_SCHEMA: edr_payment
|
|
# Same token freight already uses in the base stack.
|
|
SERVICE_AUTH_TOKEN: e2e-service-token
|
|
PUBLISHER_TRANSPORT: rabbitmq
|
|
PAYMENT_RABBITMQ_URL: amqp://edr:edr_secret@rabbitmq-it:5672/payment
|
|
# HTTP fallback targets (only used with PUBLISHER_TRANSPORT=http).
|
|
PAYMENT_NOTIFY_FREIGHT_URL: http://freight-api-e2e:3001/api/internal/payments/mark-paid
|
|
# Fast relay + sweep so retry/reconciliation are observable inside a test
|
|
# rather than a minute later.
|
|
OUTBOX_RELAY_INTERVAL_MS: "1000"
|
|
RECONCILE_STALE_AFTER_MS: "5000"
|
|
# Every gateway points at the one mock. Paths are per-provider prefixes.
|
|
CBE_BASE_URL: http://gateway-mock-it:4600/cbe-birr
|
|
CBE_MERCHANT_ID: it-cbe-merchant
|
|
CBE_SECRET_KEY: it-cbe-secret
|
|
CBE_NOTIFY_URL: http://payment-api-it:3003/webhooks/cbe-birr
|
|
CBE_RETURN_URL: http://localhost/return
|
|
TELEBIRR_BASE_URL: http://gateway-mock-it:4600/telebirr
|
|
TELEBIRR_WEB_BASE_URL: http://gateway-mock-it:4600/telebirr/web
|
|
TELEBIRR_FABRIC_APP_ID: it-fabric
|
|
TELEBIRR_APP_SECRET: it-secret
|
|
TELEBIRR_MERCHANT_APP_ID: it-merchant-app
|
|
TELEBIRR_MERCHANT_CODE: "999999"
|
|
TELEBIRR_NOTIFY_URL: http://payment-api-it:3003/webhooks/telebirr
|
|
# Telebirr PSS-signs every request object — a throwaway key generated per
|
|
# launch by it.mjs (nothing key-shaped lives in git).
|
|
TELEBIRR_PRIVATE_KEY: ${IT_TELEBIRR_PRIVATE_KEY}
|
|
EBIRR_BASE_URL: http://gateway-mock-it:4600/ebirr
|
|
DMONEY_BASE_URL: http://gateway-mock-it:4600/dmoney
|
|
CARD_BASE_URL: http://gateway-mock-it:4600/card
|
|
WAAFI_BASE_URL: http://gateway-mock-it:4600/waafi
|
|
CAC_BASE_URL: http://gateway-mock-it:4600/cac
|
|
CAC_USERNAME: it-cac
|
|
CAC_PASSWORD: it-cac
|
|
CAC_APP_KEY: it-cac-key
|
|
CAC_API_KEY: it-cac-api
|
|
CAC_COMPANY_SERVICES_ID: "1"
|
|
# Inbound CBE Unified Bill — we are the biller; bill-query hops back into
|
|
# the freight API, so this direction runs real code on both sides.
|
|
CBE_BILL_ENABLED: "true"
|
|
CBE_BILL_CLIENT_ID: it-cbe-bill
|
|
CBE_BILL_CLIENT_SECRET: it-cbe-bill-secret
|
|
CBE_BILL_JWT_SECRET: it-cbe-bill-jwt
|
|
FREIGHT_API_BASE_URL: http://freight-api-e2e:3001/api
|
|
ports:
|
|
- "${IT_PAYMENT_PORT:-3113}:3003"
|
|
healthcheck:
|
|
test:
|
|
[
|
|
"CMD",
|
|
"node",
|
|
"-e",
|
|
"fetch('http://localhost:3003/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
|
|
]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 12
|
|
start_period: 40s
|
|
|
|
# Base-stack service, re-pointed at the real payment API.
|
|
freight-api-e2e:
|
|
depends_on:
|
|
payment-api-it:
|
|
condition: service_healthy
|
|
environment:
|
|
PAYMENT_API_URL: http://payment-api-it:3003
|
|
# Freight's payment module skips RabbitMQModule entirely when this is
|
|
# unset (payment.module.ts) — without it, outbox events never arrive.
|
|
PAYMENT_RABBITMQ_URL: amqp://edr:edr_secret@rabbitmq-it:5672/payment
|
|
# RABBITMQ_ENABLED stays "false" (base stack) — it only gates the SMS/email
|
|
# clients, which must remain off. The payment consumer is wired by
|
|
# PAYMENT_RABBITMQ_URL alone.
|
|
# Drain tail on every pay window. Production defaults to 5 minutes; a
|
|
# reservation here lives ~60s, so 5 would push every natural expiry past
|
|
# the suite's 180s timeouts. One minute keeps the tail real and observable
|
|
# (src/expired-invoice-late-settle.it.ts asserts both sides of it).
|
|
FREIGHT_PAYMENT_DRAIN_MINUTES: "1"
|