From 03702ff625b04242df78e5b17f6439fd44d98d55 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Thu, 23 Apr 2026 08:20:44 -0400 Subject: [PATCH] feat: add Helm chart and release workflow Adds a Helm chart under charts/hightower/ as an alternative to the Flux/Kustomize deployment. Distributed via GitHub Pages (gh-pages branch). Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/helm-release.yml | 53 ++++++++ charts/hightower/.helmignore | 7 + charts/hightower/Chart.yaml | 6 + charts/hightower/templates/NOTES.txt | 30 +++++ charts/hightower/templates/_helpers.tpl | 122 ++++++++++++++++++ .../hightower/templates/api-deployment.yaml | 62 +++++++++ charts/hightower/templates/api-role.yaml | 16 +++ .../hightower/templates/api-rolebinding.yaml | 14 ++ charts/hightower/templates/api-service.yaml | 13 ++ .../templates/api-serviceaccount.yaml | 8 ++ .../hightower/templates/router-configmap.yaml | 10 ++ .../templates/router-deployment.yaml | 66 ++++++++++ .../hightower/templates/router-service.yaml | 14 ++ .../templates/temporal-cnpg-cluster.yaml | 19 +++ .../templates/temporal-deployment.yaml | 66 ++++++++++ .../hightower/templates/temporal-service.yaml | 16 +++ .../hightower/templates/workspaces-pvc.yaml | 17 +++ charts/hightower/values.yaml | 86 ++++++++++++ 18 files changed, 625 insertions(+) create mode 100644 .github/workflows/helm-release.yml create mode 100644 charts/hightower/.helmignore create mode 100644 charts/hightower/Chart.yaml create mode 100644 charts/hightower/templates/NOTES.txt create mode 100644 charts/hightower/templates/_helpers.tpl create mode 100644 charts/hightower/templates/api-deployment.yaml create mode 100644 charts/hightower/templates/api-role.yaml create mode 100644 charts/hightower/templates/api-rolebinding.yaml create mode 100644 charts/hightower/templates/api-service.yaml create mode 100644 charts/hightower/templates/api-serviceaccount.yaml create mode 100644 charts/hightower/templates/router-configmap.yaml create mode 100644 charts/hightower/templates/router-deployment.yaml create mode 100644 charts/hightower/templates/router-service.yaml create mode 100644 charts/hightower/templates/temporal-cnpg-cluster.yaml create mode 100644 charts/hightower/templates/temporal-deployment.yaml create mode 100644 charts/hightower/templates/temporal-service.yaml create mode 100644 charts/hightower/templates/workspaces-pvc.yaml create mode 100644 charts/hightower/values.yaml diff --git a/.github/workflows/helm-release.yml b/.github/workflows/helm-release.yml new file mode 100644 index 0000000..bd8d615 --- /dev/null +++ b/.github/workflows/helm-release.yml @@ -0,0 +1,53 @@ +name: Helm Chart Release + +on: + push: + branches: [main] + paths: + - 'charts/hightower/**' + +permissions: + contents: write + +jobs: + release: + name: Lint, package & publish + runs-on: runners-farhoodlabs + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + + - name: Install Helm + uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0 + + - name: Lint chart + run: helm lint charts/hightower + + - name: Package chart + run: | + mkdir -p .helm-packages + helm package charts/hightower -d .helm-packages + + - name: Checkout gh-pages + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: gh-pages + path: gh-pages + fetch-depth: 0 + + - name: Update Helm repo index + run: | + cp .helm-packages/*.tgz gh-pages/ + helm repo index gh-pages --url https://farhoodlabs.github.io/hightower + + - name: Push to gh-pages + run: | + cd gh-pages + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add . + git diff --staged --quiet && echo "No changes to commit" && exit 0 + git commit -m "Release Helm chart $(ls *.tgz | head -1)" + git push diff --git a/charts/hightower/.helmignore b/charts/hightower/.helmignore new file mode 100644 index 0000000..d2cda19 --- /dev/null +++ b/charts/hightower/.helmignore @@ -0,0 +1,7 @@ +.DS_Store +.git +.gitignore +.idea +*.swp +*.bak +*.tmp diff --git a/charts/hightower/Chart.yaml b/charts/hightower/Chart.yaml new file mode 100644 index 0000000..a8b0497 --- /dev/null +++ b/charts/hightower/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: hightower +description: API-driven AI pentester built on Shannon, deployed as a service on Kubernetes +type: application +version: 0.1.0 +appVersion: "1.0.0" diff --git a/charts/hightower/templates/NOTES.txt b/charts/hightower/templates/NOTES.txt new file mode 100644 index 0000000..db06e59 --- /dev/null +++ b/charts/hightower/templates/NOTES.txt @@ -0,0 +1,30 @@ +Hightower has been deployed to namespace: {{ .Release.Namespace }} + +== Prerequisites == + +Ensure the following secrets exist in the {{ .Release.Namespace }} namespace: + + 1. {{ .Values.secrets.credentials }} + Used by the API and Router for application credentials. + + 2. {{ .Values.secrets.temporalDbApp }} + Used by Temporal for PostgreSQL authentication. + Required keys: username, password +{{- if .Values.cnpg.enabled }} + + The CNPG operator must be installed on this cluster. + https://cloudnative-pg.io/documentation/current/installation_upgrade/ +{{- else }} + + CNPG is disabled. Ensure temporal.db.host points to your PostgreSQL instance: + --set temporal.db.host=your-postgres-host +{{- end }} + +== Services == + + API: {{ include "hightower.api.fullname" . }}:{{ .Values.api.port }} + Temporal: {{ include "hightower.temporal.serviceName" . }}:{{ .Values.temporal.ports.grpc }} (gRPC) + {{ include "hightower.temporal.serviceName" . }}:{{ .Values.temporal.ports.webUi }} (Web UI) +{{- if .Values.router.enabled }} + Router: {{ include "hightower.router.fullname" . }}:{{ .Values.router.port }} +{{- end }} diff --git a/charts/hightower/templates/_helpers.tpl b/charts/hightower/templates/_helpers.tpl new file mode 100644 index 0000000..0796052 --- /dev/null +++ b/charts/hightower/templates/_helpers.tpl @@ -0,0 +1,122 @@ +{{/* +Chart name, truncated to 63 chars. +*/}} +{{- define "hightower.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Fully qualified app name, truncated to 63 chars. +*/}} +{{- define "hightower.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Chart label value. +*/}} +{{- define "hightower.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels. +*/}} +{{- define "hightower.labels" -}} +helm.sh/chart: {{ include "hightower.chart" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +API component name. +*/}} +{{- define "hightower.api.fullname" -}} +{{- printf "%s-api" (include "hightower.fullname" .) | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +API selector labels. +*/}} +{{- define "hightower.api.selectorLabels" -}} +app: {{ include "hightower.api.fullname" . }} +{{- end }} + +{{/* +Temporal component name. +*/}} +{{- define "hightower.temporal.fullname" -}} +{{- printf "%s-temporal" (include "hightower.fullname" .) | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Temporal service name (same as fullname). +*/}} +{{- define "hightower.temporal.serviceName" -}} +{{- include "hightower.temporal.fullname" . }} +{{- end }} + +{{/* +Temporal selector labels. +*/}} +{{- define "hightower.temporal.selectorLabels" -}} +app: {{ include "hightower.temporal.fullname" . }} +{{- end }} + +{{/* +Router component name. +*/}} +{{- define "hightower.router.fullname" -}} +{{- printf "%s-router" (include "hightower.fullname" .) | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Router selector labels. +*/}} +{{- define "hightower.router.selectorLabels" -}} +app: {{ include "hightower.router.fullname" . }} +{{- end }} + +{{/* +CNPG cluster name. +*/}} +{{- define "hightower.cnpg.fullname" -}} +{{- printf "%s-temporal-db" (include "hightower.fullname" .) | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +CNPG read-write service name (CNPG auto-creates -rw). +*/}} +{{- define "hightower.cnpg.serviceName" -}} +{{- printf "%s-rw" (include "hightower.cnpg.fullname" .) }} +{{- end }} + +{{/* +Service account name for the API. +*/}} +{{- define "hightower.serviceAccountName" -}} +{{- if .Values.api.serviceAccount.name }} +{{- .Values.api.serviceAccount.name }} +{{- else }} +{{- include "hightower.api.fullname" . }} +{{- end }} +{{- end }} + +{{/* +Postgres seeds host — use override or default to CNPG service. +*/}} +{{- define "hightower.temporal.postgresSeeds" -}} +{{- if .Values.temporal.db.host }} +{{- .Values.temporal.db.host }} +{{- else }} +{{- include "hightower.cnpg.serviceName" . }} +{{- end }} +{{- end }} diff --git a/charts/hightower/templates/api-deployment.yaml b/charts/hightower/templates/api-deployment.yaml new file mode 100644 index 0000000..b7e9cca --- /dev/null +++ b/charts/hightower/templates/api-deployment.yaml @@ -0,0 +1,62 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "hightower.api.fullname" . }} + labels: + {{- include "hightower.labels" . | nindent 4 }} + {{- include "hightower.api.selectorLabels" . | nindent 4 }} +spec: + replicas: {{ .Values.api.replicaCount }} + selector: + matchLabels: + {{- include "hightower.api.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "hightower.api.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: {{ include "hightower.serviceAccountName" . }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: api + image: "{{ .Values.api.image.repository }}:{{ .Values.api.image.tag }}" + imagePullPolicy: {{ .Values.api.image.pullPolicy }} + ports: + - containerPort: {{ .Values.api.port }} + name: http + env: + - name: TEMPORAL_ADDRESS + value: "{{ include "hightower.temporal.serviceName" . }}:{{ .Values.temporal.ports.grpc }}" + - name: WORKER_IMAGE + value: {{ .Values.api.workerImage }} + - name: K8S_NAMESPACE + value: {{ .Release.Namespace }} + envFrom: + - secretRef: + name: {{ .Values.secrets.credentials }} + volumeMounts: + - name: workspaces + mountPath: /app/workspaces + livenessProbe: + httpGet: + path: /healthz + port: {{ .Values.api.port }} + initialDelaySeconds: 5 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /readyz + port: {{ .Values.api.port }} + initialDelaySeconds: 10 + periodSeconds: 10 + {{- with .Values.api.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: workspaces + persistentVolumeClaim: + claimName: {{ include "hightower.fullname" . }}-workspaces diff --git a/charts/hightower/templates/api-role.yaml b/charts/hightower/templates/api-role.yaml new file mode 100644 index 0000000..2d46ba3 --- /dev/null +++ b/charts/hightower/templates/api-role.yaml @@ -0,0 +1,16 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "hightower.api.fullname" . }} + labels: + {{- include "hightower.labels" . | nindent 4 }} +rules: + - apiGroups: ["batch"] + resources: ["jobs"] + verbs: ["create", "get", "list", "delete", "watch"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["pods/log"] + verbs: ["get"] diff --git a/charts/hightower/templates/api-rolebinding.yaml b/charts/hightower/templates/api-rolebinding.yaml new file mode 100644 index 0000000..4c1a6da --- /dev/null +++ b/charts/hightower/templates/api-rolebinding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "hightower.api.fullname" . }} + labels: + {{- include "hightower.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "hightower.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: {{ include "hightower.api.fullname" . }} + apiGroup: rbac.authorization.k8s.io diff --git a/charts/hightower/templates/api-service.yaml b/charts/hightower/templates/api-service.yaml new file mode 100644 index 0000000..4797815 --- /dev/null +++ b/charts/hightower/templates/api-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "hightower.api.fullname" . }} + labels: + {{- include "hightower.labels" . | nindent 4 }} +spec: + selector: + {{- include "hightower.api.selectorLabels" . | nindent 4 }} + ports: + - name: http + port: {{ .Values.api.port }} + targetPort: {{ .Values.api.port }} diff --git a/charts/hightower/templates/api-serviceaccount.yaml b/charts/hightower/templates/api-serviceaccount.yaml new file mode 100644 index 0000000..d6664ac --- /dev/null +++ b/charts/hightower/templates/api-serviceaccount.yaml @@ -0,0 +1,8 @@ +{{- if .Values.api.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "hightower.serviceAccountName" . }} + labels: + {{- include "hightower.labels" . | nindent 4 }} +{{- end }} diff --git a/charts/hightower/templates/router-configmap.yaml b/charts/hightower/templates/router-configmap.yaml new file mode 100644 index 0000000..f604208 --- /dev/null +++ b/charts/hightower/templates/router-configmap.yaml @@ -0,0 +1,10 @@ +{{- if .Values.router.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "hightower.router.fullname" . }}-config + labels: + {{- include "hightower.labels" . | nindent 4 }} +data: + router-config.json: {{ .Values.router.config | toJson | quote }} +{{- end }} diff --git a/charts/hightower/templates/router-deployment.yaml b/charts/hightower/templates/router-deployment.yaml new file mode 100644 index 0000000..330e90b --- /dev/null +++ b/charts/hightower/templates/router-deployment.yaml @@ -0,0 +1,66 @@ +{{- if .Values.router.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "hightower.router.fullname" . }} + labels: + {{- include "hightower.labels" . | nindent 4 }} + {{- include "hightower.router.selectorLabels" . | nindent 4 }} +spec: + replicas: {{ .Values.router.replicaCount }} + selector: + matchLabels: + {{- include "hightower.router.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "hightower.router.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: router + image: "{{ .Values.router.image.repository }}:{{ .Values.router.image.tag }}" + imagePullPolicy: {{ .Values.router.image.pullPolicy }} + command: + - sh + - -c + - | + apt-get update && apt-get install -y gettext-base && + npm install -g {{ .Values.router.package }} && + mkdir -p /root/.claude-code-router && + envsubst < /config/router-config.json > /root/.claude-code-router/config.json && + ccr start + ports: + - containerPort: {{ .Values.router.port }} + envFrom: + - secretRef: + name: {{ .Values.secrets.credentials }} + env: + {{- range $key, $value := .Values.router.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + volumeMounts: + - name: config + mountPath: /config + readOnly: true + readinessProbe: + httpGet: + path: /health + port: {{ .Values.router.port }} + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + {{- with .Values.router.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: config + configMap: + name: {{ include "hightower.router.fullname" . }}-config +{{- end }} diff --git a/charts/hightower/templates/router-service.yaml b/charts/hightower/templates/router-service.yaml new file mode 100644 index 0000000..abbc723 --- /dev/null +++ b/charts/hightower/templates/router-service.yaml @@ -0,0 +1,14 @@ +{{- if .Values.router.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "hightower.router.fullname" . }} + labels: + {{- include "hightower.labels" . | nindent 4 }} +spec: + selector: + {{- include "hightower.router.selectorLabels" . | nindent 4 }} + ports: + - port: {{ .Values.router.port }} + targetPort: {{ .Values.router.port }} +{{- end }} diff --git a/charts/hightower/templates/temporal-cnpg-cluster.yaml b/charts/hightower/templates/temporal-cnpg-cluster.yaml new file mode 100644 index 0000000..59c2aee --- /dev/null +++ b/charts/hightower/templates/temporal-cnpg-cluster.yaml @@ -0,0 +1,19 @@ +{{- if .Values.cnpg.enabled }} +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: {{ include "hightower.cnpg.fullname" . }} + labels: + {{- include "hightower.labels" . | nindent 4 }} +spec: + instances: {{ .Values.cnpg.instances }} + storage: + size: {{ .Values.cnpg.storage.size }} + storageClass: {{ .Values.cnpg.storage.storageClass }} + bootstrap: + initdb: + database: {{ .Values.temporal.db.name }} + owner: {{ .Values.temporal.db.name }} + postInitSQL: + - CREATE DATABASE {{ .Values.temporal.db.visibilityName }} OWNER {{ .Values.temporal.db.name }}; +{{- end }} diff --git a/charts/hightower/templates/temporal-deployment.yaml b/charts/hightower/templates/temporal-deployment.yaml new file mode 100644 index 0000000..08182fa --- /dev/null +++ b/charts/hightower/templates/temporal-deployment.yaml @@ -0,0 +1,66 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "hightower.temporal.fullname" . }} + labels: + {{- include "hightower.labels" . | nindent 4 }} + {{- include "hightower.temporal.selectorLabels" . | nindent 4 }} +spec: + replicas: {{ .Values.temporal.replicaCount }} + selector: + matchLabels: + {{- include "hightower.temporal.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "hightower.temporal.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: temporal + image: "{{ .Values.temporal.image.repository }}:{{ .Values.temporal.image.tag }}" + imagePullPolicy: {{ .Values.temporal.image.pullPolicy }} + ports: + - containerPort: {{ .Values.temporal.ports.grpc }} + name: grpc + - containerPort: {{ .Values.temporal.ports.webUi }} + name: web-ui + env: + - name: DB + value: {{ .Values.temporal.db.type }} + - name: DB_PORT + value: {{ .Values.temporal.db.port | quote }} + - name: POSTGRES_SEEDS + value: {{ include "hightower.temporal.postgresSeeds" . }} + - name: DBNAME + value: {{ .Values.temporal.db.name }} + - name: VISIBILITY_DBNAME + value: {{ .Values.temporal.db.visibilityName }} + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: {{ .Values.secrets.temporalDbApp }} + key: username + - name: POSTGRES_PWD + valueFrom: + secretKeyRef: + name: {{ .Values.secrets.temporalDbApp }} + key: password + - name: NUM_HISTORY_SHARDS + value: {{ .Values.temporal.db.numHistoryShards | quote }} + - name: SKIP_DB_CREATE + value: {{ .Values.temporal.db.skipDbCreate | quote }} + readinessProbe: + tcpSocket: + port: {{ .Values.temporal.ports.grpc }} + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 15 + {{- with .Values.temporal.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} diff --git a/charts/hightower/templates/temporal-service.yaml b/charts/hightower/templates/temporal-service.yaml new file mode 100644 index 0000000..c47b983 --- /dev/null +++ b/charts/hightower/templates/temporal-service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "hightower.temporal.serviceName" . }} + labels: + {{- include "hightower.labels" . | nindent 4 }} +spec: + selector: + {{- include "hightower.temporal.selectorLabels" . | nindent 4 }} + ports: + - name: grpc + port: {{ .Values.temporal.ports.grpc }} + targetPort: {{ .Values.temporal.ports.grpc }} + - name: web-ui + port: {{ .Values.temporal.ports.webUi }} + targetPort: {{ .Values.temporal.ports.webUi }} diff --git a/charts/hightower/templates/workspaces-pvc.yaml b/charts/hightower/templates/workspaces-pvc.yaml new file mode 100644 index 0000000..72e5545 --- /dev/null +++ b/charts/hightower/templates/workspaces-pvc.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "hightower.fullname" . }}-workspaces + labels: + {{- include "hightower.labels" . | nindent 4 }} + {{- if .Values.workspaces.retain }} + annotations: + helm.sh/resource-policy: keep + {{- end }} +spec: + accessModes: + - {{ .Values.workspaces.accessMode }} + storageClassName: {{ .Values.workspaces.storageClass }} + resources: + requests: + storage: {{ .Values.workspaces.size }} diff --git a/charts/hightower/values.yaml b/charts/hightower/values.yaml new file mode 100644 index 0000000..858ea68 --- /dev/null +++ b/charts/hightower/values.yaml @@ -0,0 +1,86 @@ +nameOverride: "" +fullnameOverride: "" +imagePullSecrets: [] + +# Externally-managed secrets (chart never creates these) +secrets: + credentials: hightower-credentials + temporalDbApp: hightower-temporal-db-app + +# Shared workspaces PVC +workspaces: + storageClass: ceph-filesystem + accessMode: ReadWriteMany + size: 10Gi + retain: false # true → add helm.sh/resource-policy: keep + +# --- API --- +api: + replicaCount: 1 + image: + repository: ghcr.io/farhoodlabs/hightower-api + tag: sha-a0efe7604ebc2f27cc37ee88f117ae619e57003f + pullPolicy: Always + port: 3000 + workerImage: ghcr.io/farhoodlabs/shannon:latest + resources: + requests: + memory: 128Mi + cpu: 100m + limits: + memory: 256Mi + serviceAccount: + create: true + name: "" + +# --- Temporal --- +temporal: + replicaCount: 1 + image: + repository: temporalio/auto-setup + tag: latest + pullPolicy: IfNotPresent + ports: + grpc: 7233 + webUi: 8233 + db: + type: postgres12 + port: "5432" + host: "" # defaults to -temporal-db-rw via helper + name: temporal + visibilityName: temporal_visibility + numHistoryShards: "4" + skipDbCreate: "true" + resources: + requests: + memory: 512Mi + cpu: 250m + limits: + memory: 1Gi + +# --- CNPG PostgreSQL Cluster (optional, requires CNPG operator) --- +cnpg: + enabled: true + instances: 1 + storage: + size: 5Gi + storageClass: ceph-block + +# --- Router (optional) --- +router: + enabled: true + replicaCount: 1 + image: + repository: node + tag: "20-slim" + pullPolicy: IfNotPresent + port: 3456 + package: "@musistudio/claude-code-router" + env: + HOST: "0.0.0.0" + resources: + requests: + memory: 128Mi + cpu: 100m + limits: {} + config: {} # serialized to router-config.json