All jobs

Review Kubernetes Manifests in Pull Requests

Yes. An agent renders your Helm and Kustomize output, runs kubeconform and kube-linter, and comments on containers without limits, probes or a non-root user.

Run this on RushIn a Project that has your repository.

What the agent does

The agent checks out the pull request's branch in its own sandbox and works out which forms of the manifests the change touches. In a repository like GoogleCloudPlatform/microservices-demo the same eleven-service app ships three ways: raw YAML in kubernetes-manifests/ (one file per service plus a kustomization.yaml), a Helm chart in helm-chart/ at version 0.10.7, and Kustomize in kustomize/, where base/ holds the services and components/ holds variants such as network-policies, memorystore, spanner, service-mesh-istio and without-loadgenerator. A change to one form often needs the same change in the others, and a missing twin is a finding in itself.

It reviews rendered output, not templates, because that is what reaches the cluster. It runs helm lint --strict and helm template . in helm-chart/, plus the variants the repository's helm-chart-ci.yaml workflow renders (gRPC health probes, Spanner, the service mesh). It runs kubectl kustomize . in kustomize/ and kustomize build for each directory in kustomize/tests/, the combinations kustomize-build-ci.yaml already checks. Then it runs the same rendering on the base commit and diffs the two, so a comment can say exactly which Deployment field changed and in which variant.

On each rendered file it runs kubeconform -strict -summary against the schemas for your cluster's Kubernetes version, which catches a misspelled field or an apiVersion the cluster no longer serves, and kube-linter lint, whose checks cover missing CPU and memory requests and limits, missing readiness and liveness probes, containers that can run as root, privileged containers, a writable root filesystem and images without a pinned tag. It keeps only results on objects the pull request changed, so the review is about this change and not every old warning in the repository.

Then it reads each finding against the repository's own baseline. kubernetes-manifests/frontend.yaml sets a pod securityContext with runAsNonRoot: true, and a container context with allowPrivilegeEscalation: false, capabilities.drop: [ALL], privileged: false and readOnlyRootFilesystem: true, plus HTTP readiness and liveness probes on /_healthz port 8080 with a session cookie header. A new service that omits any of those is a comment pointing at the frontend as the pattern. It notes the cases where a rule does not fit, such as the frontend-check init container in loadgenerator.yaml, which uses busybox pinned by digest and cannot take probes because init containers do not run them.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Review the open pull request's Kubernetes changes. Render the Helm chart with helm lint --strict and helm template, and the Kustomize base and each kustomize/tests combination, on this branch and on the base commit, and diff the output. Run kubeconform -strict and kube-linter on the rendered manifests. Comment on the changed lines with each container that lacks resource requests and limits, readiness or liveness probes, or a non-root security context, each privileged or root-capable container, and any change made in one of raw manifests, Helm or Kustomize but not the others. Do not edit the files.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-k8s-app/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 a review on the pull request with comments on the changed lines in kubernetes-manifests/, helm-chart/templates/ or kustomize/. Each comment names the Deployment and container, the rule it breaks (no memory limit, no readiness probe, runAsNonRoot missing, privileged: true), the tool that reported it, and the YAML to add, written to match the repository's existing services. When a change appears in one form of the manifests and not another, the comment names the file that needs the same change.

The session's transcript holds the full output of helm template, kustomize build, kubeconform and kube-linter for both commits, and the rendered diff, so a reviewer can open the exact manifest behind any comment.

Before merging, a reviewer checks that the suggested requests and limits fit the service's real usage, which the sandbox cannot measure, and that a probe path exists in the service's code. A container that can run as root or with privileged: true is the comment to settle first.

Run it on every pull request that changes manifests

An automation with a GitHub trigger on pull_request.opened and pull_request.synchronize runs this review on every push. To limit it to deploy changes, receive GitHub's pull_request webhook on your server, check whether the changed files are under kubernetes-manifests/, helm-chart/ or kustomize/, and send this body with the pull request URL in resources and the head SHA as the Idempotency-Key.

Set a webhook URL on the API key and Rush POSTs run.completed when the review is posted. If the author asks a question in the review thread, forward it as a follow-up message to the same session; the parked sandbox still has both renders and the tool output.

The use case this job follows, with its automation and trigger: Review every pull request.

Why run it on Rush?

Reviewing manifests from a diff misses what Helm values and Kustomize patches produce, and running helm template, kustomize build, kubeconform and kube-linter on two commits for every pull request is a setup most reviewers do not keep on their laptop. On Rush each review runs in its own sandbox with those tools installed for that run and no kube context, so rendering a chart cannot apply anything to a cluster.

Each comment is backed by tool output in the session's transcript, which makes the review a platform team can rely on for every deploy change rather than a spot check. Reviews for many pull requests run at the same time, each with its own renders, and the result is the same whether the change came from a person or a dependency bot.

Frequently asked questions

Does it need access to my cluster?

No. Rendering, kubeconform and kube-linter all work on files, and the agent gets no kubeconfig. Tell it your cluster's Kubernetes version in the prompt so kubeconform validates against the right schemas.

Will it complain about every old warning in the repository?

No. It renders the base commit as well and keeps only findings on objects the pull request changed. It may mention in the summary that an unchanged service has the same problem, without commenting on lines the pull request did not touch.

We use Kustomize components and overlays. Does it render all of them?

It renders the overlays the repository already builds in CI, such as each directory in kustomize/tests/, plus the base. Name any other overlay you deploy in the prompt and it renders that too.

What does it suggest for resource limits?

It copies the shape the repository already uses for similar services and says the numbers are a starting point. It cannot measure the service's real CPU and memory from the sandbox, so the reviewer sets the final values.