# Helm Cheat Sheet

> **Tool:** Helm
> **Category:** Containers & Orchestration
> **Verified against:** Helm v3.18.6, flags verified via `helm <cmd> --help` run locally, 2026-08-21
> **Official docs:** https://helm.sh/docs/helm/

Repos, install/upgrade/rollback, and the commands for previewing what a change would actually do before it hits a cluster.

## Managing chart repositories

```bash
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update                          # refresh the local index of all added repos
helm repo list
helm search repo postgresql               # search across all added repos
```

## Installing a release

```bash
helm install my-release bitnami/postgresql --namespace my-app --create-namespace
helm install my-release ./my-chart -f values-prod.yaml
helm install my-release ./my-chart --set image.tag=v2.1.0,replicaCount=3
helm install my-release ./my-chart --version 1.4.2   # pin a specific chart version
```

`-f values.yaml` and `--set key=value` can both be used together — `--set` values win when the same key is set both ways, which makes it the standard way to override one or two values from a CI pipeline without maintaining a separate values file per environment.

## Upgrading a release

```bash
helm upgrade my-release ./my-chart -f values-prod.yaml
helm upgrade --install my-release ./my-chart -f values-prod.yaml   # upgrade if it exists, install if it doesn't
helm upgrade my-release ./my-chart --atomic                          # auto-rollback the whole upgrade on failure
```

`--install` on `upgrade` (or the equivalent `upgrade -i`) is the standard pattern for idempotent CI/CD deploy scripts — one command works whether this is the first deploy or the hundredth, no separate install-vs-upgrade branching logic needed.

## Previewing changes before applying

```bash
helm install my-release ./my-chart --dry-run --debug          # render manifests locally, no cluster call
helm template my-release ./my-chart -f values-prod.yaml        # render manifests to stdout, no release created at all
helm diff upgrade my-release ./my-chart -f values-prod.yaml    # requires the helm-diff plugin — shows an actual diff
```

`helm diff` is a plugin, not built into core Helm — install it with `helm plugin install https://github.com/databus23/helm-diff`. It's the closest thing Helm has to `terraform plan`: an actual before/after diff against the live cluster state, versus `template`/`--dry-run` which only show the rendered output in isolation.

## Rolling back

```bash
helm history my-release                    # list all revisions of a release
helm rollback my-release                   # roll back to the previous revision
helm rollback my-release 3                 # roll back to a specific revision number
```

## Listing and removing releases

```bash
helm list --namespace my-app
helm list --all-namespaces
helm status my-release
helm uninstall my-release --namespace my-app
```

## Chart development helpers

```bash
helm lint ./my-chart                         # catch template/schema issues before installing
helm create my-new-chart                     # scaffold a new chart from the standard starter template
helm package ./my-chart                       # produce a .tgz for distribution
```

## Debugging rendered templates

```bash
helm template my-release ./my-chart -s templates/deployment.yaml   # render just one template
helm template my-release ./my-chart --debug                        # show the computed values alongside the output
helm template my-release ./my-chart --validate                     # validate rendered manifests against the live cluster's API
helm template my-release ./my-chart --set replicaCount=3 --set-string image.tag=1.2.3
```

`-s`/`--show-only` (repeatable) is the fastest way to check one resource in a chart with dozens of templates without scrolling past everything else. `--validate` actually contacts the cluster to check the rendered manifests against its API — plain `template` never does, which is why it can render manifests referencing a CRD that doesn't exist in that cluster without complaint.

## Managing chart dependencies

```bash
cat my-chart/Chart.yaml                       # dependencies are declared here: name, version, repository
helm dependency list ./my-chart                # show declared deps vs what's actually in charts/
helm dependency update ./my-chart              # pull deps declared in Chart.yaml into charts/, writes Chart.lock
helm dependency build ./my-chart               # rebuild charts/ from the existing Chart.lock (no re-resolution)
```

`update` re-resolves version ranges against the repo index and can pick up a newer chart than last time; `build` reproduces exactly what's pinned in `Chart.lock`. Use `build` in CI for reproducible installs, `update` when you deliberately want to bump a dependency.

## Testing a release

```bash
helm test my-release                          # run the test hooks defined in the chart (helm.sh/hook: test)
helm test my-release --logs                   # also dump logs from the test pods after they complete
helm test my-release --filter name=connection-test   # run only a specific named test
```

Test hooks are just Pods annotated `"helm.sh/hook": test` in the chart's templates — `helm test` finds and runs them against a release that's already installed, then reports pass/fail per pod. It's a post-install smoke test, not a substitute for `helm lint`/`--dry-run` at deploy time.

## Linting a chart

```bash
helm lint ./my-chart --strict                 # treat warnings as failures (use in CI)
helm lint ./my-chart --with-subcharts         # also lint every dependency chart under charts/
helm lint ./my-chart -f values-prod.yaml      # lint against a specific values file instead of the defaults
```

Plain `helm lint` only emits `[WARNING]` for style/convention issues and exits 0 — `--strict` is what actually fails a CI pipeline on those warnings, so add it once a chart's conventions are settled.

## Searching and removing repositories

```bash
helm search repo postgresql --versions        # every version of postgresql across added repos
helm search hub ingress                       # search Artifact Hub itself, not just your added repos
helm repo remove bitnami                      # drop a repo you added earlier
```

`search repo` only searches repos you've already `helm repo add`ed locally; `search hub` queries Artifact Hub (artifacthub.io) directly, which is useful for discovering a chart before you know which repo it lives in.
