mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-10-14 17:54:42 +00:00
Ci cd/test runner (#268)
This commit is contained in:
@@ -11,6 +11,7 @@ The project uses Docker Compose to orchestrate multiple services:
|
||||
- Database migrations runner (DbUp)
|
||||
- Database seeder
|
||||
- .NET API
|
||||
- React Router website (SSR frontend)
|
||||
- Test runners
|
||||
|
||||
See the [deployment diagram](diagrams-out/deployment.svg) for visual
|
||||
@@ -39,6 +40,7 @@ sqlserver # SQL Server 2022 (port 1434)
|
||||
database.migrations # DbUp migrations
|
||||
database.seed # Seed initial data
|
||||
api.core # Web API (ports 8080, 8081)
|
||||
frontend # React Router website (port 3000)
|
||||
mailpit # Local dev SMTP server + UI (port 8025)
|
||||
seaweedfs # S3-compatible object storage (ports 8333, 8888, 9333, 23646)
|
||||
```
|
||||
@@ -51,6 +53,7 @@ docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml up -d
|
||||
|
||||
**Access**:
|
||||
|
||||
- Website: http://localhost:3000
|
||||
- API Swagger: http://localhost:8080/swagger
|
||||
- Health Check: http://localhost:8080/health
|
||||
- Mailpit UI: http://localhost:8025
|
||||
@@ -90,6 +93,7 @@ database.migrations # Fresh schema
|
||||
database.seed # Test data
|
||||
api.specs # Reqnroll BDD tests
|
||||
unit.tests # All Features.*.Tests unit test projects
|
||||
frontend.tests # Storybook Vitest + Playwright suites (own Playwright image)
|
||||
```
|
||||
|
||||
**Run Tests**:
|
||||
@@ -119,13 +123,16 @@ docker compose --env-file web/.env.test -f web/docker-compose.test.yaml down -v
|
||||
- Health checks enabled
|
||||
- Restart policies (unless-stopped)
|
||||
- Security hardening
|
||||
- Only `frontend` publishes a port to the host; `sqlserver` and `api.core`
|
||||
are reachable only from other containers on `prodnet`
|
||||
|
||||
**Services**:
|
||||
|
||||
```yaml
|
||||
sqlserver # Production SQL Server
|
||||
sqlserver # Production SQL Server (internal only)
|
||||
database.migrations # Schema updates only
|
||||
api.core # Production API
|
||||
api.core # Production API (internal only, no published ports)
|
||||
frontend # Production website (port 3000, the only public binding)
|
||||
```
|
||||
|
||||
**Deploy Production**:
|
||||
|
||||
@@ -20,7 +20,9 @@ Direct environment variable access via `Environment.GetEnvironmentVariable()`.
|
||||
### Frontend (`web/frontend`)
|
||||
|
||||
The active website reads runtime values from the server environment for its auth
|
||||
and API integration.
|
||||
and API integration. In Docker, the `frontend` service is wired into the same
|
||||
`web/.env.dev` / `.env.test` / `.env.prod` files as the backend; running it
|
||||
locally with `npm run dev` still reads from the shell environment.
|
||||
|
||||
### Docker
|
||||
|
||||
@@ -34,8 +36,9 @@ Environment-specific `.env` files loaded via `env_file:` in docker-compose.yaml:
|
||||
|
||||
`web/generate-env.sh` copies `.env.example` to a target file and replaces the
|
||||
secret-bearing values (`DB_PASSWORD`, `ACCESS_TOKEN_SECRET`,
|
||||
`REFRESH_TOKEN_SECRET`, `CONFIRMATION_TOKEN_SECRET`, `SMTP_USERNAME`,
|
||||
`SMTP_PASSWORD`, `SEAWEEDFS_ACCESS_KEY_ID`, `SEAWEEDFS_SECRET_ACCESS_KEY`)
|
||||
`REFRESH_TOKEN_SECRET`, `CONFIRMATION_TOKEN_SECRET`, `SESSION_SECRET`,
|
||||
`SMTP_USERNAME`, `SMTP_PASSWORD`, `SEAWEEDFS_ACCESS_KEY_ID`,
|
||||
`SEAWEEDFS_SECRET_ACCESS_KEY`)
|
||||
with freshly randomized ones via `openssl`. Non-secret values are left
|
||||
untouched. The output file is written with `600` permissions.
|
||||
|
||||
@@ -173,19 +176,26 @@ The active website does not use the old Next.js/Prisma environment model. Its
|
||||
core runtime variables are:
|
||||
|
||||
```bash
|
||||
API_BASE_URL=http://localhost:8080 # Base URL for the .NET API
|
||||
API_BASE_URL=http://api.core:8080 # Base URL for the .NET API (container DNS name in Docker)
|
||||
SESSION_SECRET=<generated-secret> # Cookie session signing secret
|
||||
NODE_ENV=development # Standard Node runtime mode
|
||||
PORT=3000 # Port the built server listens on
|
||||
```
|
||||
|
||||
The `frontend` Docker service hardcodes `API_BASE_URL` to `http://api.core:8080`
|
||||
(the backend's in-network service name) and `PORT` to `3000`; only
|
||||
`SESSION_SECRET` is sourced from the env file, and `NODE_ENV` is set per
|
||||
compose file (`development` in dev, `production` in prod).
|
||||
|
||||
### Frontend variable details
|
||||
|
||||
#### `API_BASE_URL`
|
||||
|
||||
- **Required**: Yes for local development
|
||||
- **Default in code**: `http://localhost:8080`
|
||||
- **Used by**: `web/frontend/app/lib/auth.server.ts`
|
||||
- **Purpose**: Routes website auth actions to the .NET API
|
||||
- **Used by**: `web/frontend/app/features/auth/auth.server.ts`,
|
||||
`web/frontend/app/features/breweries/breweries.server.ts`
|
||||
- **Purpose**: Routes website auth and API calls to the .NET API
|
||||
|
||||
#### `SESSION_SECRET`
|
||||
|
||||
@@ -200,6 +210,12 @@ NODE_ENV=development # Standard Node runtime mode
|
||||
- **Typical values**: `development`, `production`, `test`
|
||||
- **Purpose**: Controls secure cookie behavior and runtime mode
|
||||
|
||||
#### `PORT`
|
||||
|
||||
- **Required**: No
|
||||
- **Default**: `3000`
|
||||
- **Purpose**: Port the built server (`build/server/index.js`) binds to
|
||||
|
||||
### SMTP configuration (backend)
|
||||
|
||||
Read by `Infrastructure.Email/SmtpEmailProvider.cs` for sending confirmation and
|
||||
@@ -312,9 +328,10 @@ reference only and is not run as part of the active stack.
|
||||
| `SEAWEEDFS_ACCESS_KEY_ID` | ✓ | | ✓ | Yes | S3 access key |
|
||||
| `SEAWEEDFS_SECRET_ACCESS_KEY` | ✓ | | ✓ | Yes | S3 secret key |
|
||||
| `SEAWEEDFS_BUCKET` | ✓ | | ✓ | Yes | S3 bucket name |
|
||||
| `API_BASE_URL` | | ✓ | | Yes | Website-to-API base URL |
|
||||
| `SESSION_SECRET` | | ✓ | | Yes | Website session signing |
|
||||
| `NODE_ENV` | | ✓ | | No | Runtime mode |
|
||||
| `API_BASE_URL` | | ✓ | ✓ | Yes | Website-to-API base URL |
|
||||
| `SESSION_SECRET` | | ✓ | ✓ | Yes | Website session signing |
|
||||
| `NODE_ENV` | | ✓ | ✓ | No | Runtime mode |
|
||||
| `PORT` | | ✓ | ✓ | No | Frontend server port |
|
||||
| `CLEAR_DATABASE` | ✓ | | ✓ | No | Dev/test reset flag |
|
||||
| `ASPNETCORE_ENVIRONMENT` | ✓ | | ✓ | Yes | ASP.NET environment |
|
||||
| `ASPNETCORE_URLS` | ✓ | | ✓ | Yes | API binding address |
|
||||
@@ -366,6 +383,9 @@ REFRESH_TOKEN_SECRET=<generated-with-openssl>
|
||||
CONFIRMATION_TOKEN_SECRET=<generated-with-openssl>
|
||||
WEBSITE_BASE_URL=http://localhost:3000
|
||||
|
||||
# Frontend session signing
|
||||
SESSION_SECRET=<generated-with-openssl>
|
||||
|
||||
# SMTP (Mailpit in dev)
|
||||
SMTP_HOST=mailpit
|
||||
SMTP_PORT=1025
|
||||
|
||||
@@ -33,7 +33,8 @@ This command:
|
||||
1. Starts a fresh SQL Server instance
|
||||
2. Runs database migrations
|
||||
3. Seeds test data
|
||||
4. Executes all test suites in parallel
|
||||
4. Executes all test suites in parallel, including the frontend's Storybook
|
||||
Vitest and Playwright suites (`frontend.tests`, which needs no database)
|
||||
5. Exports results to `./test-results/`
|
||||
6. Exits when tests complete
|
||||
|
||||
@@ -49,6 +50,8 @@ cat test-results/Features.Users.Tests.trx
|
||||
cat test-results/Features.Breweries.Tests.trx
|
||||
cat test-results/Features.Emails.Tests.trx
|
||||
cat test-results/Features.PhotoUpload.Tests.trx
|
||||
cat test-results/frontend/vitest-storybook.xml
|
||||
cat test-results/frontend/playwright-storybook.xml
|
||||
```
|
||||
|
||||
### Clean up
|
||||
@@ -327,8 +330,10 @@ Scenario: User login with valid credentials
|
||||
|
||||
## Continuous integration
|
||||
|
||||
Tests run automatically in CI/CD pipelines using the test Docker Compose
|
||||
configuration:
|
||||
The `.github/workflows/tests.yml` GitHub Actions workflow runs on every push
|
||||
and pull request to `main`. It runs the same test Docker Compose
|
||||
configuration used locally, so backend and frontend tests execute in the same
|
||||
containerized environment in CI as they do on a developer machine:
|
||||
|
||||
```bash
|
||||
# CI/CD command
|
||||
@@ -337,13 +342,22 @@ docker compose --env-file web/.env.test -f web/docker-compose.test.yaml up --abo
|
||||
docker compose --env-file web/.env.test -f web/docker-compose.test.yaml down -v
|
||||
```
|
||||
|
||||
Because `--abort-on-container-exit` stops the stack as soon as any one-shot
|
||||
test container exits (success or failure), the workflow separately inspects
|
||||
the exit code of each test container (`test-env-api-specs`,
|
||||
`test-env-unit-tests`, `test-env-frontend-tests`) after `up` returns and fails
|
||||
the job if any of them is non-zero. `./test-results/` is uploaded as a build
|
||||
artifact regardless of outcome.
|
||||
|
||||
Exit codes:
|
||||
|
||||
- `0` - All tests passed
|
||||
- Non-zero - Test failures occurred
|
||||
|
||||
Frontend UI checks should also be included in CI for the active website
|
||||
workspace:
|
||||
The frontend's Storybook Vitest and Playwright suites run inside the
|
||||
`frontend.tests` container (see [Docker Guide](docker.md)) as part of that
|
||||
same compose run, so no separate frontend CI step is needed. To run them
|
||||
locally without Docker:
|
||||
|
||||
```bash
|
||||
cd web/frontend
|
||||
|
||||
Reference in New Issue
Block a user