All jobs

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 RushIn 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 with this body:

{
  "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.

The use case this job follows, with its automation and trigger: Fix a bug from an alert.

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.