diff --git a/.ai/instructions/skills/helm.instructions.md b/.ai/instructions/skills/helm.instructions.md index 2edc568..1e0a7cc 100644 --- a/.ai/instructions/skills/helm.instructions.md +++ b/.ai/instructions/skills/helm.instructions.md @@ -11,6 +11,61 @@ Before writing a new template, config, or resource: --- +## 🚫 Never Hardcode Namespace, Release Name, or Installation-Specific Values + +**A Helm chart must be fully agnostic about where and how it is installed.** + +This is a hard rule — no exceptions. + +### Namespace + +Never hardcode a namespace in any template. The namespace is set by the deployer at install time. + +```yaml +# ❌ FORBIDDEN — always +metadata: + namespace: my-app + namespace: production + namespace: default + +# ✅ Required — or omit namespace entirely and let Helm inject it +metadata: + namespace: {{ .Release.Namespace }} +``` + +If a resource must reference another namespace (e.g. a NetworkPolicy peer), expose it as a required value: + +```yaml +metadata: + namespace: {{ required "global.namespace is required" .Values.global.targetNamespace }} +``` + +### Release Name + +Never hardcode a release name. Use `.Release.Name` to derive resource names: + +```yaml +# ❌ FORBIDDEN +name: my-app-service +name: myapp-ingress + +# ✅ Required +name: {{ include "mychart.fullname" . }} +# or +name: {{ .Release.Name }}-service +``` + +### Why — IaC Principle + +The chart is infrastructure code. It must be deployable to any cluster, any namespace, any environment, by any deployer — without editing the chart itself. Installation-specific decisions belong exclusively in `values..yaml` in the deployment repo. + +``` +❌ Wrong: chart decides where it lives +✅ Right: deployer decides where it lives — chart only describes what it is +``` + +--- + ## 🏠 Resource Ownership **Every Kubernetes resource must have exactly one owner. Never duplicate.**