Add deployment files
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# Guide 26: VigilCareRecords CI/CD (Gitea Actions + Docker Compose)
|
||||
|
||||
How VigilCareRecords is built, tested, and deployed on the same Gitea Actions + `act_runner` + container registry setup already used by VigilCareClinical. See [`docs/25-gitea-cicd-docker-deploy.md`](25-gitea-cicd-docker-deploy.md) for the general pattern this guide instantiates; this doc only covers what is specific to this repo.
|
||||
|
||||
Related files:
|
||||
|
||||
- [`.gitea/workflows/ci.yml`](../.gitea/workflows/ci.yml) / [`.gitea/workflows/cd.yml`](../.gitea/workflows/cd.yml)
|
||||
- [`docker-compose.yml`](../docker-compose.yml) (local + CI dependencies)
|
||||
- [`docker-compose.prod.yml`](../docker-compose.prod.yml) (production app stack)
|
||||
- [`.env.example`](../.env.example)
|
||||
- [`VigilCareRecordsAPI/Dockerfile`](../VigilCareRecordsAPI/Dockerfile) / [`vigilcare-records-web/Dockerfile`](../vigilcare-records-web/Dockerfile)
|
||||
|
||||
---
|
||||
|
||||
## 1. Topology
|
||||
|
||||
VigilCareRecords ships two images:
|
||||
|
||||
| Image | Dockerfile | Build context |
|
||||
|---|---|---|
|
||||
| `vigilcare-records-api` | `VigilCareRecordsAPI/Dockerfile` | repo root |
|
||||
| `vigilcare-records-dashboard` | `vigilcare-records-web/Dockerfile` | `vigilcare-records-web/` |
|
||||
|
||||
Unlike VigilCareClinical, there is no gateway service, and the frontend does not bake in an absolute API URL at build time — `src/api/client.ts` and `src/api/fhirClient.ts` use relative base URLs (`/api/v1`, `/fhir`). The dashboard's `nginx.conf` reverse-proxies those paths to the `api` container, so the same image works behind any hostname without a build-arg.
|
||||
|
||||
## 2. Shared production infrastructure
|
||||
|
||||
Per the "Integrated Database Deployment" decision documented in [`vigilcare-records-clinical-overview.md`](vigilcare-records-clinical-overview.md), VigilCareRecords does **not** run its own Postgres/Redis/MinIO/Seq in production. It joins the external `shared-services` Docker network already created by VigilCareClinical's own compose project and connects to those same containers, using:
|
||||
|
||||
- Its own logical Postgres database (`vigilcare_records`, separate schema/tables from VigilCareClinical's `patients`/`encounters`/`observations` — see the promotion service for how the two connect at the application layer, not the infrastructure layer)
|
||||
- A dedicated Redis logical database (`defaultDatabase=2` in `.env.example`) so batch-assignment locks never collide with VigilCareClinical's keys
|
||||
- A dedicated MinIO bucket (`vigilcare-records-scans`) separate from any clinical document buckets
|
||||
|
||||
**Before the first deploy**, confirm the VigilCareClinical infra stack (or whatever compose project owns `shared-services`) is already running on the deploy host — `docker network ls | grep shared-services` should show it. `docker compose -f docker-compose.prod.yml up` will fail to find the network otherwise.
|
||||
|
||||
## 3. One-time host setup
|
||||
|
||||
```bash
|
||||
ssh deploy@YOUR_HOST "mkdir -p /opt/vigilcare-records"
|
||||
scp .env deploy@YOUR_HOST:/opt/vigilcare-records/.env
|
||||
ssh deploy@YOUR_HOST "chmod 600 /opt/vigilcare-records/.env"
|
||||
```
|
||||
|
||||
Fill in `.env` from [`.env.example`](../.env.example) first — generate `JWT_SECRET` with `openssl rand -base64 48`, and get real credentials for the shared Postgres/Redis/MinIO/Seq services from whoever manages that stack. CD never uploads or overwrites `.env`; only the `IMAGE_TAG` line is patched automatically on each release.
|
||||
|
||||
## 4. Gitea secrets and variables
|
||||
|
||||
Repo → **Settings** → **Actions**.
|
||||
|
||||
### Secrets
|
||||
|
||||
| Secret | Used by |
|
||||
|---|---|
|
||||
| `REGISTRY_USERNAME` | `docker login` |
|
||||
| `REGISTRY_TOKEN` | `docker login` (access token / PAT with package write) |
|
||||
| `PG_CONNECTION_DDL` | migrate job only — DDL-privileged connection to the shared Postgres, never given to the API container |
|
||||
| `DEPLOY_HOST` | SSH / SCP |
|
||||
| `DEPLOY_USER` | SSH / SCP |
|
||||
| `DEPLOY_SSH_KEY` | Private key PEM / OpenSSH private key body |
|
||||
|
||||
### Variables
|
||||
|
||||
| Variable | Used by |
|
||||
|---|---|
|
||||
| `REGISTRY` | Optional override of the default `git.vectur45.com/trent/vigilcare-records` |
|
||||
|
||||
## 5. Release flow
|
||||
|
||||
```bash
|
||||
# CI green on master, then:
|
||||
git tag v1.0.0
|
||||
git push origin v1.0.0
|
||||
```
|
||||
|
||||
This triggers `.gitea/workflows/cd.yml`: build & push both images → apply EF Core migrations against `PG_CONNECTION_DDL` → SSH deploy (`scp` the prod compose file, patch `IMAGE_TAG`, `pull` + `up -d`) → smoke test (`/health/ready`, dashboard `/`) → automatic rollback to the previous `IMAGE_TAG` on failure (schema changes are not reverted; see the expand/contract note in `cd.yml`).
|
||||
|
||||
Manual redeploy of an existing tag: Gitea UI → Actions → CD → Run workflow, with `image_tag` input.
|
||||
|
||||
## 6. Pre-production checklist (application-level, not part of this CI/CD change)
|
||||
|
||||
- **Demo data seeding runs unconditionally on startup.** `Program.cs` calls `DataSeeder.SeedAsync(db)` whenever `ASPNETCORE_ENVIRONMENT` is not `Testing` — including `Production`. Unlike the VigilCareClinical example (`Seeding__EnableDemoData=false`), this app has no seeding toggle. Before a real clinical deploy, either add a guard around `DataSeeder.SeedAsync` for `Production`, or confirm the twelve seeded demo accounts (all password `password`) are acceptable/rotated before go-live.
|
||||
- Confirm `Cors:AllowedOrigins` / `DASHBOARD_ORIGIN` matches the real public dashboard origin if the dashboard is ever served from a different origin than the API (not the default same-origin nginx-proxy setup described above).
|
||||
- Rotate `JWT_SECRET` from any value used during testing before the first real deploy.
|
||||
Reference in New Issue
Block a user