# Fix a Failing CI Build in a Spring Boot Project

Yes. A failed workflow starts an agent that reads the log, reruns ./mvnw verify on the same JDK in a sandbox and opens a pull request with the fix.

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

## What the agent does

The run starts when a workflow on the default branch ends in failure. The event lists the workflow name, head commit and failing check runs; the agent clones that commit into its sandbox and reads the failed job's log with `gh run view --log-failed`. A Maven or Gradle log is long, so it searches for the first `[ERROR]` or `FAILED` line and the plugin that produced it before reading anything else.

In an application like `spring-projects/spring-petclinic`, there are two build workflows for the same code. `maven-build.yml` sets up JDK 17 (`adopt`) and runs `./mvnw -B verify` with Maven 3.9.16 from `.mvn/wrapper/maven-wrapper.properties`; `gradle-build.yml` runs `./gradlew build` with the Spring Boot 4.1.0 plugin and a Java 17 toolchain. A third, `deploy-and-test-cluster.yml`, applies `k8s/` to a kind cluster and only runs when those manifests change. The `pom.xml` binds `spring-javaformat-maven-plugin` to the `validate` phase and runs Checkstyle with the `nohttp` rules, so a build can fail on formatting or an `http://` URL before any test compiles.

The agent installs the JDK the job used and runs the same command. For a format failure it runs `./mvnw spring-javaformat:apply` and checks the diff touches only what the commit changed. For a test failure it runs the one class, `./mvnw -B test -Dtest=OwnerControllerTests`, and reads the Surefire report under `target/surefire-reports/`. Most of the test classes are slice or unit tests (`OwnerControllerTests`, `VetControllerTests`, `ValidatorTests`, `I18nPropertiesSyncTest`), while `MySqlIntegrationTests` is `@Testcontainers(disabledWithoutDocker = true)` and `PostgresIntegrationTests` assumes Docker is available, so the agent notes when a failure is in a class that skips without Docker.

It fixes the cause in `src/main/java/` or in the template, message bundle or test that the commit broke, then reruns `./mvnw -B verify` and `./gradlew build`, because a change that passes one build and not the other still leaves a red check.

## Start it with one API call

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

```json
{
  "agent": "claude",
  "input": "The GitHub Actions run on the default branch failed; the event follows this prompt. Read the failed job's log and name the workflow, the JDK, and the first failing plugin, test class or step. Install that JDK, reproduce the failure with the job's exact Maven or Gradle command, fix the cause, and run both the Maven and Gradle builds if the repository has both. Open a pull request that quotes the failing log lines and explains the fix. Do not skip, mark flaky or delete a failing test, and do not disable Checkstyle or the formatter.",
  "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 whose description names the workflow and the failing plugin or test class, quotes the `[ERROR]` lines from the log, and shows the same command failing and then passing in the sandbox. The diff is the fix; a change to `pom.xml`, `build.gradle` or a workflow file is listed apart from the code because it changes every build.

Both build workflows run again on the pull request, so a reviewer sees Maven and Gradle green side by side. They check that no test gained `@Disabled`, that `src/checkstyle/` and the formatter plugin are untouched, and that a dependency version change agrees with the Spring Boot 4.1.0 parent rather than overriding it.

When the failure is in a class that needs Docker and the cause cannot be shown without it, the run says that, with what the log shows and what it checked, instead of reporting a fix it could not prove.

## Run it on every failed Maven or Gradle build on main

In the console, add an automation to the Project for this repository with the prompt above and a `github` trigger on `workflow_run.failure`, with `main` in its branch patterns. When both `Java CI with Maven` and `Java CI with Gradle` fail on the same commit, each failure is its own event; the runs-per-hour limit and the clear workflow name in each event keep that readable.

A redelivered event never starts a second run, and failures on contributors' forks are ignored. If you route alerts through your own service instead, it can call `POST /o/{org}/sessions` with this body and take the key's `run.completed` webhook when the pull request is open.

## Why run it on Rush?

A red Spring Boot build means a cold Maven or Gradle download, the right JDK and a few minutes of compile before the first failing test even runs, often on a machine with a different Java on its path. A Rush run does that in its own sandbox with each command and its output kept, so the evidence that the fix works is in the session, not in someone's terminal history.

Builds break in batches when a shared parent or a JDK image moves. Several repositories, or the Maven and Gradle builds of one, each get their own run on their own branch at once, and each ends with a pull request that GitHub's checks confirm or a report of what is still unexplained.

## Frequently asked questions

### Which JDK does the sandbox use?

The one the failing job set up, read from `actions/setup-java` in the workflow and from `<java.version>` or the Gradle toolchain. For PetClinic that is Java 17 in both builds.

### Can it fix a Checkstyle or spring-javaformat failure?

Yes. It runs the formatter's `apply` goal or fixes the line Checkstyle names, such as an `http://` URL the nohttp rule refuses, and the prompt forbids turning either check off.

### What about integration tests that need MySQL or PostgreSQL?

In PetClinic those classes use Testcontainers and Docker Compose and skip when Docker is missing. The agent tells you when a failure is in one of them, and the pull request's own CI run is where those tests prove the fix.

### We only use Gradle. Does it still work?

Yes. The agent runs whatever the failing step runs, whether `./gradlew build`, `./gradlew test --tests` or a Maven goal, and only runs the second build tool when the repository has a workflow for it.
