Files
docs/k8s/docs-app.yaml
T
zandClaude Opus 4.8 d557d63aa3 fix(docs-deploy): one registry — ghcr.io/hanzoai/docs (CR pull == CI push)
The docs App CR + pods pull ghcr.io/hanzoai/docs (public), but deploy-docs.yml
built+pushed+patched ghcr.io/hanzo-docs/docs (private) → every operator deploy
ErrImagePull'd (kept alive only by a manual crane-copy). Converge both on the
canonical public ghcr.io/hanzoai/docs per the Hanzo registry rule: CI push target
now equals the CR pull source. Immutable SHA tag only (drop floating :latest).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 07:09:39 -07:00

66 lines
2.7 KiB
YAML

# docs.hanzo.ai — the ONE canonical serve: a hanzo-operator App CR.
#
# WHY AN App CR (not a hand-rolled Deployment/Service/Ingress):
# The hanzoai/ingress controller only routes ingresses the operator
# reconciles (analytics, bot-docs, team-docs all work this way). A
# hand-applied ingress for docs.hanzo.ai was NEVER admitted — the
# controller fell through to the default *.hanzo.ai cert and 404'd every
# path. Modeled exactly on the working `bot-docs` App; the only deltas are
# the image, containerPort (our static server listens on 3000, not 80),
# and the host.
#
# The operator reconciles this into Deployment + Service + Ingress with the
# correct route registration and a per-host cert via letsencrypt-prod.
#
# CD: bump .spec.image.tag to the pushed commit SHA — the operator rolls it.
# Immutable SHA tags only; never a floating :latest in the cluster.
apiVersion: hanzo.ai/v1
kind: App
metadata:
name: docs
namespace: hanzo
labels:
app.kubernetes.io/name: docs
app.kubernetes.io/part-of: platform
spec:
component: docs
partOf: platform
replicas: 2
image:
# ONE registry for docs: ghcr.io/hanzoai/docs (public). This is where the
# platform-native fabric (POST /v1/runner → buildkit Job, see root Dockerfile)
# pushes AND where deploy-docs.yml pushes — CR pull source == CI push target,
# per the "Hanzo → ghcr.io/hanzoai/*" registry rule. NEVER ghcr.io/hanzo-docs/*
# (a private package the pods' ghcr-secret can't pull → ErrImagePull).
repository: ghcr.io/hanzoai/docs
tag: sha-40e315ec0
pullPolicy: IfNotPresent
imagePullSecrets:
- name: ghcr-secret
# hanzoai/static ships a locked-down default CSP (default-src 'none') that
# blocks all client JS — including the docs' own interactivity and the Scalar
# API reference at /reference. HANZO_STATIC_CSP relaxes it to a secure docs
# policy (self + inline/eval for the OpenAPI renderer) while keeping
# frame-ancestors/object-src locked. Browsers receive both this and the
# ingress CSP and enforce the intersection, so this must stay permissive
# enough for Scalar to execute.
env:
- name: HANZO_STATIC_CSP
value: "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob:; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https://api.hanzo.ai https://analytics.hanzo.ai; worker-src 'self' blob:; child-src 'self' blob:; manifest-src 'self'"
ports:
- name: http
containerPort: 3000
servicePort: 80
ingress:
enabled: true
hosts:
- docs.hanzo.ai
tls: true
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 50m
memory: 64Mi