feat: add dual-container compose configuration and test environment specifications

This commit is contained in:
Luis Gabriel Ramos Robles 2026-06-11 13:43:34 +00:00
parent 5f71688f20
commit 0ff507f67d
3 changed files with 149 additions and 14 deletions

66
docker-compose.yml Normal file
View file

@ -0,0 +1,66 @@
version: '3.8'
services:
# -----------------------------------------------------------------------------
# Production Application Instance
# -----------------------------------------------------------------------------
app-prod:
build:
context: .
dockerfile: Dockerfile
container_name: special-hotel-prod
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=${DATABASE_URL}
- NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL}
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
- N8N_WEBHOOK_URL=${N8N_WEBHOOK_URL}
- N8N_WEBHOOK_SECRET=${N8N_WEBHOOK_SECRET}
# Log tag prefix for syslog / journald, or environment labeling for standard output
logging:
driver: "json-file"
options:
tag: "app-prod/{{.Name}}"
max-size: "10m"
max-file: "3"
# -----------------------------------------------------------------------------
# Development & Testing Application Instance
# -----------------------------------------------------------------------------
app-dev:
build:
context: .
dockerfile: Dockerfile
container_name: special-hotel-dev
restart: no # Do not auto-restart if variables are missing or if it gracefully stops
ports:
- "127.0.0.1:3001:3000"
environment:
- NODE_ENV=development
- DATABASE_URL=${DATABASE_URL_DEV}
- TEST_DATABASE_URL=${TEST_DATABASE_URL}
- NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL_DEV}
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET_DEV}
- N8N_TEST_WEBHOOK_URL=${N8N_TEST_WEBHOOK_URL}
- N8N_WEBHOOK_SECRET=${N8N_WEBHOOK_SECRET_DEV}
# Commands run a pre-startup verification. If development-exclusive
# variables are missing, it logs a warning and exits with code 0 (graceful exit).
entrypoint: >
/bin/sh -c "
if [ -z \"$${TEST_DATABASE_URL}\" ] || [ -z \"$${N8N_TEST_WEBHOOK_URL}\" ]; then
echo '[DEV] Required development-exclusive variables (TEST_DATABASE_URL, N8N_TEST_WEBHOOK_URL) are missing.';
echo '[DEV] Gracefully shutting down the development service with exit code 0.';
exit 0;
fi;
echo '[DEV] Starting Next.js development server...';
exec npm run dev
"
logging:
driver: "json-file"
options:
tag: "app-dev/{{.Name}}"
max-size: "10m"
max-file: "3"

View file

@ -201,4 +201,34 @@ With `tea` configured, you can manage pull requests directly from the repository
* **Merge a PR**: `tea pulls merge <PR_NUMBER>`
* **Approve/Review a PR**: `tea pulls review <PR_NUMBER> --approve`
---
## 4. Testing Procedures & Webhook Testing Flow
Testing must occur in complete isolation from production data. We achieve this by splitting execution paths using dedicated test hooks in both Next.js and n8n.
### 4.1. Development & Test Variables Configuration
During test executions (such as running Jest, Cypress, or integration suites), the application uses the following development-exclusive variables:
* `TEST_DATABASE_URL`: Dedicated database connection URL for test schemas (e.g. `postgresql://.../special_hotel_test`). Migrations are run here independently.
* `N8N_TEST_WEBHOOK_URL`: The specific path n8n exposes for test triggers.
### 4.2. n8n Testing Webhook Routing
All calculations triggered by test suites route to n8n via `/webhook-test` path segments:
1. **Trigger**: Test suite invokes n8n via `POST ${process.env.N8N_TEST_WEBHOOK_URL}/calculate-commissions`.
2. **n8n Path Branching**:
- Within the n8n canvas, an **`IF` node** checks: `{{ $json.headers["x-nginx-original-uri"] || $json.path }}` contains `webhook-test`.
- **True**: The n8n workspace connects to the database utilizing `TEST_DATABASE_URL` credentials. It pulls test sales/goals data and pushes calculations back to the Next.js dev API.
- **False**: Connects to the main `DATABASE_URL` for production processing.
### 4.3. Running Integration Tests Locally
To run the full sandbox locally:
1. Spin up both databases: `docker compose up -d postgres-dev postgres-test`.
2. Run database migrations on the test database:
```bash
DATABASE_URL=$TEST_DATABASE_URL npx prisma migrate deploy
```
3. Run the Next.js development server (which connects to the dev database by default, but switches API routing to test endpoints under integration scripts).
4. Run testing script: `npm run test:integration`.

View file

@ -18,23 +18,30 @@
## 2. Decoupled Network & Environment Independence
The project is structured to run in any isolated Docker environment. All parameters are fed via environment variables:
The project is structured to run in any isolated Docker environment. All parameters are fed via environment variables to cleanly partition production and development configurations:
* `DATABASE_URL`: Connection string for PostgreSQL (e.g. `postgresql://user:pass@host:port/dbname`).
* `N8N_WEBHOOK_URL`: The entry point for the n8n workflow engine.
* `N8N_API_KEY`: Token to authorize callbacks from n8n to the Next.js API.
* `NEXTAUTH_SECRET`: Secret for securing JWT cookies.
### 2.1. Environment Variables
* **Core Variables (Both Env)**:
* `DATABASE_URL`: Connection string for the active database (Production or Development).
* `NEXT_PUBLIC_APP_URL`: The domain or local host path of the running application.
* `NEXTAUTH_SECRET`: Secret key for JWT session validation.
* **Development-Exclusive Test Variables**:
* `TEST_DATABASE_URL`: Connection string to the secondary sandbox/test database.
* `N8N_TEST_WEBHOOK_URL`: The n8n testing webhook entry point. Used by development services and test runners.
* `N8N_WEBHOOK_SECRET`: Token to authorize and verify n8n webhook payload signatures locally.
### Component Interaction:
### 2.2. Component Interaction:
```mermaid
graph TD
User([User Client]) -->|HTTPS| WebApp[Next.js App Router]
subgraph Isolated Network
WebApp -->|Prisma Client| DB[(PostgreSQL)]
WebApp -->|HTTP POST Webhook| n8n[n8n Workflow Engine]
WebApp -->|Prisma Client| DB[(PostgreSQL Main)]
WebApp -.->|Prisma Client - Test Env| DBTest[(PostgreSQL Test)]
WebApp -->|HTTP POST Webhook /webhook-test| n8n[n8n Workflow Engine]
n8n -->|IF Webhook Path Match| DBTest
n8n -->|Else| DB
n8n -->|HTTP POST Callback| WebApp
n8n -->|Interact| LLM[AI Model / Provider]
end
```
@ -190,11 +197,21 @@ By offloading calculations and integrations to n8n, we achieve a highly visual,
### 4.2. Settlement Calculation Workflow
1. **Trigger**: Next.js calls n8n to execute the calculation for period `YYYY-MM`.
2. **n8n Processing**:
- Pulls active plans, individual goals, and actual sales from the Next.js API.
- Evaluates the mathematical formulas.
- Evaluates rule scales and applies caps.
- Generates notifications (via email or push notifications) using n8n integrations.
3. **Response**: Updates database records via the Next.js API and completes the task.
- Pulls active plans, individual goals, and actual sales from the Next.js API.
- Evaluates the mathematical formulas.
- Evaluates rule scales and applies caps.
- Generates notifications (via email or push notifications) using n8n integrations.
3. **Response**: Updates database records via the Next.js API and completes the task.
### 4.3. Test Webhook Branching & Database Isolation in n8n
To ensure complete isolation of production data, all n8n workflows must follow a strict testing branch architecture:
1. **Webhook Entry Node**: n8n listens on two webhook path variants:
- Production calls hit: `/webhook/calculate-commissions`
- Test suite calls hit: `/webhook-test/calculate-commissions`
2. **Conditional Path Routing**:
- An `IF` node immediately checks if the webhook request path contains `webhook-test`.
- **True (Test Mode)**: The workflow overrides its database credential node configurations to connect to `TEST_DATABASE_URL` (the secondary test sandbox database) and makes API callbacks back to the Next.js test instance.
- **False (Prod Mode)**: The workflow executes against the main `DATABASE_URL` and interacts with the production Next.js instance.
---
@ -211,3 +228,25 @@ We define role-based access restrictions as follows:
| **Analista Financiero** | Reviews calculations. Exports consolidated PDF/Excel reports. | Cannot approve. |
| **Consulta** | Read-only. | No mutations allowed. |
| **Colaborador** | Consults own history & dashboard. | Restricted to `user_id`. |
---
## 6. Dual-Environment Docker Deployment Model
We design the containerized architecture to run two distinct instances of the application concurrently from the same codebase, ensuring clean division.
### 6.1. Service Configurations
* **Production Container (`app-prod`)**:
* **Network Port**: Exposed on port `3000` (mapped via Caddy to `special-hotel.yourdomain.com`).
* **Database**: Bound to the production `DATABASE_URL`.
* **Logs**: Prefixed with `[PROD]` inside the container engine.
* **Development Container (`app-dev`)**:
* **Network Port**: Exposed on port `3001` (mapped via Caddy to `special-hotel-dev.yourdomain.com`).
* **Database**: Bound to `TEST_DATABASE_URL` (acting as its main `DATABASE_URL` for test isolated migrations).
* **Logs**: Prefixed with `[DEV]` for easy debugging contrast.
### 6.2. Graceful Dev Failure Model
The development instance utilizes a validation startup hook. If any development-exclusive environment variables (like `TEST_DATABASE_URL`) are omitted:
1. The `app-dev` container logs a clear notification: `[DEV] Missing required development variables. Gracefully shutting down development service.`
2. The entrypoint script exits with **exit code 0**.
3. Docker or the compose orchestrator registers the container as cleanly stopped (not crashed). The production stack is completely unaffected, avoiding restart-loop penalties or deployment failures.