118 lines
4.4 KiB
YAML
118 lines
4.4 KiB
YAML
# pragent pilot — central dashboard service.
|
|
#
|
|
# Read-only overview + per-repo / per-PR drilldown over the same SQLite
|
|
# feedback DB the webhook writes. Also mutates `.pr-review.json` on covered
|
|
# repos via the Gitea contents API (Tasks C+D in pilot/dashboard.py). Same
|
|
# image as the webhook (`pragent-webhook:optin`) — all pilot modules are
|
|
# baked in at /app/pilot/.
|
|
#
|
|
# Routes: GET / (overview), GET /r/<o>/<n> (repo), GET /r/<o>/<n>/<i> (PR),
|
|
# GET /r/<o>/<n>/<i>/raw (PR markdown raw), GET /login, GET /static/style.css,
|
|
# POST /login, POST /r/<o>/<n>/edit.
|
|
#
|
|
# Auth: PRAGENT_DASHBOARD_TOKEN in the pragent-webhook Secret, cookie
|
|
# `pragent_dash=<token>`, single-user. Empty / unset = no auth (tailnet-only).
|
|
#
|
|
# NodePort 30082 — only reachable on the Tailscale / LAN side of kubernets
|
|
# (100.74.17.70 / 192.168.1.80) until/unconfigured. Mirrors pragent-webhook.yaml
|
|
# in every other respect (uid 10001, nodeSelector, /data PVC).
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: pragent-dashboard
|
|
namespace: pragent
|
|
labels:
|
|
app: pragent-dashboard
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: pragent-dashboard
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: pragent-dashboard
|
|
spec:
|
|
# Same node as the webhook — holds the headroom proxy + the /data PVC.
|
|
nodeSelector:
|
|
kubernetes.io/hostname: kubernets
|
|
# Dashboard is read-only over /data and only mutates Gitea (not local
|
|
# files), so unprivileged is fine. fsGroup matches the image's USER
|
|
# directive (10001) so the RO mount is readable.
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 10001
|
|
runAsGroup: 10001
|
|
fsGroup: 10001
|
|
containers:
|
|
- name: dashboard
|
|
image: pragent-webhook:optin
|
|
imagePullPolicy: Never
|
|
workingDir: /app
|
|
command: ["python3", "-m", "pilot.dashboard"]
|
|
ports:
|
|
- name: http
|
|
containerPort: 8081
|
|
env:
|
|
- name: PRAGENT_FEEDBACK_DB
|
|
value: /data/feedback.db
|
|
- name: PRAGENT_GITEA_API
|
|
value: http://gitea-http.gitea.svc.cluster.local:3000
|
|
# Dashboard reads DASHBOARD_PORT (not PORT) — verified in
|
|
# pilot/dashboard.py:51. Default 8081 if unset.
|
|
- name: DASHBOARD_PORT
|
|
value: "8081"
|
|
# Used by /r/<o>/<n>/edit to PUT updated JSON to the repo's
|
|
# contents API. Reuses the same bot token the webhook uses.
|
|
- name: PRAGENT_BOT_TOKEN
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: pragent-webhook
|
|
key: PRAGENT_BOT_TOKEN
|
|
# Auth cookie value. Add to the pragent-webhook Secret with:
|
|
# kubectl patch secret pragent-webhook -n pragent --type=json \
|
|
# -p='[{"op":"add","path":"/data/PRAGENT_DASHBOARD_TOKEN","value":"<base64>"}]'
|
|
- name: PRAGENT_DASHBOARD_TOKEN
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: pragent-webhook
|
|
key: PRAGENT_DASHBOARD_TOKEN
|
|
# /data is read-only — the dashboard doesn't write the SQLite file;
|
|
# .pr-review.json mutations go through the Gitea contents API, not
|
|
# local fs. RO avoids any chance of two pods racing the same RWO PVC.
|
|
volumeMounts:
|
|
- name: feedback-data
|
|
mountPath: /data
|
|
readOnly: true
|
|
# No /health route in dashboard.py (returns 404 on unknown paths).
|
|
# Probes omitted intentionally — see pilot/dashboard.py:687-721.
|
|
# Resources: dashboard is read-heavy + tiny writes. /data RO + no
|
|
# subprocess fan-out (no opencode) keeps footprint small.
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 256Mi
|
|
limits:
|
|
cpu: 500m
|
|
memory: 512Mi
|
|
volumes:
|
|
- name: feedback-data
|
|
persistentVolumeClaim:
|
|
claimName: pragent-feedback-data
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: pragent-dashboard
|
|
namespace: pragent
|
|
spec:
|
|
selector:
|
|
app: pragent-dashboard
|
|
ports:
|
|
- name: http
|
|
port: 80
|
|
targetPort: http
|
|
nodePort: 31540
|
|
type: NodePort
|
|
# 31540 — auto-allocated at first apply (30082 was already taken by
|
|
# habitsnow/habitsnow-proxy). Tailscale / LAN only until a Caddy route is set. |