You maintain a shared Helm chart. A breaking change is coming. Which teams across the org are running it — and at which version?
You own a shared Helm chart. Maybe it’s a platform-services chart that bundles your observability stack: Prometheus, Alertmanager, and a custom metrics exporter your platform team maintains. Maybe it’s an ingress-gateway chart that every product team deploys at the edge of their namespace. Maybe it’s a company-wide chart for spinning up a standard service with your logging sidecar, network policies, and PodDisruptionBudget pre-configured.
It started as a convenience. Teams stopped reinventing the same Kubernetes manifests. A dozen clusters adopted it. Then more. Some teams deploy it via ArgoCD. Some use Flux. Some have helm install calls baked into their CI pipelines. Some consume it as a subchart inside their own umbrella chart. Some use a plain Chart.yaml with a dependencies: block and run helm dependency update before deploy.
Now you need to change it. Maybe a value key is being renamed — replicaCount is becoming replicas to align with upstream conventions. Maybe you’re dropping support for a Kubernetes API version that was removed in 1.32. Maybe you’re restructuring the chart into subcharts to make individual components opt-in rather than all-or-nothing.
The question is the same one it always is: which repos across the org consume this chart, and at which version?
The scenario
Here is what Helm chart consumption looks like in practice. Your platform team publishes a chart to an internal chart repository or OCI registry. Consumers reference it in a few different ways:
As a standalone helm install:
helm install platform-services oci://registry.company.com/helm-charts/platform-services --version 3.2.1 -n monitoring
As a dependency in another chart’s Chart.yaml:
# some-service/chart/Chart.yaml
dependencies:
- name: platform-services
version: "~3.2.0"
repository: "https://charts.company.com"
alias: monitoring
As an ArgoCD Application manifest:
# gitops/apps/some-team/monitoring.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
source:
chart: platform-services
repoURL: https://charts.company.com
targetRevision: 3.2.1
As a Flux HelmRelease CRD:
# gitops/releases/monitoring.yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
spec:
chart:
spec:
chart: platform-services
version: ">=3.0.0 <4.0.0"
sourceRef:
kind: HelmRepository
name: company-charts
All four patterns express the same dependency. None of them look the same in source code. And right now, they probably live in different repos, written by different teams, using different GitOps tooling.
What existing tools give you (and where they stop)
Helm itself
The helm CLI knows about releases deployed to a cluster. helm list -A shows every release across all namespaces in a given cluster, including which chart and version is installed. helm history <release> shows the version history for a specific release.
This is useful once you have access to the cluster. The limitation is that it’s cluster-scoped and live-state-only. You can see what’s running right now, but it tells you nothing about source repos — which repo contains the values.yaml driving the release, which team owns it, or whether the same chart is deployed to a different cluster you don’t have access to. Most companies have at least three clusters (dev, staging, prod), and many have dozens. You’d need access to all of them, and even then you’d have a list of running releases, not a map of source-code consumers.
Artifact Hub and Chart Museums
Artifact Hub is the public index for Helm charts. It tracks download counts and shows chart metadata, but it’s a discovery tool for chart users, not a graph of chart consumers. If your chart is published internally — to a private chart repository or an OCI registry — it doesn’t appear in Artifact Hub at all. And even for public charts, neither Artifact Hub nor any chart museum stores information about which orgs or repos have installed a particular chart version.
ArgoCD and Flux
If your org has committed fully to GitOps and every Helm release is declared as an ArgoCD Application or a Flux HelmRelease manifest in a Git repo, then in theory all your consumers are visible in those manifests. The problem is “in theory.” In practice:
- Not every team has migrated to GitOps. Some still run
helm upgradein CI pipelines or from engineer laptops. - The GitOps manifests may live in many different repos — a central gitops repo, per-team repos, per-environment repos — rather than a single queryable location.
- ArgoCD’s UI shows you the apps it’s managing, but querying “show me every app that references chart
platform-services” is not a built-in view. You’d need to iterate through the Application CRDs or query the Argo CD API. - Flux doesn’t have a central query surface for “which
HelmReleaseobjects across all clusters reference chart X at version Y” — that information is spread acrossHelmReleaseYAML files in whatever repos your GitOps setup uses.
Renovate
Renovate supports Helm chart version bumps as a first-class feature. Configured in a repo, it detects chart references in Chart.yaml dependencies, ArgoCD Application manifests, and Flux HelmRelease CRDs, and opens pull requests when new chart versions are published.
As with Terraform and GitHub Actions: Renovate must know who consumes what in order to open those PRs. But it doesn’t expose that knowledge as a queryable view. You can’t ask Renovate “which repos reference my chart and at which version?” It reacts after a new version is published. The consumer list before you publish a breaking change is not something it surfaces.
Renovate also only covers repos where it has been configured. A team that hasn’t added Helm to their Renovate config — or doesn’t use Renovate at all — is invisible.
Grep
Clone every repo. Search for the chart name:
grep -r "platform-services" --include="*.yaml" --include="*.yml" ~/repos/
This finds direct name references in YAML files. It doesn’t distinguish between chart references and random YAML comments, doesn’t extract version constraints, misses OCI-format references where the chart name is embedded in a registry URL, and ignores any helm install calls in shell scripts or Makefile targets. And as always: the results are stale by the next commit.
Why this is harder than it looks
Reference formats are highly inconsistent. A Helm chart can be referenced via a traditional HTTP chart repository, an OCI registry, or a local path. These look nothing alike:
# Traditional repository (in Chart.yaml dependencies)
repository: "https://charts.company.com"
# OCI registry (in Chart.yaml dependencies, Helm 3.8+)
repository: "oci://registry.company.com/helm-charts"
# OCI in a Flux HelmRepository
spec:
type: oci
url: oci://registry.company.com/helm-charts
# Inline OCI reference in a helm CLI call
helm install platform-services oci://registry.company.com/helm-charts/platform-services --version 3.2.1
Resolving all of these back to the same chart identity requires knowing how your registry namespaces charts and how your chart repositories map to OCI paths — out-of-band information that no grep can recover.
Version constraints vary widely. Unlike Docker image FROM statements (which usually pin to a specific tag) or Terraform module ref= pins, Helm consumers regularly use semver constraints:
version: "~3.2.0" # patch-compatible only: >=3.2.0 <3.3.0
version: "^3.0.0" # minor-compatible: >=3.0.0 <4.0.0
version: ">=3.0.0 <4" # explicit range
version: "*" # any version (dangerous)
A consumer pinned to ^3.0.0 will automatically receive your 3.3.0 release — they don’t have to explicitly upgrade. A consumer on ~3.2.0 won’t. Understanding who will be affected by a minor version bump versus a major bump requires evaluating constraints, not just comparing version strings.
Umbrella charts create transitive consumers. An umbrella chart is a Helm chart whose primary purpose is to bundle multiple subcharts together. If team-a publishes an umbrella chart team-a-stack that includes your platform-services chart as a dependency, and team-b deploys team-a-stack — then team-b is a transitive consumer of platform-services through team-a-stack. A breaking change to platform-services affects team-b, but a search for platform-services in their repos finds nothing.
GitOps and imperative installs coexist. In most organisations, some teams manage Helm releases declaratively (ArgoCD, Flux) and others do it imperatively (helm install or helm upgrade in CI pipelines, shell scripts, or Makefiles). The declarative installs leave traces in Git repos as YAML manifests. The imperative installs may leave no trace in source code at all — just a live release visible in helm list. A complete consumer map needs to combine both sources.
Chart aliases break name matching. A Chart.yaml dependency can declare an alias, which changes the name used to refer to the subchart in values overrides:
dependencies:
- name: platform-services
version: "~3.2.0"
repository: "https://charts.company.com"
alias: monitoring # the chart is installed as "monitoring", not "platform-services"
A naive search for platform-services in values files will find nothing, because the values are nested under monitoring:. Tools that rely on name matching alone miss aliased consumers entirely.
What the full answer requires
To reliably answer “who consumes this chart,” you need a system that:
- Scans every repo in the org, including GitOps repos, service repos, and platform repos — without requiring registration or manual catalog entries
- Parses all reference formats —
Chart.yamldependencies, ArgoCD Application manifests, Flux HelmRelease CRDs, andhelm installcalls in CI configs and shell scripts - Resolves OCI and HTTP registry references back to a canonical chart identity, so consumers using different registry URL formats for the same chart are recognised as the same dependency
- Evaluates version constraints rather than just matching exact version strings, so you know which consumers are within range of your next release
- Follows umbrella chart transitive dependencies, so second-order consumers are visible, not just direct chart references
- Keeps results current through regular rescans, not a one-time manual trawl
This is one of the specific problems Riftmap is built to solve. It connects to your GitHub or GitLab organisation, scans every repo, and extracts chart references from Chart.yaml dependency blocks, ArgoCD Application and ApplicationSet manifests, Flux HelmRelease CRDs, and helm calls in CI configs. It resolves OCI and HTTP registry URLs to a unified chart identity and builds a cross-repo dependency graph you can query by chart name and version.
The result is the same kind of view described in the earlier posts in this series: before you rename a value key or drop a Kubernetes API version, you open the graph, click the chart, and see every consumer — their version constraint, the repo that owns the deployment declaration, and which constraint ranges include your next release. You know who’ll automatically receive the change, who’s pinned to an older range, and who you need to contact before shipping.
No cluster access required. No cross-org Slack ping. No grep marathon across forty repos.
This is the fourth post in the Find Every Consumer series. Previous posts cover Docker base images, Terraform modules, and GitHub Actions workflows. Next up: Go modules.
If this is a problem your platform team deals with, I’d be interested to hear how you’re solving it today. You can find more at riftmap.dev or reach me at [email protected].