diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 31a63a7..73359f4 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -16,12 +16,45 @@ jobs: go-version: '1.26' - name: Run tests with coverage run: | - go test -v -coverprofile=coverage.out ./... + go test -v -coverprofile=coverage.out -coverpkg=./... ./... go tool cover -func=coverage.out | tee coverage.txt cov=$(go tool cover -func=coverage.out | grep total: | awk '{print substr($3, 1, length($3)-1)}') cov=${cov%.*} if [ "$cov" -lt 80 ]; then echo "::warning::Test coverage is below 80% ($cov%)" fi - - name: Build Docker image - run: docker build -t diun-webhook-dashboard . \ No newline at end of file + - name: Build binary + run: go build ./... + + docker: + runs-on: dind + needs: build-test + if: gitea.event_name == 'push' + container: + image: docker:cli + services: + dind: + image: docker:dind + options: --privileged + env: + DOCKER_TLS_CERTDIR: "" + env: + DOCKER_HOST: tcp://dind:2375 + steps: + - name: Checkout code + uses: actions/checkout@v6 + - name: Log in to Gitea registry + run: | + REGISTRY="${{ gitea.server_url }}" + REGISTRY="${REGISTRY#https://}" + REGISTRY="${REGISTRY#http://}" + echo "${{ secrets.GITEA_TOKEN }}" | docker login "$REGISTRY" -u "${{ gitea.actor }}" --password-stdin + - name: Build and push + run: | + REGISTRY="${{ gitea.server_url }}" + REGISTRY="${REGISTRY#https://}" + REGISTRY="${REGISTRY#http://}" + IMAGE="$REGISTRY/${{ gitea.repository }}" + docker build -t "$IMAGE:${{ gitea.sha }}" -t "$IMAGE:latest" . + docker push "$IMAGE:${{ gitea.sha }}" + docker push "$IMAGE:latest" \ No newline at end of file diff --git a/.idea/copilot.data.migration.ask2agent.xml b/.idea/copilot.data.migration.ask2agent.xml new file mode 100644 index 0000000..1f2ea11 --- /dev/null +++ b/.idea/copilot.data.migration.ask2agent.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..084b6ad --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,40 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Commands + +```bash +# Run all tests with coverage +go test -v -coverprofile=coverage.out -coverpkg=./... ./... + +# Run a single test +go test -v -run TestWebhookHandler ./test/diunwebhook/ + +# Run the app locally +go run ./cmd/diunwebhook/ + +# Build Docker image +docker build -t diun-webhook-dashboard . + +# Run with Docker Compose +docker compose up -d +``` + +CI warns (but does not fail) when coverage drops below 80%. + +## Architecture + +The app is a minimal Go HTTP server that receives [DIUN](https://crazymax.dev/diun/) webhook events and exposes them via a JSON API and static HTML dashboard. All state is in-memory (no persistence). + +**Package layout:** +- `pkg/diunwebhook/` — core library: `DiunEvent` struct, in-memory `updates` map (guarded by `sync.Mutex`), and HTTP handlers (`WebhookHandler`, `UpdatesHandler`) +- `cmd/diunwebhook/main.go` — wires the handlers and static file server onto `net/http`'s default mux, listens on `:8080` +- `test/diunwebhook/` — external test package (`package diunwebhook_test`) that imports `pkg/diunwebhook`; uses `httptest` for handler tests +- `static/` — served verbatim at `/` + +**Key data flow:** +1. DIUN POSTs JSON to `/webhook` → `WebhookHandler` decodes into `DiunEvent` → stored in `updates[event.Image]` (latest event per image wins) +2. Dashboard JS polls `GET /api/updates` → `UpdatesHandler` returns full map as JSON + +**Test helpers exposed from the library package** (not part of the public API, only for tests): `GetUpdatesMap()`, `UpdatesReset()`, `UpdateEvent()`.