All jobs

Turn GitHub Issues into Pull Requests for a Spring Boot App

Yes. Label a GitHub issue on a Spring Boot app and an agent reproduces it with a MockMvc test, fixes the controller and opens a pull request that closes the issue.

Run this on RushIn a Project that has your repository.

What the agent does

The agent reads the issue and then the build before touching Java. In an app like spring-projects/spring-petclinic, pom.xml inherits spring-boot-starter-parent 4.1.0, sets java.version to 17, binds spring-javaformat-maven-plugin to validate and runs Checkstyle with the nohttp rules from src/checkstyle/ in the same phase, so a formatting slip or an http:// string fails the build before compilation. There is a parallel build.gradle and Gradle 9.5.1 in gradle/wrapper/gradle-wrapper.properties, and .github/workflows/ runs ./mvnw -B verify and ./gradlew build on JDK 17 as two separate workflows. Maven is 3.9.16 through .mvn/wrapper/maven-wrapper.properties. The agent uses the wrappers and never a global Maven.

The code the issue names is small and structured. The owner package has OwnerController, PetController and VisitController, the Owner, Pet, PetType and Visit entities, OwnerRepository with findByLastNameStartingWith(String, Pageable), and PetValidator. OwnerController.processFindForm strips the last name, pages five at a time through findPaginatedForOwnersLastName, redirects to page 1 when the page is out of range, rejects lastName with notFound when nothing matches and redirects straight to the owner when exactly one does. PetController.processCreationForm rejects a duplicate pet name with duplicate and a future birth date with typeMismatch.birthDate, and catches DataIntegrityViolationException for the database-level duplicate. VisitController.processNewVisitForm rejects a date that is not after today with typeMismatch.visitDate, and its minVisitDate model attribute is tomorrow. Messages for those codes live in src/main/resources/messages/messages.properties and the ten locale files beside it.

The reproduction is a test in the class that already covers the controller. OwnerControllerTests, PetControllerTests and VisitControllerTests are @WebMvcTest slices with a @MockitoBean repository and MockMvc, so a request like post("/owners/{ownerId}/pets/{petId}/visits/new").param("date", LocalDate.now().toString()) with model().attributeHasFieldErrorCode("visit", "date", "typeMismatch.visitDate") is the shape of an issue about validation. A persistence issue needs ClinicServiceTests or PetClinicIntegrationTests, which starts the app on a random port against H2 with database=h2 from application.properties; MySqlIntegrationTests and PostgresIntegrationTests use Testcontainers and are disabledWithoutDocker, so the agent runs them when the sandbox has Docker and says so either way. A message change is checked by I18nPropertiesSyncTest, which fails when a key is missing from a locale file or a template has hard-coded text outside th:text.

The fix stays in the layer the issue names and keeps the form flow: a validation issue is a rejectValue in the controller or a constraint on the entity (Owner.telephone is \d{10} with the telephone.invalid message), a search issue is in processFindForm or the repository query, a display issue is in the Thymeleaf template under src/main/resources/templates/. The agent runs ./mvnw spring-javaformat:apply on the files it touched, then ./mvnw -B test -Dtest=<Class> for the fast loop and ./mvnw -B verify and ./gradlew build before opening the pull request, because a change that passes one build and not the other still leaves a red check. The pull request body says Closes #<issue> and quotes the failing then passing test.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Fix the GitHub issue that follows this prompt in this Spring Boot 4.1 application on Java 17 with Maven and Gradle wrappers. Read pom.xml, the controller, entity, repository and Thymeleaf template the issue concerns, and the existing test class for that controller. Reproduce the reported behavior first with a test in that class: a @WebMvcTest with MockMvc for a request, binding or validation behavior, or ClinicServiceTests or PetClinicIntegrationTests when persistence is involved. Run it alone with ./mvnw -B test -Dtest=<Class> and confirm it fails. Fix the cause in the controller, entity, repository, template or messages.properties and its locale files, keeping the existing form flow and redirects. Run ./mvnw spring-javaformat:apply on the files you edited, then ./mvnw -B verify and ./gradlew build until both pass. Do not disable Checkstyle, the formatter or a test. Open a pull request whose description says Closes #<issue>, explains the cause and quotes the failing then passing test.\n\nIssue #88: Searching owners by last name with trailing spaces returns no results even though the owner exists.",
  "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 with Closes #<issue> in its body. The diff holds the new test method in the controller's existing test class or in an integration test, the fix in src/main/java/org/springframework/samples/petclinic/, and, when a message code changed, the key in messages.properties and each locale file so I18nPropertiesSyncTest stays green. The description names the cause in the code's own terms, quotes the test failing before the fix, and quotes the ./mvnw -B verify and ./gradlew build summaries after it.

