# ADR-0012: String-interpolated Helm values from user config.yaml **Status:** Accepted **Category:** COMMUNICATION **Date decided:** Project inception **Date documented:** 2026-05-13 ## Context ArgoCD deploys are driven by Helm charts whose `values.yaml` files are produced per-build by `deployArgoCD.groovy`. The inputs are a service's `deployment.yaml` plus a handful of pipeline-derived fields (image tag, pod resources, JVM heap, etc.). Helm chart `values.yaml` is itself a templating surface — Helm's own `{{ .Values.x }}` syntax reads these files at install time — so anything produced here is interpreted as a template by the next layer, not as plain data. ## Decision `deployArgoCD.groovy` builds the rendered `values.yaml` by string-substituting fields into a stub template via chained `.replaceAll()` calls, rather than constructing it via a YAML library or a typed DTO and re-serialising. The team treats Helm's chart-values surface as a template-on-template stack: re-serialising via a YAML library would re-introduce template-syntax escaping problems (quoting `{{ }}`, preserving multi-line string semantics, handling Helm-specific structural tags) — keeping the entire pipeline string-native is the simpler invariant. ## Alternatives Considered No alternatives were explicitly evaluated by the team during this interview. The "use a typed YAML library / DTO and re-serialise" approach was acknowledged as the obvious counter-proposal but was rejected on the template-on-template grounds above. ## Consequences **Positive:** - The renderer stays a one-layer string substitution — easy to read, easy to debug from a Jenkins console log. - No risk of a typed re-serialisation silently re-escaping Helm `{{ }}` templates or stripping comments. - Matches the rest of the pipeline, which is string-and-`sh` heavy. **Negative:** - User-supplied config values are not validated against a schema before substitution — a service's `deployment.yaml` containing unescaped quotes, colons, or newlines can produce a malformed `values.yaml` (review-learnings PR #343 flagged this). - The implicit YAML-injection risk depends on every consumer service writing well-formed `deployment.yaml` — there is no guardrail in the library itself. - Adding a new field requires editing the template stub AND the substitution chain in `deployArgoCD.groovy` together — easy to drift. **Neutral:** - The decision lives entirely in `deployArgoCD.groovy`; switching strategies in future would be local to that file. ## Constraints - Helm chart values are interpreted as templates downstream — any solution must preserve template literals without escaping them. - The shared library runs in the Jenkins sandbox, which constrains which Java / Groovy serialisation APIs are safely callable. ## Current Assessment - **Adequate with caveats** — the strategy is defensible, but the lack of input-validation guardrails (the YAML-injection surface called out in review learnings) remains an open risk. A targeted schema-validation pass before substitution would mitigate it without changing the rendering strategy. ## Related Decisions - [ADR-0007: GitOps Deployments via Strict 4-Step ArgoCD Sync Sequence](0007-gitops-via-argocd-4-step-sync-sequence.md) — the deploy mechanism that consumes the rendered `values.yaml`. - [ADR-0009: JVM Heap Auto-Derived from Pod memory_request](0009-jvm-heap-auto-derived-from-pod-memory-request.md) — another pipeline-derived input to the same `values.yaml`. ## Notes - Key files: `src/com/meesho/stages/deployArgoCD.groovy` - Open risk: review-learnings PR #343 flagged the YAML-injection surface — input validation is the recommended mitigation. - Discovery id: COMMUNICATION-2