diff --git a/.gitea/workflows/cd.yml b/.gitea/workflows/cd.yml
index 3c8bb55..cb9cde0 100644
--- a/.gitea/workflows/cd.yml
+++ b/.gitea/workflows/cd.yml
@@ -1,13 +1,17 @@
name: CD
on:
- push:
+ workflow_run:
+ workflows: ["CI"]
+ types:
+ - completed
branches: [main]
workflow_dispatch:
jobs:
deploy:
runs-on: [ubuntu-latest]
+ if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' }}
environment: production
steps:
- name: Checkout code
diff --git a/docs/architecture/README.md b/docs/architecture/README.md
index 0bd6674..056af3b 100644
--- a/docs/architecture/README.md
+++ b/docs/architecture/README.md
@@ -217,6 +217,65 @@ Notable aspects: Manifest freshness ensures all viewers stay on same timeline; c
## Deployment View
+### CI/CD Pipeline Architecture
+
+The deployment follows a two-stage pipeline: **CI builds and pushes images**, then **CD pulls and deploys** them to the production host.
+
+```mermaid
+flowchart LR
+ subgraph "Gitea Actions"
+ CI[CI Workflow
Build + Push Images]
+ CD[CD Workflow
Pull + Deploy]
+ end
+ subgraph "Gitea Container Registry"
+ REGISTRY[git.allucanget.biz
playout:latest
chat:latest
nginx:latest]
+ end
+ subgraph "Production Host (192.168.88.40)"
+ DOCKER[Docker Engine
via TCP :2375]
+ PLAYOUT[linearvoid-playout]
+ CHAT[linearvoid-chat]
+ NGINX[linearvoid-nginx]
+ REDIS[linearvoid-redis]
+ DB[linearvoid-db]
+ PROM[linearvoid-prometheus]
+ GRAF[linearvoid-grafana]
+ end
+
+ CI -->|push| REGISTRY
+ REGISTRY -->|pull| CD
+ CD -->|deploy via DOCKER_HOST| DOCKER
+ DOCKER --> PLAYOUT
+ DOCKER --> CHAT
+ DOCKER --> NGINX
+ DOCKER --> REDIS
+ DOCKER --> DB
+ DOCKER --> PROM
+ DOCKER --> GRAF
+
+ classDef ci fill:#e1f5fe,stroke:#0288d1
+ classDef reg fill:#fff3e0,stroke:#f57c00
+ classDef prod fill:#e8f5e9,stroke:#388e3c
+ class CI,CD ci
+ class REGISTRY reg
+ class DOCKER,PLAYOUT,CHAT,NGINX,REDIS,DB,PROM,GRAF prod
+```
+
+**Pipeline Sequence:**
+
+1. **CI Workflow** (`.gitea/workflows/ci.yml`):
+ - Triggers on `push` to `main` or `pull_request`
+ - Runs `test` job: frontend lint/build, Go validation, `docker compose build`
+ - Runs `docker` job (after `test` passes, only on `main` push):
+ - Builds `playout`, `chat`, `nginx` images with Buildx
+ - Pushes to Gitea Container Registry with `main` and `latest` tags
+2. **CD Workflow** (`.gitea/workflows/cd.yml`):
+ - Triggers on `workflow_run` when CI completes successfully, or manually via `workflow_dispatch`
+ - Pulls latest images from registry
+ - Generates `.env` from secrets
+ - Seeds Prometheus config into named volume
+ - Deploys via `docker compose -f docker-compose.prod.yml up -d` to remote host (`192.168.88.40:2375`)
+ - Runs health checks with retry logic for playout initialization
+
### Infrastructure Level 1
**Overview Diagram**: See Mermaid in Building Block section (VPS + Cloudflare R2/Pages/CDN).