# Review Terraform Pull Requests for a GKE Module

Yes. An agent runs terraform fmt, validate and plan on your GKE module's examples and comments on each resource the change would replace, destroy or expose.

[Run this on Rush](https://cloud.getrush.ai/run/review-terraform-changes/gke/), 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 maps the change to the configurations that use it. In a module like terraform-google-modules/terraform-google-kubernetes-engine, the root module is split across `cluster.tf`, `networks.tf`, `firewall.tf`, `sa.tf`, `dns.tf`, `masq.tf` and `moved.tf`, `modules/` holds 20 submodules such as `private-cluster`, `beta-private-cluster-update-variant`, `safer-cluster` and `gke-node-pool`, and `examples/` holds 48 configurations from `simple_regional` to `shared_vpc`. `versions.tf` requires Terraform `>=1.3` and the `google` provider `>= 7.39.0, < 9`, and the agent installs a Terraform release that satisfies it.

Before planning, it checks the repository's own rule about where changes belong. `CONTRIBUTING.md` says the root module and most submodules are generated from `autogen/` by `make build`, and `autogen/main/` holds `cluster.tf.tmpl`, `main.tf.tmpl` and the rest. A pull request that edits `modules/private-cluster/cluster.tf` by hand without the matching template change will be overwritten by the next `make build`, so the agent regenerates the files with `make build`, which the `Makefile` runs through its `docker_generate_modules` and `docker_generate_docs` targets, and comments on any file whose generated output differs from what the pull request committed.

Then it runs the checks. `terraform fmt -check -recursive` over the whole tree, then `terraform init -backend=false` and `terraform validate` in every example that uses a changed file. The examples point at the published module, for instance `examples/simple_regional/main.tf` has `source = "terraform-google-modules/kubernetes-engine/google"` with `version = "~> 45.0"`, so in its sandbox copy the agent repoints `source` to the local path, never committing that edit, to plan the pull request's code rather than the registry's. `terraform plan` needs read-only Google credentials because the module reads `google_compute_zones`, `google_container_engine_versions` and `google_compute_subnetwork`; with them it plans the base commit and the branch and compares the two.

With both plans in hand, it lists every resource whose action is replace or delete. On a GKE cluster that matters more than anywhere: a change to a field like the cluster's location, its private cluster config or a node pool's machine type can replace the cluster or the pool. It checks that a renamed resource came with a `moved` block, which `moved.tf` already uses for renames such as `kube-dns` to `kube_dns`, that `deletion_protection` (default `true` in `variables.tf`) is not turned off for users, and that a new firewall rule or `master_authorized_networks` entry does not open `0.0.0.0/0` for ingress. It reads the action as well as the range, because the module's `gke-shadow-*` rules in `firewall.tf` use `0.0.0.0/0` for deny rules, which narrow access.

## Start it with one API call

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

```json
{
  "agent": "claude",
  "input": "Review the open pull request. Run terraform fmt -check -recursive, then make build and report any generated file that differs from what the pull request committed. For every example under examples/ that uses the changed files, point its module source at the local path in the sandbox only, run terraform init -backend=false and terraform validate, and run terraform plan with a local backend on the base commit and on this branch using the read-only credentials in GOOGLE_CREDENTIALS. Comment with each resource that would be replaced or destroyed, each rename without a moved block, any change to deletion_protection, and any new public exposure such as an ingress rule or authorized network open to 0.0.0.0/0. Do not push commits and never run terraform apply.",
  "resources": [
    {
      "url": "https://github.com/your-org/terraform-google-kubernetes-engine/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. Each comment sits on the changed line in a `.tf` file or `autogen/` template and names the resource address the plan shows (`module.gke.google_container_cluster.primary`, `module.gke.google_container_node_pool.pools["default-node-pool"]`), the action (update in place, replace, destroy), the attribute that forces it, and which example's plan it came from. Renames without a `moved` block and generated files out of step with `autogen/` get their own comments with the fix.

The session keeps the `fmt`, `make build`, `validate` and both `plan` outputs per example, so a reviewer can read the exact plan lines a replacement comment quotes. If no credentials were set, the review says `plan` did not run and reports only what `fmt` and `validate` found, rather than implying the change is safe.

Before merging, a maintainer decides whether each replacement is acceptable for a module that many clusters depend on, which usually means a major version and an upgrade note in `CHANGELOG.md`, and checks that any new exposure is opt-in through a variable that defaults to closed.

## Run it on every Terraform pull request

An automation with a GitHub trigger on `pull_request.opened` and `pull_request.synchronize` runs this review on each push. Start it in the Project that holds the `GOOGLE_CREDENTIALS` secret with `POST /o/{org}/p/{project}/sessions`, so every review gets the read-only service account without the key ever appearing in a request body.

A module with dozens of examples can take a while to plan, so set a webhook URL on the API key and wait for `run.completed` rather than holding the event stream open. If the author pushes a fix, a follow-up message to the same session re-plans only the examples that change touched.

## Why run it on Rush?

A Terraform review that does not run `plan` misses the one thing reviewers most need to know: whether the change replaces a cluster. Planning several examples on two commits takes a clean working directory per example and Google credentials on the reviewer's machine. On Rush each review gets its own sandbox and its own `.terraform` directories, with only the read-only service account from the Project secret, a local backend, and a prompt that forbids `apply`.

The comments quote the plan, and the session keeps every command and its output, so a maintainer can check a replacement claim without re-running the plan. Reviews for several pull requests run at the same time without sharing state, and none of them can touch your real state files because they never see the backend.

## Frequently asked questions

### What credentials does the agent need?

Only for `terraform plan`, because the module reads data sources such as the available zones and GKE versions. Save a read-only service account key as a Project secret named `GOOGLE_CREDENTIALS` and start the session in that Project; the agent reads it as an environment variable. Without it, the review runs `fmt` and `validate` and says plan was skipped.

### Can it change our Terraform state or apply anything?

It uses a local backend with `-backend=false` for init, so it never reads or writes your remote state, and the prompt forbids `terraform apply`. A read-only service account makes that a hard limit rather than an instruction.

### Why does it run make build?

Because the GKE module generates most of its files from `autogen/` templates. A hand edit to a generated file passes `validate` and then disappears the next time someone runs `make build`, so the agent regenerates and comments on any difference.

### Does this work for our own Terraform, not a public module?

Yes. Point it at your root configurations instead of `examples/`, and name the backend and variable files in the prompt. The replacement and exposure checks are the same.
