feat: Add Docker support and CI/CD workflows documentation; include setup instructions for Docker-based deployment
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 1m35s
Deploy to Server / deploy (push) Failing after 3s
Run Tests / test (push) Failing after 6m2s

This commit is contained in:
2025-10-23 17:25:26 +02:00
parent 119bbcc7a8
commit f228eac61f
4 changed files with 101 additions and 14 deletions

View File

@@ -33,3 +33,30 @@ This repository contains detailed developer and architecture documentation in th
Key architecture documents: see [architecture](docs/architecture/README.md) for the arc42-based architecture documentation. Key architecture documents: see [architecture](docs/architecture/README.md) for the arc42-based architecture documentation.
For contributors: the `routes/`, `models/` and `services/` folders contain the primary application code. Tests and E2E specs are in `tests/`. For contributors: the `routes/`, `models/` and `services/` folders contain the primary application code. Tests and E2E specs are in `tests/`.
## Run with Docker
The repository ships with a multi-stage `Dockerfile` that produces a slim runtime image.
```powershell
# Build the image locally
docker build -t calminer:latest .
# Run the container (exposes FastAPI on http://localhost:8000)
docker run --rm -p 8000:8000 calminer:latest
# Provide environment variables (e.g., database URL)
docker run --rm -p 8000:8000 -e DATABASE_URL="postgresql://user:pass@host/db" calminer:latest
```
Use `docker compose` or an orchestrator of your choice to co-locate PostgreSQL/Redis alongside the app when needed. The image expects migrations to be applied before startup.
## CI/CD expectations
CalMiner uses Gitea Actions workflows stored in `.gitea/workflows/`:
- `test.yml` runs style/unit/e2e suites on every push with cached Python dependencies.
- `build-and-push.yml` builds the Docker image, reuses cached layers, and pushes to the configured registry.
- `deploy.yml` pulls the pushed image on the target host and restarts the container.
Pipelines assume the following secrets are provisioned in the Gitea instance: `GITEA_USERNAME`, `GITEA_PASSWORD`, `GITEA_REGISTRY`, `SSH_HOST`, `SSH_USERNAME`, and `SSH_PRIVATE_KEY`.

View File

@@ -4,6 +4,8 @@ description: "Describe deployment topology, infrastructure components, and envir
status: draft status: draft
--- ---
<!-- markdownlint-disable-next-line MD025 -->
# 07 — Deployment View # 07 — Deployment View
## Deployment Topology ## Deployment Topology
@@ -23,8 +25,8 @@ The infrastructure components for the application include:
- **Database Server**: PostgreSQL database for persisting application data. - **Database Server**: PostgreSQL database for persisting application data.
- **Static File Server**: Serves static assets such as CSS, JavaScript, and image files. - **Static File Server**: Serves static assets such as CSS, JavaScript, and image files.
- **Reverse Proxy (optional)**: An Nginx or Apache server can be used as a reverse proxy. - **Reverse Proxy (optional)**: An Nginx or Apache server can be used as a reverse proxy.
- **CI/CD Pipeline (optional)**: Automated deployment pipelines can be set up using tools like GitHub Actions. - **Containerization**: Docker images are generated via the repository `Dockerfile`, using a multi-stage build to keep the final runtime minimal.
- **Containerization (optional)**: Docker can be used to containerize the application. - **CI/CD Pipeline**: Automated pipelines (Gitea Actions) run tests, build/push Docker images, and trigger deployments.
- **Cloud Infrastructure (optional)**: The application can be deployed on cloud platforms. - **Cloud Infrastructure (optional)**: The application can be deployed on cloud platforms.
## Environments ## Environments
@@ -55,7 +57,32 @@ The production environment is set up for serving live traffic and includes:
- Load balancer (e.g., Nginx) for distributing incoming requests - Load balancer (e.g., Nginx) for distributing incoming requests
- Monitoring and logging tools for tracking application performance - Monitoring and logging tools for tracking application performance
## Containerized Deployment Flow
The Docker-based deployment path aligns with the solution strategy documented in [04 — Solution Strategy](04_solution_strategy.md) and the CI practices captured in [14 — Testing & CI](14_testing_ci.md).
### Image Build
- The multi-stage `Dockerfile` installs dependencies in a builder layer (including system compilers and Python packages) and copies only the required runtime artifacts to the final image.
- Build arguments are minimal; environment configuration (e.g., `DATABASE_URL`) is supplied at runtime. Secrets and configuration should be passed via environment variables or an orchestrator.
- The resulting image exposes port `8000` and starts `uvicorn main:app` (s. [README.md](../README.md)).
### Runtime Environment
- For single-node deployments, run the container alongside PostgreSQL/Redis using Docker Compose or an equivalent orchestrator.
- A reverse proxy (e.g., Nginx) terminates TLS and forwards traffic to the container on port `8000`.
- Migrations must be applied prior to rolling out a new image; automation can hook into the deploy step to run `scripts/run_migrations.py`.
### CI/CD Integration
- Gitea Actions workflows reside under `.gitea/workflows/`.
- `test.yml` executes the pytest suite using cached pip dependencies.
- `build-and-push.yml` logs into the container registry, rebuilds the Docker image using GitHub Actions cache-backed layers, and pushes `latest` (and additional tags as required).
- `deploy.yml` connects to the target host via SSH, pulls the pushed tag, stops any existing container, and launches the new version.
- Required secrets: `GITEA_REGISTRY`, `GITEA_USERNAME`, `GITEA_PASSWORD`, `SSH_HOST`, `SSH_USERNAME`, `SSH_PRIVATE_KEY`.
- Extend these workflows when introducing staging/blue-green deployments; keep cross-links with [14 — Testing & CI](14_testing_ci.md) up to date.
## Integrations and Future Work (deployment-related) ## Integrations and Future Work (deployment-related)
- **Persistence of results**: `/api/simulations/run` currently returns in-memory results; next iteration should persist to `simulation_result` and reference scenarios. - **Persistence of results**: `/api/simulations/run` currently returns in-memory results; next iteration should persist to `simulation_result` and reference scenarios.
- **Deployment**: documentation focuses on local development; containerization and CI/CD pipelines remain to be defined. Consider Docker + GitHub Actions or a simple Docker Compose for local stacks. - **Deployment**: implement infrastructure-as-code (e.g., Terraform/Ansible) to provision the hosting environment and maintain parity across dev/stage/prod.

