# Fix Failing GitHub Actions Checks in a Go Service

Yes. When your Go build goes red, an agent reads the failed job's log, reruns go test with the same flags, fixes the cause and opens a pull request.

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

## What the agent does

The agent reads the failed job before anything else. It gets the `workflow_run` event, runs `gh run view <run id> --log-failed`, and finds which job and which matrix entry failed. That matters in a Go project like miniflux/v2, whose `.github/workflows/tests.yml` runs unit tests on `ubuntu-latest`, `windows-latest` and `macOS-latest`: only Ubuntu runs `make test`, which is `go test -cover -race -count=1 ./...`, while Windows and macOS run plain `go test ./...`. A test that fails only on Ubuntu is often a data race the `-race` flag caught, and the log then shows `WARNING: DATA RACE` with two goroutine stacks rather than a failed assertion. The agent quotes the relevant block and names the package.

Then it matches the toolchain. `go.mod` declares `module miniflux.app/v2` and `go 1.26.0`, and the workflow installs `go-version: stable`, so the agent uses a Go release that satisfies the `go` line and runs the exact command of the failing matrix entry, flags included. It runs the failing package alone first, such as `go test -race -count=1 -run TestRetryDelay ./internal/reader/fetcher/`, where `response_handler_test.go` holds `TestIsModified`, `TestRetryDelay` and `TestExpiresInMinutes`. `-count=1` keeps Go from serving a cached pass.

With the failure reproduced, it reads the code the test covers, here `internal/reader/fetcher/response_handler.go` and `request_builder.go`, or the reader handler in `internal/reader/handler/handler.go`, and the commit that broke it. A race is fixed with the synchronization the shared value needs, not by removing `t.Parallel()` from the test; a failed assertion is fixed in the code unless the test encoded behavior the commit deliberately changed. Before pushing, the agent reruns `make test` across the whole module and runs `go vet ./...` and `gofmt -l .`, the first two checks of the repository's `make lint`.

When the failing job is `integration-tests`, the agent sets up what that job sets up: a Postgres service (the workflow uses `postgres:11`), then `make integration-test`, which drops and recreates `miniflux_test` with `psql`, starts the app with `go run main.go` (`CREATE_ADMIN=1`, `RUN_MIGRATIONS=1`, `ADMIN_USERNAME=admin`), waits for port 8080, and runs `go test -v -count=1 ./internal/api` against it. The server's own output goes to `/tmp/miniflux.log`, and the agent reads that file when an API test fails, since the test log alone shows only the HTTP status.

## Start it with one API call

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

```json
{
  "agent": "codex",
  "input": "The GitHub Actions workflow 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 test or race report. Use a Go version that satisfies go.mod and run the exact command that job runs, with the same flags (-race, -count=1, -cover), on the failing package first with -run. Fix the cause in the code (fix a data race with proper synchronization rather than by disabling parallel tests; change a test only if the test is wrong, and say so), then run go test ./... with the job's flags, go vet ./... and gofmt -l . 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 failing branch, with the fix in the package the failing test covers and the job, matrix entry and quoted error in the description. For a race, the description includes the two stacks from the race report and explains which value was shared and how it is now guarded. It lists every command the agent ran in its sandbox, from the single `-run` test to the full `go test ./...`, `go vet` and `gofmt`, and the session's trajectory keeps them with their output. The workflow runs again on the pull request across the same matrix.

When the failure appears only on Windows or macOS, the agent says it reproduces on Linux only if it can, reads the code for platform differences such as path separators or line endings, and states in the pull request that the fix is unverified on that platform until the workflow reruns. If it finds no code cause, it opens nothing and its answer explains what the log shows.

A reviewer checks that a race fix does not add a lock on a hot path where a channel or a copy would do, that no `t.Parallel()` or `-race` was removed, and that an edited test was truly wrong.

## Run it on every failed Go test run

Subscribe a GitHub webhook to `workflow_run` and, on `completed` with `conclusion: failure`, send this request with the event in `input` and `https://github.com/<owner>/<repo>/tree/<head_branch>` as the resource. miniflux's tests run on pull requests to `main`, so most failures arrive on contributors' branches; exclude branches the agent opened so a failed fix does not trigger itself.

A failed matrix produces one `workflow_run` with several failed jobs, so one run covers all of them and the prompt asks for each. Keep the `workflow_run.id` with the returned `execution_id` to skip redeliveries, and use the `run.completed` webhook from Rush to post the pull request link back on the contributor's pull request.

## Why run it on Rush?

Race failures are the hard kind to fix on a laptop: they depend on scheduling, need `-race` and `-count=1` to show up, and are easy to dismiss as flaky. The agent runs the exact command the runner ran, as many times as it takes, in its own sandbox with its own clone and module cache, without slowing your machine or touching your checkout.

What it hands back is checkable: the quoted race report or assertion, the trajectory with every `go test` run and its output, and the full matrix rerunning on the pull request. Failures on several branches each get their own run in parallel, and nothing merges without a reviewer.

## Frequently asked questions

### Will it make a race go away by removing -race or t.Parallel()?

No. The prompt rules that out, and the pull request has to name the shared value and how it is now synchronized. Any change to the Makefile or workflow flags would show in the diff.

### Can it reproduce a Windows-only failure?

Its sandbox runs Linux, so it cannot run the Windows job itself. It reads the code for platform-specific behavior, fixes what it finds, and says in the pull request that the Windows result comes from the workflow rerun, not from its own run.

### Does it run golangci-lint?

When the failing workflow is the lint one, yes, with the version that workflow installs. Otherwise it runs `go vet` and `gofmt`, which every Go repository can run without extra configuration.

### What if the failing test needs Postgres?

It starts Postgres in the sandbox the way the workflow's `services` block does and runs the same Makefile target, such as `make integration-test` in miniflux, with the same environment variables.
