Files
mic-check/docs/system-design.md
T
James Wampler aa611feaff
CI / build-and-push (push) Has been cancelled
CI / deploy-qa (push) Has been cancelled
CI / smoke-qa (push) Has been cancelled
WIP
2026-07-22 14:02:59 -07:00

2.9 KiB

System Design — QA Physical Architecture

Physical deployment topology for the QA environment. Source: deploy/qa/docker-compose.qa.yml, scripts/ci/*.sh, .github/workflows/ci.yml.

flowchart TB
    subgraph CI["Self-hosted CI runner (qa)"]
        Pipeline["deploy-qa.sh / smoke-qa.sh"]
    end

    subgraph Registry["Gitea Container Registry"]
        ApiImage["miccheck-api:qa"]
        AdminImage["miccheck-admin:qa"]
    end

    subgraph QAHost["QA Docker host — network: miccheck-qa-net (bridge)"]
        subgraph AdminC["admin container<br/>nginx:1.27-alpine"]
            Nginx["nginx<br/>serves Vue SPA<br/>proxies /api/, /health"]
        end

        subgraph ApiC["api container<br/>aspnet:10.0"]
            Api["MicCheck.Api<br/>ASPNETCORE_URLS=http://+:8080"]
        end

        subgraph DbC["db container<br/>postgres:16-alpine"]
            Db[("miccheck DB")]
        end
    end

    Browser["Browser / QA tester"]

    Pipeline -->|docker build/push| Registry
    Registry -->|pull :qa| AdminC
    Registry -->|pull :qa| ApiC

    Browser -->|":3001 (QA_ADMIN_PORT)"| Nginx
    Nginx -->|"http://api:8080 (internal)"| Api
    Api -->|"Host=db;5432 (internal)"| Db

    Pipeline -.->|"127.0.0.1:55432 (bridge-gateway bound)"| Db

Components

Component Image Exposure Notes
admin nginx:1.27-alpine (built from src/admin/Dockerfile.ci, node:22-alpine build stage) ${QA_ADMIN_PORT:-3001}:80 published on host Serves Vue/Vite SPA; nginx (src/admin/nginx.conf) reverse-proxies /api/ and /health to api:8080
api mcr.microsoft.com/dotnet/aspnet:10.0 (built from src/api/MicCheck.Api/Dockerfile.ci, sdk:10.0 build stage) no published host port — internal only, reached via admin's nginx proxy ASPNETCORE_URLS=http://+:8080; JWT config (Jwt__SecretKey/Issuer=MicCheck/Audience=MicCheck) from JWT_SECRET_KEY secret; healthcheck curl localhost:8080/health
db postgres:16-alpine ${DB_BIND_HOST:-127.0.0.1}:55432 → 5432, bound to docker bridge gateway IP (not 0.0.0.0) — reachable only from sibling CI containers, not off-box DB miccheck, user miccheck, password from POSTGRES_PASSWORD secret; volume miccheck-qa-pgdata

All three services run on an isolated bridge network miccheck-qa-net (project miccheck-qa), separate from the local dev Aspire stack.

Deploy flow

  1. build-and-push job builds api and admin images, tags with git SHA and qa, pushes to Gitea registry as $REGISTRY/$REGISTRY_OWNER/miccheck-api / miccheck-admin.
  2. deploy-qa job (self-hosted runner, main branch only) pulls :qa images and runs docker-compose.qa.yml via deploy-qa.sh.
  3. smoke-qa job hits the deployed stack (smoke-qa.sh) to verify health.

Secrets used: REGISTRY, REGISTRY_OWNER, REGISTRY_USER, REGISTRY_TOKEN, JWT_SECRET_KEY, POSTGRES_PASSWORD. Vars: QA_ADMIN_PORT.