View File

@@ -20,9 +20,12 @@ CalMiner uses a combination of unit, integration, and end-to-end tests to ensure
### CI/CD ### CI/CD
- Use GitHub Actions for CI. - Use Gitea Actions for CI/CD; workflows live under `.gitea/workflows/`.
- Run tests on pull requests. - `test.yml` runs on every push with cached Python dependencies via `actions/cache@v3`.
- Code coverage target: 80% (using pytest-cov). - `build-and-push.yml` builds the Docker image with `docker/build-push-action@v2`, reusing GitHub Actions cache-backed layers, and pushes to the Gitea registry.
- `deploy.yml` connects to the target host (via `appleboy/ssh-action`) to pull the freshly pushed image and restart the container.
- Mandatory secrets: `GITEA_USERNAME`, `GITEA_PASSWORD`, `GITEA_REGISTRY`, `SSH_HOST`, `SSH_USERNAME`, `SSH_PRIVATE_KEY`.
- Run tests on pull requests to shared branches; enforce coverage target ≥80% (pytest-cov).
### Running Tests ### Running Tests
@@ -34,7 +37,7 @@ CalMiner uses a combination of unit, integration, and end-to-end tests to ensure
Organize tests under the `tests/` directory mirroring the application structure: Organize tests under the `tests/` directory mirroring the application structure:
```text ````text
tests/ tests/
unit/ unit/
test_<module>.py test_<module>.py
@@ -71,7 +74,7 @@ To run the Playwright tests:
```bash ```bash
pytest tests/e2e/ pytest tests/e2e/
``` ````
To run headed mode: To run headed mode:
@@ -93,9 +96,22 @@ pytest tests/e2e/ --headed
### CI Integration ### CI Integration
- Configure GitHub Actions workflow in `.github/workflows/ci.yml` to: `test.yml` encapsulates the steps below:
- Install dependencies, including Playwright browsers (`playwright install`).
- Run `pytest` with coverage for unit tests. - Check out the repository and set up Python 3.10.
- Run `pytest tests/e2e/` for E2E tests. - Restore the pip cache (keyed by `requirements.txt`).
- Fail on coverage <80%. - Install project dependencies and Playwright browsers (if needed for E2E).
- Upload coverage artifacts under `reports/coverage/`. - Run `pytest` (extend with `--cov` flags when enforcing coverage).
`build-and-push.yml` adds:
- Registry login using repository secrets.
- Docker image build/push with GHA cache storage (`cache-from/cache-to` set to `type=gha`).
`deploy.yml` handles:
- SSH into the deployment host.
- Pull the tagged image from the registry.
- Stop, remove, and relaunch the `calminer` container exposing port 8000.
When adding new workflows, mirror this structure to ensure secrets, caching, and deployment steps remain aligned with the production environment.

View File

@@ -22,6 +22,23 @@ pip install -r requirements.txt
uvicorn main:app --reload uvicorn main:app --reload
``` ```
## Docker-based setup
To build and run the application using Docker instead of a local Python environment:
```powershell
# Build the application image (multi-stage build keeps runtime small)
docker build -t calminer:latest .
# Start the container on port 8000
docker run --rm -p 8000:8000 calminer:latest
# Supply environment variables (e.g., Postgres connection)
docker run --rm -p 8000:8000 -e DATABASE_URL="postgresql://user:pass@host/db" calminer:latest
```
If you maintain a Postgres or Redis dependency locally, consider authoring a `docker compose` stack that pairs them with the app container. The Docker image expects the database to be reachable and migrations executed before serving traffic.
## Usage Overview ## Usage Overview
- **API base URL**: `http://localhost:8000/api` - **API base URL**: `http://localhost:8000/api`