# Fix a Failing CI Build in a Gin Project

Yes. When a Gin project's Actions run fails, an agent reads the failed job's log, reruns the same script in its sandbox, fixes the cause and opens a pull request.

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

## What the agent does

The agent starts from the failed run, not from a guess. With the `workflow_run` payload after the prompt, it runs `gh run view <run id> --log-failed` and reads which job failed. In a Gin project like gothinkster/golang-gin-realworld-example-app, `.github/workflows/ci.yml` has four jobs, and each fails for a different reason: `Test` runs `scripts/gofmt.sh` and then `scripts/coverage.sh` on a matrix of Go 1.21, 1.22 and 1.23; `Lint` runs golangci-lint v1.61 with the `staticcheck`, `unused` and `misspell` linters from `.golangci.yml`; `Security Scan` runs gosec with `-no-fail`, so it rarely breaks the build; and `API Integration Test` builds the binary, starts it on port 8080 and runs the RealWorld Postman collection with Newman. The log says which one, and the agent quotes the failing block.

Then it reproduces the failure with the job's own command. `go.mod` declares `go 1.21`, so for a `Test` failure it installs the matrix version that failed, runs `bash ./scripts/gofmt.sh` (which fails when `gofmt -l .` prints any file) and `bash ./scripts/coverage.sh`, which loops over every package directory and runs `go test -coverprofile=profile.out -covermode=atomic` in each. A failure in one package is rerun alone, such as `go test -run TestArticleFeedCount ./articles/`, where `articles/unit_test.go` opens the SQLite test database through `common.TestDBInit()` in `TestMain` and removes it in `common.TestDBFree`. A test that passes alone and fails in the loop usually means a leftover `data/gorm_test.db` or a shared `test_db` between the `users` and `articles` packages, and the agent checks that before it touches the code.

With the failure reproduced, it reads the code the test covers: `articles/routers.go` for the handlers (`ArticleList`, `ArticleFeed`, `ArticleCommentDelete`), `articles/models.go` for `FindManyArticle` and `GetArticleFeed`, which parse `limit` and `offset` with `strconv.Atoi` and fall back to 20 and 0, `users/middlewares.go` for `AuthMiddleware`, and `common/utils.go` for `Bind` and `NewValidatorError`. A lint failure is fixed in the line golangci-lint names, and a `gofmt` failure by running `go fmt ./...`. The agent does not skip a test, mark it flaky or loosen an assertion; if a test is wrong it changes the test and says so in the pull request.

For a failed `API Integration Test` it follows `scripts/run-api-tests.sh`: deletes `data/gorm.db`, builds with `go build -o app hello.go`, starts `PORT=8080 ./app`, waits for `/api/ping` and runs Newman against the Conduit collection with `APIURL=http://localhost:8080/api`. Those failures are usually a response shape, like the empty body `DELETE /articles/:slug` must return or the 401 `POST /users/login` must give on a bad password, both called out in the readme's spec-compliance list. Before it pushes, the agent reruns the full `coverage.sh` loop, `gofmt.sh` and `golangci-lint run` with the pinned version so the other jobs stay green.

## Start it with one API call

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

```json
{
  "agent": "codex",
  "input": "The GitHub Actions run on this branch failed; the workflow_run event is at the end of this prompt. Read the failed job's log with gh run view <run id> --log-failed, name the job and matrix entry that failed, and quote the failing output. Reproduce it in the sandbox with the job's own command from .github/workflows/ci.yml: scripts/gofmt.sh and scripts/coverage.sh for the Test job with the Go version that failed, golangci-lint v1.61 for Lint, or scripts/run-api-tests.sh for the API Integration Test. Run the failing package or test alone first, check for a stale data/gorm_test.db before blaming the code, then fix the cause in the handlers, models or middleware. Do not skip, mark flaky or delete a failing test; if a test itself is wrong, change it and say why. Rerun scripts/gofmt.sh, scripts/coverage.sh and golangci-lint run until they pass, and open a pull request against the failing branch that quotes the error it fixed.\n\nEvent: <workflow_run payload>",
  "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

A pull request against the branch whose run failed, with the fix in the package the failing test or linter named and the job, matrix entry and quoted error in the description. For a test failure it shows the single `go test -run` output before and after; for a lint failure it names the golangci-lint rule; for a Newman failure it names the collection request and the field in the response that was wrong. It lists every command the agent ran, and the session's transcript keeps each with its output.

The `CI` workflow runs again on the pull request across all three Go versions and the three other jobs. When the agent finds no code cause, such as a transient `go mod download` failure or a Newman request that timed out, it opens nothing and its answer says what the log showed and what it reran.

A reviewer checks that the test's assertions still mean what they did, that no `t.Skip` or `//nolint` was added, and that a changed response shape matches the RealWorld spec the Postman collection enforces.

## Run it on every failed Go workflow run

Create an automation in the Project with this prompt and a `github` trigger on `workflow_run.failure`. Only work by an owner, member or collaborator fires it, and runs from forks never do, so a contributor's broken branch does not start a run until a maintainer pushes to it. The event arrives after the prompt as untrusted text.

Or have your own server subscribe to the repository's `workflow_run` webhook and, on `conclusion: failure`, send this request with the event in `input` and `https://github.com/<owner>/<repo>/tree/<head_branch>` as the resource. Keep the `workflow_run.id` next to the returned `execution_id` to drop redeliveries, and read the `run.completed` webhook to post the pull request link on the commit.

## Why run it on Rush?

A red Go build with a three-version matrix and a Newman job is tedious to debug by hand: you install the right Go, remember that `coverage.sh` runs packages in a loop, and rebuild the server for the API tests. The agent does that in a sandbox with its own module cache and SQLite file, runs the exact scripts the workflow runs, and never touches your working tree.

The pull request comes with proof: the quoted log, the failing and passing output of the same command, and the full workflow rerunning on the branch. Several broken branches each get their own run at once, and a human still decides what merges.

## Frequently asked questions

### Will it make the build green by skipping the test?

No. The prompt forbids `t.Skip`, flaky markers and deleted tests, and any such change would be visible in the diff. If a test encodes behaviour the code deliberately changed, the agent edits the test and explains that in the pull request.

### Which Go version does it use?

The one in the failed matrix entry, from `go-version` in `ci.yml`: 1.21, 1.22 or 1.23. `go.mod` says `go 1.21`, so a failure only on 1.23 is reproduced on 1.23 and the fix is rerun on all three before the pull request.

### Can it run the Newman API tests?

Yes. `scripts/run-api-tests.sh` builds the binary, starts it on port 8080 and runs the Conduit Postman collection with `npx newman`, and the agent installs Node 20 in its sandbox as the job does. The agent reads the request that failed and the response body from Newman's output.

### What if the failure is a stale test database?

`common.TestDBInit` opens `data/gorm_test.db` and `TestDBFree` removes it, so a crashed earlier test can leave a file behind. The agent deletes it and reruns before changing code, and says in the pull request when that was the whole cause.
