# Fix Failing GitHub Actions Checks in a Terraform Module

Yes. An agent reads the failed pre-commit job, reruns terraform validate and the hook that broke on that Terraform version, and opens a fix PR.

[Run this on Rush](https://cloud.getrush.ai/run/fix-failing-ci/terraform/), in a Project that has your repository.

## What the agent does

Terraform module CI rarely fails in one place, so the agent first works out which job and which Terraform version went red. In terraform-aws-modules/terraform-aws-vpc, `.github/workflows/pre-commit.yml` has a `collectInputs` job that lists the module's directories, then a `preCommitMinVersions` matrix that runs only `terraform_validate` in each directory on the lowest Terraform the code allows, and a `preCommitMaxVersion` job that runs every hook on the newest. The agent reads `gh run view <id> --log-failed` and notes the job name, the directory from the matrix (such as `examples/complete` or `modules/vpc-endpoints`) and the Terraform version in the step title.

Next it installs the matching toolchain in its sandbox. The minimum comes from `required_version = ">= 1.0"` in `versions.tf`, and the AWS provider constraint is `version = ">= 6.28"`, so a resource argument added in a newer provider can pass on the max job and fail validation on the min job, or the reverse. The workflow pins `TFLINT_VERSION: v0.64.0` and `TERRAFORM_DOCS_VERSION: v0.24.0`, and `.pre-commit-config.yaml` pins `antonbabenko/pre-commit-terraform` at `v1.108.1`. The agent installs those exact versions so its results match the runner's.

Then it reproduces the failure. For a validate error it runs `terraform init -backend=false` and `terraform validate` in the failing directory, which needs no AWS credentials. For a lint error it runs the `terraform_tflint` hook with the same `--only` rules the config lists, such as `terraform_documented_variables`, `terraform_typed_variables` and `terraform_unused_declarations`. A `terraform_docs` failure means the inputs and outputs table between `<!-- BEGIN_TF_DOCS -->` and `<!-- END_TF_DOCS -->` in `README.md` no longer matches `variables.tf` and `outputs.tf`; a `terraform_wrapper_module_for_each` failure means the files under `wrappers/` are stale.

The fix goes where the error points. In a 1,543-line `main.tf` with seven `aws_subnet` resources (`public`, `private`, `database`, `redshift`, `elasticache`, `intra`, `outpost`), that is often one argument on one subnet resource, a variable in `variables.tf` with no `type` or `description`, or an output with no description. Generated files are regenerated by the hook, never edited by hand. The agent reruns `pre-commit run -a` until every hook passes, then opens a pull request against the failing branch.

## Start it with one API call

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

```json
{
  "agent": "codex",
  "input": "The Pre-Commit workflow failed on the branch feat/subnet-tags. Find the failed run with `gh run list --branch feat/subnet-tags --status failure --limit 1` and read it with `gh run view <run id> --log-failed`. Note which job failed (min or max Terraform version), which directory, and which hook. Install the same Terraform version, TFLint v0.64.0, terraform-docs v0.24.0 and pre-commit-terraform v1.108.1. Reproduce with `terraform init -backend=false && terraform validate` in that directory, or with the failing pre-commit hook. Fix the cause in the .tf files; let terraform_docs and the wrapper hook regenerate README.md and wrappers/ rather than editing them by hand. Do not run terraform plan or apply and do not use AWS credentials. Confirm `pre-commit run -a` passes, then open a pull request against feat/subnet-tags that quotes the error.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

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 pull request against the failing branch. Its diff has the `.tf` change that fixes the error, and, when a hook regenerated them, the updated `README.md` docs table and files under `wrappers/`. The description says which job failed, on which Terraform version and in which directory, quotes the validate or lint message, and lists the commands it ran to confirm the fix.

Pushing the branch runs `pre-commit.yml` again, so the pull request's checks show both the min-version matrix and the max-version job. That matters for a module whose constraints span from Terraform 1.0 upward: a fix that only passes on the newest Terraform shows up red on the min job before anyone merges it.

A reviewer checks that a new argument is supported by the lowest AWS provider version `versions.tf` allows, or that the constraint was raised on purpose and noted for the changelog, and that the regenerated docs match the variables they describe. No `plan` or `apply` ran, so nothing in an AWS account changed.

## Run it on every pre-commit workflow failure

Add an automation to the Project that holds the module, with this prompt and a GitHub trigger on `workflow_run.failure`. Each failed run of the workflow starts one Rush run with the event after the prompt, so the agent gets the run id and branch without listing runs first. CI runs from forks never fire, which keeps outside contributors' pull requests from starting agents.

Modules in one organization often share the same pre-commit setup, so the same automation prompt works in each module's Project. Give the API key a webhook URL and Rush POSTs `run.completed` with the `session_url` when a turn finishes, so a bot can post the fix's link next to the failed check.

## Why run it on Rush?

Reproducing module CI on a laptop means installing the exact minimum and maximum Terraform versions, TFLint, terraform-docs and the pre-commit-terraform hooks, often in different versions from the ones your other projects use. In a Rush sandbox the agent installs exactly what the workflow pins, with its own clone, and leaves your local Terraform and plugin cache untouched.

The output is checkable. Every `terraform validate` and hook run is kept with its output, the pull request reruns both the min and max jobs, and the prompt rules out `plan`, `apply` and cloud credentials, so the run's reach is the repository and nothing else. When a provider release breaks validation across a dozen modules, each module's failure starts its own run, and they run at the same time.

## Frequently asked questions

### Does the agent need AWS credentials?

No. `terraform init -backend=false` and `terraform validate` check the configuration without contacting AWS, and the pre-commit hooks are static checks. The prompt forbids `plan` and `apply`, so the run never needs an account.

### Why did validate pass for me and fail in CI?

Usually because CI runs the lowest Terraform version your `required_version` allows, and you run a newer one. The agent installs the version named in the failed step's title, so it sees the same error the runner did.

### Will it edit the generated README table by hand?

No. It runs the `terraform_docs` hook, which rewrites the section between the `BEGIN_TF_DOCS` and `END_TF_DOCS` markers from your variables and outputs. Hand edits there would be overwritten by the next run of the hook anyway.

### Can it fix a failure in an example directory?

Yes. The min-version job validates each directory separately, so a failure in `examples/ipv6-dualstack` or `examples/complete` names that directory. The agent runs validate there, fixes the example or the module input it uses, and reruns the hook for that directory.
