From 421086f845f687fcde9b23bc54e464a955f84e48 Mon Sep 17 00:00:00 2001 From: Story Crater Bot <19826264+Riotpiaole@users.noreply.github.com> Date: Tue, 14 Jul 2026 23:37:54 -0700 Subject: [PATCH] docs(iac): enforce single source of truth for infrastructure Add IaC practice section to coding-standards.md: - All infrastructure state via Terraform or Helm (never ad-hoc scripts) - Clear division: Terraform owns helm releases/namespaces/storage/state - Anti-pattern: split bucket definitions across multiple files - Bootstrap-only exception: document one-time setup with rationale Rationale: prevents state drift, credential duplication, and unclear ownership. --- project-usage/coding-standards.md | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/project-usage/coding-standards.md b/project-usage/coding-standards.md index 897e501..d26ced2 100644 --- a/project-usage/coding-standards.md +++ b/project-usage/coding-standards.md @@ -70,6 +70,59 @@ set: --- +## Infrastructure as Code (IaC) — Single Source of Truth + +**Core principle:** All infrastructure state must be declaratively managed via Terraform or Helm (via helmfile + Terraform). No ad-hoc scripts, manual kubectl, or side-by-side resource definitions. + +### Terraform + Helm Division of Labor + +- **Terraform manages:** + - Helm releases (chart + version + values) + - Namespaces + - StorageClasses + - Static Kubernetes resources (RBAC, NetworkPolicies, IngressClasses) + - Cloud infrastructure (Vault, S3 backends, secrets) + - State persistence (S3 backend in MinIO) + +- **Helmfile manages:** + - Chart release ordering via `needs:` + - Environment-specific value interpolation (Go templating, not shell) + - Hook workflows (pre/post-sync orchestration) + - **Never use helmfile for one-off bucket creation, job runs, or manual setup** — those belong in Terraform or a documented bootstrap process + +- **Kubernetes manifests (`k8s/`) manage:** + - ArgoCD applications (single source of truth for GitOps) + - Service definitions that ArgoCD syncs + - **Never manage app objects (Deployments, StatefulSets) directly** — let helm + ArgoCD own them + +### Anti-Pattern: Ad-Hoc Resource Creation + +❌ **Bad:** Separate `minio-buckets.tf` using `aws_s3_bucket` resources + post-deploy scripts +- Split responsibility: some buckets in Terraform, others in helmfile, others manual +- State drift: unclear what's managed where +- Credential duplication: secrets in multiple places + +✅ **Good:** Single source in `minio.tf` helm release: +```hcl +buckets = [ + { name = "terraform-state", policy = "none", purge = false }, + { name = "vault", policy = "none", purge = false }, + ... +] +``` +- One place to define, one place to audit +- Credentials in variables + Vault, not scattered +- TF state tracks all changes + +### When to Break the Rule + +Only when **explicitly documented**: +- Bootstrap scripts (one-time cluster init) — commit to `scripts/` with clear "run once" warning +- Temporary debugging (never leave in git) — stash or delete before committing +- Manual steps for constraint (e.g., "create namespace before ArgoCD bootstraps") — document in `TROUBLESHOOTING.md` with rationale + +--- + ## YAML & ConfigMap/Secret Patterns ### Secret Field Naming