feat: initial commit
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
# CI Observer Architecture
|
||||
|
||||
## What It Is
|
||||
CI Observer is a read-only dashboard that polls GitHub Actions run data and renders a live CI status wall.
|
||||
|
||||
## Core Technologies
|
||||
- Backend: Python 3.11 + FastAPI
|
||||
- HTTP client: `httpx`
|
||||
- Storage: SQLite (`/app/data/ci_observer.db`)
|
||||
- Frontend: server-rendered static HTML/CSS/JS (no SPA framework)
|
||||
- Runtime: Docker + Docker Compose
|
||||
- Source control: GitHub
|
||||
|
||||
## High-Level Flow
|
||||
```mermaid
|
||||
flowchart LR
|
||||
GH[GitHub Actions API] -->|poll runs| APP[FastAPI Poller]
|
||||
APP -->|upsert| DB[(SQLite)]
|
||||
UI[Browser] -->|GET /api/runs /api/filters /api/config| APP
|
||||
APP -->|query| DB
|
||||
APP -->|JSON + static assets| UI
|
||||
```
|
||||
|
||||
## Runtime Components
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph Runner_VM
|
||||
C[Docker Container: ci-observer-dashboard-prod]
|
||||
D[(Volume ./data -> /app/data)]
|
||||
S[Static UI: index.html + app.js + styles.css]
|
||||
A[FastAPI app/main.py]
|
||||
C --> A
|
||||
C --> S
|
||||
C --> D
|
||||
end
|
||||
|
||||
Browser -->|HTTP :8089| C
|
||||
A -->|HTTPS calls| GitHubAPI[api.github.com]
|
||||
```
|
||||
|
||||
## Data Model (Main Fields)
|
||||
Stored run fields include:
|
||||
- `repo`, `workflow`, `run_id`, `status`, `conclusion`
|
||||
- `head_branch`, `head_sha`, `actor`
|
||||
- `started_at`, `updated_at`, `duration_seconds`
|
||||
- `html_url`
|
||||
- `raw_json` (full run payload for future extensions)
|
||||
|
||||
## App Principles
|
||||
- Read-only by design: no write-back to GitHub or pipeline control.
|
||||
- Operational simplicity: one container, one DB file, one compose file per instance.
|
||||
- Clear rollout model: feature branch on test port, then merge to `main`, then production deploy.
|
||||
- Low blast radius: test instances isolated by folder, port, and SQLite volume path.
|
||||
|
||||
## Config Contract
|
||||
Environment variables:
|
||||
- `GITHUB_TOKEN`
|
||||
- `GH_REPOS` (comma-separated)
|
||||
- `GH_WORKFLOWS` (comma-separated workflow file names)
|
||||
- `REFRESH_SECONDS`
|
||||
- `DASHBOARD_TITLE`
|
||||
|
||||
Important:
|
||||
- Current polling logic requires both `GH_REPOS` and `GH_WORKFLOWS`.
|
||||
- If `GH_WORKFLOWS` is empty, polling does not start.
|
||||
|
||||
## Deployment Model Used
|
||||
1. Build/test on temporary instance in `/webapps/ci-observer-dashboard-<feature>` on test port.
|
||||
2. Validate UI/behavior.
|
||||
3. Merge approved branch to `main`.
|
||||
4. Production update from `/webapps/ci-observer-dashboard-prod` on `8089`.
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# CI Observer Operations Runbook
|
||||
|
||||
## Purpose
|
||||
Operational guide for running CI Observer on the runner VM with one stable production instance and optional temporary test instances.
|
||||
|
||||
## Standard Layout on Runner
|
||||
- Production folder: `/webapps/ci-observer-dashboard-prod`
|
||||
- Temporary test folder example: `/webapps/ci-observer-dashboard-<feature>`
|
||||
- One folder per instance. No nested folder-in-folder setup.
|
||||
|
||||
## Production Deploy (main branch)
|
||||
```bash
|
||||
cd /webapps/ci-observer-dashboard-prod
|
||||
git checkout main
|
||||
git pull
|
||||
docker compose up -d --build
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
## Required `.env`
|
||||
```env
|
||||
GITHUB_TOKEN=...
|
||||
GH_REPOS=Wolkabout/IoT-Platform-Core,Wolkabout/argocd
|
||||
GH_WORKFLOWS=unit-tests.yml,deploy-be.yml,deploy-fe.yml
|
||||
REFRESH_SECONDS=5
|
||||
DASHBOARD_TITLE="CI Observer Dashboard"
|
||||
```
|
||||
|
||||
Notes:
|
||||
- `GH_WORKFLOWS` must be set in current app behavior.
|
||||
- Private repos require PAT scopes: `repo`, `read:org`, `workflow`.
|
||||
|
||||
## Production Compose (8089)
|
||||
`docker-compose.yml` should use:
|
||||
- `container_name: ci-observer-dashboard-prod`
|
||||
- `ports: "8089:8088"`
|
||||
- `volumes: ./data:/app/data`
|
||||
|
||||
## Quick Health Check
|
||||
```bash
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep ci-observer-dashboard-prod
|
||||
curl -s http://127.0.0.1:8089/api/config
|
||||
curl -s http://127.0.0.1:8089/api/runs | head -c 800; echo
|
||||
```
|
||||
|
||||
## Temporary Test Instance Flow
|
||||
```bash
|
||||
cd /webapps
|
||||
git clone https://github.com/Wolkabout/ci-observer-dashboard.git ci-observer-dashboard-mytest
|
||||
cd ci-observer-dashboard-mytest
|
||||
cp /webapps/ci-observer-dashboard-prod/.env .env
|
||||
git checkout <feature-branch>
|
||||
```
|
||||
|
||||
Edit `docker-compose.yml` for test:
|
||||
- `container_name: ci-observer-dashboard-mytest`
|
||||
- `ports: "8090:8088"` (or any free test port)
|
||||
- `volumes: ./data-mytest:/app/data`
|
||||
|
||||
Run:
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Cleanup after test:
|
||||
```bash
|
||||
docker compose down --remove-orphans
|
||||
cd /webapps
|
||||
rm -rf /webapps/ci-observer-dashboard-mytest
|
||||
```
|
||||
|
||||
## Final Cleanup Checklist
|
||||
```bash
|
||||
docker rm -f ci-observer-dashboard ci-observer-dashboard-filters ci-observer-dashboard-metadata-test 2>/dev/null || true
|
||||
find /webapps -maxdepth 1 -type d -name "ci-observer-dashboard-*" ! -name "ci-observer-dashboard-prod"
|
||||
```
|
||||
|
||||
Expected final state:
|
||||
- Only `/webapps/ci-observer-dashboard-prod` is active for production.
|
||||
- Production container on `8089`.
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# CI Observer Dashboard (POC)
|
||||
|
||||
Minimal read-only dashboard that polls GitHub Actions runs and renders a live status wall.
|
||||
|
||||
## Quick start
|
||||
|
||||
1. Copy env template:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
2. Edit `.env` and set:
|
||||
|
||||
- `GITHUB_TOKEN` (classic PAT with `repo`, `read:org`, `workflow`)
|
||||
- `GH_REPOS` (e.g. `Wolkabout/IoT-Platform-Core`)
|
||||
- `GH_WORKFLOWS` (e.g. `unit-tests.yml`)
|
||||
|
||||
3. Run:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
4. Open:
|
||||
|
||||
```
|
||||
http://<runner-ip>:8088
|
||||
```
|
||||
|
||||
## Filters preview (separate instance)
|
||||
|
||||
If testing the filters branch in parallel, use:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.filters.yml up -d --build
|
||||
```
|
||||
|
||||
This runs on port `8089` and uses `./data-filters`.
|
||||
|
||||
### Parallel instance on VM
|
||||
|
||||
```bash
|
||||
cd /webapps
|
||||
git clone https://github.com/Wolkabout/ci-observer-dashboard.git ci-observer-dashboard-filters
|
||||
cd ci-observer-dashboard-filters
|
||||
git checkout feature/filters
|
||||
cp .env.example .env
|
||||
docker compose -f docker-compose.filters.yml up -d --build
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- This is read-only; no CI/CD impact.
|
||||
- For private repos, a token is required.
|
||||
- Data stored locally in `./data/ci_observer.db`.
|
||||
|
||||
## Documentation
|
||||
|
||||
- Operations runbook: `docs/OPERATIONS_RUNBOOK.md`
|
||||
- Architecture + diagrams: `docs/ARCHITECTURE.md`
|
||||
|
||||
## Appendix: Reverse proxy (NPM)
|
||||
|
||||
- Nginx Proxy Manager runs at `10.0.50.78`.
|
||||
- DNS/hosts should point `ci-observer.wolkabout.com` to `10.0.50.78`.
|
||||
- NPM forwards to the dashboard on `10.1.50.20:8089`.
|
||||
@@ -0,0 +1,7 @@
|
||||
# Stack Overview
|
||||
|
||||
- FE: HTML + CSS + Vanilla JavaScript
|
||||
- BE: Python + FastAPI
|
||||
- Between FE and BE: REST API over HTTP (`/api/runs`, `/api/filters`, `/api/config`)
|
||||
- Under BE: SQLite database + GitHub Actions API as the external data source
|
||||
|
||||
Reference in New Issue
Block a user