# ADR-A1 — Cache upstream charts in `helm-templates/` (vs. pull on the fly) > **Status:** Accepted (de facto — current state of the repo). > **Repo:** `devops-infra-helm-charts`. > **Related:** [docs/architecture.md](../../docs/architecture.md), [SANCTITY_RULES R7](../../docs/global/SANCTITY_RULES.md), [update-chart-version.md](../../docs/platform/procedures/update-chart-version.md), [fork-upstream-chart.md](../../docs/platform/procedures/fork-upstream-chart.md). --- ## Context Argo CD can render a Helm release in two ways: 1. **Pull on the fly** — `Application.spec.source.repoURL` points at an upstream Helm registry; `chart:` names the chart. Argo CD pulls the chart at sync time. 2. **Cache locally** — the chart lives in a git repo (this one), and `Application.spec.source.path` points at it. Argo CD reads the chart files from git directly. This repo has chosen **caching**. Every chart consumed by Meesho's GKE infra fleet has a directory in `helm-templates//` — usually a thin wrapper whose `Chart.yaml` declares the upstream chart as a dependency, with the resolved subchart materialised in `Chart.lock` and `charts/-.tgz`. ## Decision Cache upstream charts in `helm-templates/` as thin wrapper directories with pinned `dependencies[].version` and a committed `Chart.lock`. Do not configure Argo CD to pull charts directly from upstream registries. ## Rationale 1. **Repeatable renders.** A chart-version bump in this repo is a git diff; a chart-version "bump" via upstream pull is whatever the registry returns at sync time. Reproducibility on rollback requires the chart bytes to be in git. 2. **Air-gapped reviewability.** A reviewer can read the `Chart.yaml`, the `Chart.lock`, and the subchart `.tgz` to know exactly what will render. With on-the-fly pulls, the reviewer trusts the upstream registry hasn't moved a tag. 3. **Network independence at sync time.** Argo CD's reconcile loop doesn't need outbound network to upstream registries. If GitHub is reachable, sync works; if it isn't, nothing's deploying anyway. 4. **Supply-chain control.** Pinning `dependencies[].version` plus committing `Chart.lock` means the *digest* of each subchart `.tgz` is recorded. A registry compromise that re-publishes a tag with new content is detected by the lockfile mismatch. 5. **Forking is local.** When upstream lacks a feature or has a bug, [fork-upstream-chart](../../docs/platform/procedures/fork-upstream-chart.md) is a local edit. No "wait for upstream merge"; the patch lives in our repo until upstream catches up. 6. **Render-tooling unchanged.** Reviewer-side `helm template helm-templates/ -f overrides.yaml` works locally without any registry config. Pre-merge validation is just `helm template` against the directory. ## Consequences ### Accepted - **Repo bigger.** 74 chart directories totalling tens of MBs of subchart `.tgz` files. - **Manual update cadence.** A new upstream release isn't picked up automatically. Someone has to bump `dependencies[].version` and run `helm dependency update`. ([update-chart-version](../../docs/platform/procedures/update-chart-version.md)) - **Forking risk.** Editing `helm-templates//templates/` casually creates an accidental fork that gets clobbered next `helm dependency update`. ([SANCTITY_RULES R7](../../docs/global/SANCTITY_RULES.md)) - **Lock-step requirement.** A `Chart.yaml` bump without a refreshed `Chart.lock` is incomplete — Argo CD reads the lockfile, so the version change silently no-ops. ### Mitigated - **Update-chart-version procedure** documents the lock-step requirement explicitly. - **Versioned siblings** ([ADR-A2](ADR-A2-blue-green-sibling-pattern.md)) handle major-version bumps without losing the old chart. - **Pre-merge `helm template`** catches values incompatibilities before merge. ### Open - **Stale charts.** Some directories in `helm-templates/` have no current consumer (`grep -rl '' helm-overrides` empty). A periodic clean-up exercise has not been formalised. - **Subchart `.tgz` size pollution in git history.** Every `helm dependency update` writes a new `.tgz` to `charts/`. Over years, the repo's history grows accordingly. Whether to switch to a Helm-OCI-pull model is an open question. - **Chart-bump notification.** Nothing currently alerts the team when an upstream advisory affects a chart we have pinned at an old version. Manual diligence today. ## Alternatives considered | Alternative | Why not | |-------------|---------| | **Pull-on-the-fly from upstream registries.** | Reproducibility, network dependency, supply-chain risk all worse. | | **Fully vendor every chart's `templates/`** (no `dependencies[]`, no subchart `.tgz`). | Massive diff churn on every upstream release; worse fork hygiene. | | **Use Helm OCI registries** as a middle ground (pull `.tgz` from a private registry instead of git). | Plausible Phase-2 work. Adds an extra service to maintain; doesn't solve forking. Not done today. | | **Use `kustomize` instead of Helm.** | Most upstream charts are Helm; rewriting every chart's templates as Kustomize patches would be enormous. | ## References - Argo CD Helm chart source docs: - This repo's chart directory layout: [docs/architecture.md §Module boundaries](../../docs/architecture.md). - Bump procedure: [update-chart-version](../../docs/platform/procedures/update-chart-version.md). - Fork procedure: [fork-upstream-chart](../../docs/platform/procedures/fork-upstream-chart.md).