# Review Helm Chart Pull Requests

Yes. An agent checks out the chart change, runs helm lint, ct lint and helm unittest, renders old and new templates and reviews what an upgrade would change.

[Run this on Rush](https://cloud.getrush.ai/run/review-chart-changes/helm/), in a Project that has your repository.

## What the agent does

The agent checks out the pull request's branch in its own sandbox and reads how the repository tests charts before it runs anything. In a repository like prometheus-community/helm-charts, `.github/workflows/ci.yaml` pins Helm v4.3.1 and chart-testing v3.15.0, and `.github/linters/ct.yaml` sets `target-branch: main`, `chart-dirs: [charts]`, excludes `prometheus-to-sd`, and adds two commands that `ct lint` runs on every changed chart: `ci/lint.sh` through shellcheck when a chart has one, and `helm unittest --strict --file 'unittests/**/*.yaml'`. The agent installs the same versions and the helm-unittest plugin so its results match what CI will report.

Then it runs `ct list-changed` and `ct lint --config .github/linters/ct.yaml`, which fails on a chart whose `version` in `Chart.yaml` was not bumped against `main`, plus `helm lint` and the unit tests. For `kube-prometheus-stack` that means the suites under `unittests/` (`alertmanager/`, `prometheus/`, `grafana/`, `node_selector_test.yaml`, `route_test.yaml` and more), and every values file under the chart's `ci/` directory, such as `03-non-defaults-values.yaml` and `07-arbitrary-fs-access-deny-values.yaml`, which CI also uses as its install matrix.

Linting passes on plenty of changes that still break an upgrade, so the agent renders the chart twice. It runs `helm template` on the `main` version and on the pull request's version with the default `values.yaml` and with each `ci/*-values.yaml`, and diffs the output, the same comparison the repository's CI makes with `helm diff upgrade --normalize-manifests` against a kind cluster. A change to `spec.selector.matchLabels` on a Deployment or DaemonSet is the classic finding: selectors are immutable, and `REVIEW_GUIDELINES.md` says `helm.sh/chart` must never appear there because the next upgrade fails.

Last, it reads the diff against the repository's own checklist. `REVIEW_GUIDELINES.md` asks that `resources` are not set by default, that persistence, ingress and autoscaling are off by default, that a breaking change bumps the major version and adds a section under the README's `## Upgrading` heading, and that each chart has tests. The chart's `UPGRADE.md` shows the expected style: the 91.x to 92.x entry explains that a new default `nodeSelector` restarts Prometheus, Alertmanager and the operator once. The agent posts one review with file and line for each finding and the rendered manifest lines that show it.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Review the open pull request on this Helm chart repository. Install the Helm and chart-testing versions the CI workflow pins, then run ct lint with the repository's ct.yaml, helm lint and helm unittest for every changed chart. Render each changed chart with helm template on main and on this branch, with values.yaml and each file in the chart's ci/ directory, and diff the output. Post one review that cites file and line for every finding, covering template logic, changed values defaults, selector or other immutable field changes, a missing version bump, and breaking upgrades without upgrade notes. Do not push commits.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-charts/pull/123"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is one review on the pull request. Comments sit on the changed lines of `templates/*.yaml`, `values.yaml` or `Chart.yaml`, and each one quotes the rendered manifest that shows the problem: the Deployment whose selector changes, the container that now gets a `resources` block by default, the value whose new default turns on a ServiceMonitor or a PersistentVolumeClaim for every existing install. The summary lists each command it ran per chart and per values file.

The session keeps the evidence: the `ct lint` output with the version check, the helm-unittest results per suite, and the rendered diff between `main` and the branch for each values file. A reviewer can see from those whether a finding came from a failing test, a lint rule or only from the rendered output.

Before merging, a maintainer checks that the version bump matches the size of the change (a major for anything that needs a manual step), that the upgrade notes say what restarts and what users must change, and that new defaults stay off unless the chart has always shipped them on. A selector or StatefulSet volume claim change is the finding to resolve before anything else.

## Run it on every chart pull request

An automation with a GitHub trigger on `pull_request.opened` and `pull_request.synchronize` runs this review on each push, which suits a chart repository where most pull requests are small version bumps from Renovate and a few change templates. From your own server, receive GitHub's `pull_request` webhook and send this body with the pull request URL in `resources` and the head SHA as the `Idempotency-Key`.

A key runs at most `max_concurrent` sessions at once, 4 by default, and answers `429` past that, so a burst of dependency pull requests should be queued by your server. Set a webhook URL on the key and each `run.completed` tells you which review is posted.

## Why run it on Rush?

Reviewing a chart properly means installing the right Helm and chart-testing versions, the unittest plugin, and rendering two versions of the chart with several values files, then reading a long diff. That is a lot of setup to repeat for every pull request on a laptop, and it is why many chart reviews only read the template diff. On Rush each review runs in its own sandbox with those tools installed for that run, with no kube context and no cluster access, so a wrong render cannot touch anything.

The output is a review with the evidence attached. Every comment points to the rendered lines or the failing test in the session's transcript, so a maintainer can trust a selector finding without re-running `helm template` themselves. Reviews of pull requests to different charts run at the same time, each isolated from the others.

## Frequently asked questions

### Does it need a Kubernetes cluster?

No. `ct lint`, `helm lint`, `helm unittest` and `helm template` all run without a cluster, and the upgrade comparison is a diff of rendered output from `main` and the branch. If you want an install check as well, ask for a kind cluster in the prompt and the agent creates one inside its sandbox.

### Will it catch a missing chart version bump?

Yes. `ct lint` compares each changed chart's `version` in `Chart.yaml` with the target branch set in `ct.yaml` and fails when it was not bumped. The review also says whether the bump fits the change, for example a patch bump on a change that alters a selector.

### What about charts with subcharts?

The agent runs `helm dependency update` before rendering, as the repository's CI does for `kube-prometheus-stack` with its `grafana`, `kube-state-metrics` and node exporter subcharts. A change to a subchart's version shows up in the rendered diff like any other change.

### Does it check values.schema.json?

When a chart ships a `values.schema.json`, `helm lint` validates the values files against it, and the agent comments if a new value is missing from the schema. In prometheus-community/helm-charts seven charts carry one and the CI installs a schema plugin to keep it in step.
