# Turn a Jira Issue into a Pull Request for a Spring Boot App

Yes. One request starts an agent that reads the Jira issue, makes the change in your Spring Boot repo, runs ./mvnw verify and opens a PR.

[Run this on Rush](https://cloud.getrush.ai/run/jira-issue-to-pr/spring-boot/), in a Project that has your repository.

## What the agent does

The agent opens the Jira issue through the Atlassian connection and reads all of it: summary, description, acceptance criteria, comments, the issue type and anything linked. A bug report gets its reproduction steps written down first; a story gets a list of the behaviours the criteria name. That list is what the pull request will be checked against.

Next it reads the build and the layout. In a Spring Boot app like spring-projects/spring-petclinic, `pom.xml` inherits `spring-boot-starter-parent` 4.1.0 with `java.version` 17, and the build runs more than tests: `spring-javaformat-maven-plugin` validates formatting, Checkstyle 12.3.1 runs a `check` goal with the nohttp rules, and JaCoCo instruments the run. The code is organised by feature, not by layer: `owner/` holds `OwnerController`, `Owner`, `OwnerRepository` (a Spring Data repository with `findByLastNameStartingWith(String lastName, Pageable pageable)`), `PetController`, `PetValidator` and `VisitController`, with Thymeleaf views under `src/main/resources/templates/owners/` and message bundles in 11 `messages*.properties` files. An issue such as "search owners by city" turns into a repository method, a controller change, a form field in `findOwners.html` and new message keys.

It writes tests the way the existing ones are written. Controller tests like `OwnerControllerTests` use `@WebMvcTest(OwnerController.class)` with `@MockitoBean` repositories and MockMvc, so the agent adds cases there for each criterion. `I18nPropertiesSyncTest` checks that the message files stay in step, so a new label added to `messages.properties` has to reach the other languages too, and the agent adds those keys rather than letting the test fail. `PetClinicIntegrationTests` boots the full app on H2 at a random port; `MySqlIntegrationTests` is marked `@Testcontainers(disabledWithoutDocker = true)` and `PostgresIntegrationTests` starts the `postgres` service from `docker-compose.yml`, and the agent reports which of those ran in its sandbox.

Before pushing it runs `./mvnw spring-javaformat:apply` and then `./mvnw -B verify`, the same command `.github/workflows/maven-build.yml` runs on Java 17, and fixes anything red. Then it opens the pull request with the issue key in the title and comments the link on the Jira issue.

## Start it with one API call

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

```json
{
  "agent": "codex",
  "input": "Read Jira issue PROJ-456 through the Atlassian connection, including its description, acceptance criteria, comments and linked issues, and list the criteria. Make the change in this Spring Boot repository inside the existing feature package (owner, vet or system), extending the controller, repository and Thymeleaf templates already there. Add any new message keys to every messages*.properties file so I18nPropertiesSyncTest passes. Add @WebMvcTest cases for each criterion next to the existing controller tests, and an integration test if the change touches a repository query. Run ./mvnw spring-javaformat:apply and ./mvnw -B verify and fix what fails, and say which database integration tests ran. Open a pull request titled with the issue key that maps each criterion to a test, then comment the pull request link on the Jira issue.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-spring-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 the Jira key in its title, and a comment on the issue that links to it. For a petclinic-shaped repository, the diff stays inside one feature package: the controller and repository under `src/main/java/.../owner/` (or `vet/`), the template under `src/main/resources/templates/`, the message keys across the `messages*.properties` files, and new test methods in the matching `*ControllerTests` class, plus an integration test when a query changed.

The description lists the acceptance criteria from Jira, the test that covers each, and which integration tests ran: the H2 one always, the MySQL and PostgreSQL ones only when Docker was available in the sandbox. The session's trajectory keeps the full `./mvnw -B verify` output, including the format check and Checkstyle, so a reviewer sees the same build CI will run. The repository's Maven and Gradle workflows then run on the pull request.

Before merging, a reviewer checks that a new repository method does what the issue asked against real data (a derived query name can match more than intended), that translated message keys are real translations or clearly marked for a translator, and that the controller still validates input through the existing `@Valid` and `PetValidator` path rather than a new one.

## Run it on every Jira issue moved to Ready for Dev

Use a Jira automation rule with a "Send web request" action, or a Jira webhook filtered by JQL, to call your server when an issue enters the column your team uses for agent work. Your server sends this request with the issue key in `input` and the repository in `resources`. Each issue runs in its own sandbox on its own branch, so the pull requests stay independent and can be reviewed in any order.

With a webhook URL on the API key, Rush POSTs `run.completed` or `run.failed` when each turn finishes, so your server can move the issue to In Review or flag it for a person. A key runs at most `max_concurrent` sessions at once (4 by default); a rule that fires for a whole sprint at once should queue past that instead of retrying a `429`.

## Why run it on Rush?

A full `./mvnw verify` on a Spring Boot app with format checks, Checkstyle, JaCoCo and database integration tests takes over the laptop while it runs, and Testcontainers needs a local Docker daemon. On Rush the agent runs that build in its own sandbox with its own clone and Maven cache, started with one request from the terminal, and it keeps going after you sign off. Your IDE, your local Docker and your checked-out branch are left alone.

The morning result is a pull request you can check rather than trust. The build output is in the trajectory, CI runs on the pull request, and the description maps each Jira criterion to a test. A team can start several issues at once, each isolated from the others, each waiting for review before anything merges.

## Frequently asked questions

### Will the Testcontainers integration tests run?

They run when Docker is available in the sandbox; `MySqlIntegrationTests` is marked `disabledWithoutDocker = true`, so without Docker it is skipped rather than failing. The request asks the agent to say which database tests ran, so the pull request never implies coverage it did not have. Your CI runs the rest.

### Does it work with Gradle instead of Maven?

Yes. It uses the build the repository has. petclinic ships both `pom.xml` and `build.gradle` with wrappers, and the agent runs whichever the issue's change needs to keep green; name one in `input` if your team only uses one.

### How does the agent read the Jira issue?

Through the Atlassian server in Rush's MCP catalog, which covers Jira and Confluence. Connect it once with `POST /me/connections`, then name it in the request's `connections`. The issue key goes in `input`; a Jira URL in `resources` is refused with `422 RESOURCE_UNSUPPORTED`.

### What if the issue is missing acceptance criteria?

It writes down the criteria it inferred from the description and comments, and puts them at the top of the pull request so a reviewer can disagree with them. If the issue is too thin to act on, it comments a question on the issue and stops; reply with a follow-up message to the same session and it continues from there.