The reviewer reads the test first and confirms it fails on main. Then they check the fix kept the MVC flow: the same view names, the same redirects, the same rejectValue codes, no @Disabled, and no change to src/checkstyle/ or the formatter plugin. Both Java CI with Maven and Java CI with Gradle run on the pull request, so the reviewer sees the two builds green on GitHub rather than taking the sandbox's word.

When the issue is in a class that needs Docker and the sandbox could not run it, the run says that, with what it did run and what remains for the pull request's own CI, instead of reporting a fix it could not prove. The session keeps every Maven and Gradle command and its output.

Run it on every GitHub issue labelled agent

In the console, add an automation to the Project with this prompt and a github trigger on issues.labeled, filtered to the agent label in config.labels. The trigger appends the issue after the prompt, so leave the example issue out of the automation's prompt. Only labels added by an owner, member or collaborator fire it, by GitHub's author_association. Each labelled issue gets its own sandbox, branch and pull request, and max_runs_per_hour bounds a triage session that labels many at once.

The same request can come from your own tracker through POST /o/{org}/sessions, with the issue's text after the prompt and the delivery id as the Idempotency-Key. Set a webhook_url on the key and Rush POSTs run.completed when the turn finishes, with the session_url that reads the pull request.

The use case this job follows, with its automation and trigger: Turn a Linear label into a PR.

Why run it on Rush?

Reproducing a Spring Boot issue means JDK 17, a cold Maven and Gradle download, a formatter that must run before the compiler, and a suite that mixes MockMvc slices with Testcontainers classes that silently skip without Docker. On a laptop that is a different Java on the path and an afternoon. A Rush run builds from the wrappers in its own sandbox, keeps every command and its output, and the pull request quotes the failing test rather than asserting there was one.

The fix is proportionate because the agent reads the controller, the validator codes and the message bundles before editing, and runs both builds because the repository has both. Several labelled issues run at once, each on its own branch, and each ends in a pull request that two GitHub workflows confirm, or in a note explaining why the issue could not be reproduced.

Frequently asked questions

Which JDK does it use?

Java 17, from <java.version> in pom.xml and the toolchain in build.gradle, which is also what both workflows set up with actions/setup-java. The maven-enforcer-plugin refuses an older JVM, so the sandbox installs 17 before running the wrapper.

MockMvc passed. Does that prove the database change?

No. The controller tests mock OwnerRepository with @MockitoBean, so they prove binding, validation and the view, not a write. For a persistence issue the agent adds to ClinicServiceTests or PetClinicIntegrationTests, which run against H2, and the pull request labels which kind of evidence it has.

Will it fix a formatting or nohttp failure it caused?

Yes. spring-javaformat-maven-plugin and Checkstyle both run in the validate phase, so the agent runs spring-javaformat:apply on the files it edited and avoids http:// literals. It never turns either plugin off.

What if the fix changes a user-facing message?

It adds or changes the key in messages.properties and in each messages_<locale>.properties beside it, because I18nPropertiesSyncTest fails when a key is missing from any locale, and it keeps template text inside th:text for the same test's hard-coded string check.

Does it run the MySQL and PostgreSQL integration tests?

When the sandbox has Docker, MySqlIntegrationTests starts a mysql:9.7 container through Testcontainers and PostgresIntegrationTests uses docker-compose.yml; without it they are skipped as disabledWithoutDocker says. The pull request states which ran, and the GitHub workflows run them again.