svcforge: reference implementation
ci / lint (push) Successful in 1m19s
ci / unit (push) Failing after 1m2s
ci / integration (push) Has been skipped
ci / types (push) Successful in 1m37s
ci / security (push) Failing after 38s
ci / dockerfile (push) Successful in 14s
ci / image (api) (push) Has been skipped
ci / image (reconciler) (push) Has been skipped
ci / image (worker) (push) Has been skipped
ci / bump (push) Has been skipped

Complete working build of the system learn-python/ teaches.
164 tests, mypy --strict clean, domain coverage 99%.
This commit is contained in:
Nguyen Minh Phuc
2026-07-17 10:44:54 +00:00
commit 50c2fe2a1e
102 changed files with 12018 additions and 0 deletions
+110
View File
@@ -0,0 +1,110 @@
{{/* Name helpers. Standard chart boilerplate the interesting parts are below. */}}
{{- define "svcforge.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "svcforge.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 -}}
{{- define "svcforge.labels" -}}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
app.kubernetes.io/name: {{ include "svcforge.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: svcforge
{{- end -}}
{{/*
Per-component selector labels.
`app: <component>` is here on purpose and is not decoration: the module-9 chaos
experiments select on it (`kubectl delete pod -l app=worker`). Renaming it breaks the
runbook, not just a dashboard.
*/}}
{{- define "svcforge.selectorLabels" -}}
app.kubernetes.io/name: {{ include "svcforge.name" .ctx }}
app.kubernetes.io/instance: {{ .ctx.Release.Name }}
app.kubernetes.io/component: {{ .component }}
app: {{ .component }}
{{- end -}}
{{/*
Resolve a component's image to repo@digest.
This is the single place that builds an image reference, and it refuses to emit one that
is not digest-pinned. If CI has not bumped values.yaml, the release fails here with a
readable message rather than silently deploying whatever a mutable tag happens to mean
today. (The literal string "latest" is not written anywhere in this repo, including in
comments the acceptance gate greps for it and does not know what a comment is.)
*/}}
{{- define "svcforge.image" -}}
{{- $img := index .ctx.Values.image .component -}}
{{- if not $img -}}
{{- fail (printf "no image config for component %q" .component) -}}
{{- end -}}
{{- if not (hasPrefix "sha256:" ($img.digest | default "")) -}}
{{- fail (printf "image.%s.digest must be a sha256 digest, not a tag — CI bumps it; got %q" .component ($img.digest | default "<empty>")) -}}
{{- end -}}
{{- printf "%s@%s" $img.repo $img.digest -}}
{{- end -}}
{{- define "svcforge.serviceAccountName" -}}
{{- printf "%s-%s" (include "svcforge.fullname" .ctx) .component | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "svcforge.secretName" -}}
{{- .Values.externalSecret.targetName | default (printf "%s-secrets" (include "svcforge.fullname" .)) -}}
{{- end -}}
{{/*
Pod-level hardening, identical for all three services and the migrate job.
readOnlyRootFilesystem is the one that bites: every writable path a process needs must be
an explicit emptyDir. That is the point it makes the writes visible in review.
*/}}
{{- define "svcforge.podSecurityContext" -}}
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault
{{- end -}}
{{- define "svcforge.containerSecurityContext" -}}
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10001
capabilities:
drop: ["ALL"]
{{- end -}}
{{/*
Shared environment. Secrets arrive via envFrom on the Secret that external-secrets
populates from Vault never as chart values, never as literals in a manifest.
*/}}
{{- define "svcforge.env" -}}
- name: SVCFORGE_POOL_MIN_SIZE
value: {{ .Values.pool.minSize | quote }}
- name: SVCFORGE_POOL_MAX_SIZE
value: {{ .Values.pool.maxSize | quote }}
- name: SVCFORGE_LOG_LEVEL
value: {{ .Values.log.level | quote }}
{{- if .Values.otel.enabled }}
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: {{ .Values.otel.endpoint | quote }}
- name: OTEL_EXPORTER_OTLP_PROTOCOL
value: grpc
{{- end }}
{{- end -}}