What the agent does
The run opens on the pull request's branch and diffs it against the base, so the agent reads the change exactly as the reviewer will. In a multi-module build like spring-petclinic/spring-petclinic-microservices, it maps each changed file to its Maven module: a change to OwnerResource.java belongs to spring-petclinic-customers-service, a change to VisitResource.java to spring-petclinic-visits-service. It reads the controller methods the diff touches, such as createOwner, updateOwner and findOwner behind @RequestMapping("/owners"), or the two GET mappings and the POST owners/*/pets/{petId}/visits in the visits service.
Then it reads the tests that already exist, because new tests should look like them. That repository has PetResourceTest in the customers service and VisitResourceTest in the visits service, both @WebMvcTest slices with @ActiveProfiles("test"), repositories replaced by @MockitoBean, and assertions written with MockMvc and jsonPath. There is no OwnerResourceTest at all. The root pom.xml inherits spring-boot-starter-parent 4.0.1 with java.version 17, and the imports already use Spring Boot 4's org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest, so the agent writes against those packages rather than the Boot 3 ones most examples online still show.
For each changed method it writes the cases the diff introduces: the success response and its JSON body, the @Valid failures on OwnerRequest that should return 400, the @Min(1) path checks, and the not-found branch through ResourceNotFoundException. Where the change is in a repository query or an entity mapping rather than a controller, it uses a @DataJpaTest against the HSQLDB schema that application-test.yml already points at (classpath*:db/hsqldb/schema.sql), with Spring Cloud Config and Eureka disabled exactly as that file sets them.
It runs only the modules it touched, ./mvnw -pl spring-petclinic-customers-service,spring-petclinic-visits-service test, so the Maven wrapper's 3.3.2 download and the build stay small, then the full ./mvnw test once before pushing. It checks each new test can fail by reverting the line under test and seeing it go red, and it leaves src/main alone.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "codex",
"input": "This pull request changes the customers and visits services. Read the diff against the base branch, find the new or changed behavior that no test covers, and write JUnit 5 tests for it next to the existing tests in each module's src/test/java, in the style of PetResourceTest and VisitResourceTest: @WebMvcTest slices with @ActiveProfiles(\"test\") and MockMvc for controllers, @DataJpaTest for repository changes. Cover success responses, validation failures and not-found cases. Run ./mvnw -pl <changed modules> test until they pass, then ./mvnw test. Do not change anything under src/main. Push the tests to this pull request's branch and comment on the pull request listing each test and what it covers.",
"resources": [
{
"url": "https://github.com/your-org/your-app/pull/123"
}
]
}- 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.
- 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.
- 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
The pull request gets one more commit, on its own branch, with test files only: for example a new OwnerResourceTest.java under spring-petclinic-customers-service/src/test/java/.../customers/web/ and new methods in VisitResourceTest.java. If a module needs a test dependency it does not declare yet, the commit adds it to that module's pom.xml in test scope and the comment says why. The push re-runs the repository's own maven-build.yml workflow, which runs mvn -B package on JDK 17, so the new tests pass on GitHub's runner as well as in the sandbox.
A comment on the pull request lists every test method by name with the endpoint and case it covers ("shouldRejectOwnerWithBlankFirstName: POST /owners without firstName returns 400"), names any changed behavior it did not test and why, and flags anything that looks like a bug instead of writing a test that would enshrine it. The session's record has every Maven run with its Surefire output.
A reviewer checks that the mocked repository calls match what the controller really does, that each test asserts on the response the pull request promises, and that no test relies on data from the HSQLDB data.sql that another test changes.
Run it on every pull request opened
Create an automation in the console with a GitHub trigger on pull_request.opened, branch pattern main, and this prompt. Each pull request from someone with write access to the repository starts its own run; pull requests from forks are ignored. With pull_request.synchronize added, every later push to the branch gets a fresh look, which suits teams that open draft pull requests early.
If your services live in several repositories, add the trigger to each repository's Project. One run covers one repository, and runs for different services proceed side by side, so a change that touches the customers service and a separate change to the vets service are tested at the same time.
The use case this job follows, with its automation and trigger: Write the missing tests.
Why run it on Rush?
Testing a Spring Cloud service on a laptop means a JDK 17 install, a Maven cache, and remembering that the test profile turns off Config Server and Eureka, otherwise the context will not start. Doing that for every colleague's pull request competes with your own work. On Rush each pull request gets a sandbox with its own clone and its own Maven cache, the agent runs the real ./mvnw there, and your checkout never switches branches.
The commit is backed by evidence: the Maven output in the session's record, the repository's own CI run on the push, and a comment that maps every test to a line of the diff. Several pull requests opened in the same hour are handled in parallel, each with its own run, so coverage keeps up with the change rate instead of waiting for a cleanup sprint.
Frequently asked questions
Will it use @MockBean or @MockitoBean?
It matches what your tests already use and what your Spring Boot version supports. In a Boot 4 project like PetClinic microservices that is @MockitoBean from org.springframework.test.context.bean.override.mockito, because @MockBean was deprecated in Boot 3.4 and removed in 4.0. On Boot 3.3 or earlier it uses @MockBean.
Does it start the whole microservice stack?
No. It writes slice tests (@WebMvcTest, @DataJpaTest) and runs each module with the test profile, which disables Config Server and Eureka. If your pull request changes how two services talk to each other, it says so in the comment and suggests a contract or integration test rather than starting every container.
We use Gradle, not Maven. Does it still work?
Yes. It reads the build tool from the repository and runs ./gradlew test (or the module's :service:test task) instead. Change the command in the prompt if your team runs tests through a different task.
Can it push to a protected branch?
It pushes to the pull request's head branch, not to main. If branch protection blocks pushes to that branch, the push fails and the agent says so in its answer, so open the pull request from a branch the Rush GitHub App can write to.