# DIUN Webhook Dashboard A Go web app that receives [DIUN](https://crazymax.dev/diun/) webhook events and shows image updates in a modern dashboard. Events are persisted to SQLite so they survive restarts. - Receives DIUN webhooks at `POST /webhook` - Serves a React SPA dashboard at `/` - REST API for updates, tags, and acknowledgements - Persistent storage via SQLite (`diun.db`) - Tag/group system to organize images - Dismiss (acknowledge) updates you've reviewed ## Quick start ### Run locally (Go 1.26+) ```bash # Build the frontend first cd frontend && bun install && bun run build && cd .. # Start the server go run ./cmd/diunwebhook/ # open http://localhost:8080 ``` ### Docker ```bash docker build -t diun-webhook-dashboard . docker run --rm -p 8080:8080 diun-webhook-dashboard # open http://localhost:8080 ``` ### Docker Compose (deploy) ```bash # Pulls from Gitea registry, persists DB to a named volume docker compose up -d # open http://localhost:8080 ``` ### Docker Compose (dev) ```bash # Builds the image locally from source docker compose -f compose.dev.yml up -d # open http://localhost:8080 ``` ## Webhook authentication Set `WEBHOOK_SECRET` to protect the webhook endpoint with token authentication. When set, every `POST /webhook` must include a matching `Authorization` header. When unset, the webhook is open (a warning is logged at startup). ```bash # Run with authentication WEBHOOK_SECRET=your-secret-token-here go run ./cmd/diunwebhook/ # Or via Docker Compose (.env file or inline) WEBHOOK_SECRET=your-secret-token-here docker compose up -d # Custom database path (useful for Docker volume mounts) DB_PATH=/data/diun.db go run ./cmd/diunwebhook/ ``` ## DIUN configuration example Configure DIUN to send webhooks to this app. Example (YAML): ```yaml notif: webhook: enable: true endpoint: http://your-host-or-ip:8080/webhook headers: authorization: "your-secret-token-here" ``` Or via env: `DIUN_NOTIF_WEBHOOK_HEADERS_AUTHORIZATION=your-secret-token-here` The `authorization` header value must match `WEBHOOK_SECRET` exactly. Expected JSON payload (simplified): ```json { "image": "library/nginx", "tag": "1.27.0", "status": "new", "time": "2026-02-23T16:00:00Z" } ``` ## API | Method | Endpoint | Description | |--------|----------|-------------| | `POST` | `/webhook` | Accept a DIUN event JSON body | | `GET` | `/api/updates` | Return all events (keyed by image) with tag and acknowledged state | | `PATCH` | `/api/updates/{image}` | Mark an event as acknowledged (dismiss) | | `GET` | `/api/tags` | List all tags | | `POST` | `/api/tags` | Create a new tag | | `DELETE` | `/api/tags/{id}` | Delete a tag (cascades to assignments) | | `PUT` | `/api/tag-assignments` | Assign an image to a tag | | `DELETE` | `/api/tag-assignments` | Unassign an image from its tag | ## Project Structure ``` cmd/diunwebhook/ — main application entrypoint pkg/diunwebhook/ — core library (handlers, DB, models) frontend/ — React SPA (Bun + Vite + React 19 + Tailwind + shadcn/ui) .gitea/workflows/ — CI/CD workflows (Gitea Actions) Dockerfile — 3-stage multi-stage build compose.yml — deploy compose (pulls from Gitea registry) compose.dev.yml — dev compose (builds locally) ``` ## Development **Backend:** ```bash go run ./cmd/diunwebhook/ ``` **Frontend (dev server with hot reload):** ```bash cd frontend bun install bun run dev # http://localhost:5173, proxies API to :8080 ``` ## Testing Run unit tests and check coverage: ```bash go test -v -coverprofile=coverage.out -coverpkg=./... ./... ``` Aim for 80-90% coverage. Coverage below 80% will emit a warning in CI but will not fail the pipeline. ## CI/CD with Gitea Actions - **CI** (`.gitea/workflows/ci.yml`): Runs on push/PR to `develop`. Checks formatting (`gofmt`), runs `go vet`, tests with coverage, and builds the binary. - **Release** (`.gitea/workflows/release.yml`): Manual dispatch. Runs tests, bumps version, tags, builds and pushes Docker image to Gitea registry, creates a release with changelog. ## Production notes - Behind a reverse proxy, ensure the app is reachable at `/webhook` from DIUN. - Data is persisted to `diun.db` in the working directory by default. Set `DB_PATH` to change the location (e.g. `DB_PATH=/data/diun.db`). The deploy compose file uses a named volume at `/data`. - Set `WEBHOOK_SECRET` to protect the webhook endpoint if exposed publicly. ## License MIT — see `LICENSE`.