# Turn a Jira Issue into a Pull Request for an ASP.NET Core App

Yes. Send one request from your terminal; an agent reads the Jira issue, does the work in your ASP.NET Core repo with tests and opens a PR.

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

## What the agent does

The agent reads the Jira issue through the Atlassian connection before it reads any code: the summary, the description, the acceptance criteria field or checklist your project uses, every comment, and linked issues. Comments matter most, because that is where "actually, keep the old endpoint for a release" lives. It writes the criteria down as a list it will test against.

Then it finds where the change belongs in the solution. In an app built on jasontaylordev/CleanArchitecture, `CleanArchitecture.slnx` lists `src/Domain`, `src/Application`, `src/Infrastructure` and `src/Web`, and `global.json` pins the .NET SDK to `10.0.402`. Features are vertical slices: a command like `src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs` has its MediatR handler beside a FluentValidation validator (`CreateTodoItemCommandValidator` caps `Title` at 200 characters and requires it), and `src/Web/Endpoints/TodoItems.cs` maps it to a route. A Jira issue that adds a field or a rule becomes a change to the entity in `src/Domain`, the command and its validator, the EF Core configuration under `src/Infrastructure`, and the endpoint, following that same slice shape rather than a new pattern.

It writes tests where the template already keeps them. `tests/Application.FunctionalTests/TodoItems/Commands/` holds one NUnit test class per command (`CreateTodoItemTests.cs`, `UpdateTodoItemTests.cs`, ...), using Shouldly assertions and `TestBase`, which resets the database between tests with Respawn. Those functional tests boot `tests/TestAppHost` through Aspire's testing builder, which starts SQLite, PostgreSQL or SQL Server depending on how the template was generated, so the agent runs them in its sandbox with the real database the app uses rather than a stub. Domain rules get unit tests in `tests/Domain.UnitTests`.

Before pushing it runs `dotnet build` and `dotnet test` on the solution, reads any failure, and fixes the cause. Package versions stay central in `Directory.Packages.props`, so if the issue needs a new package it adds a `PackageVersion` there rather than a version in a project file. Then it opens the pull request with the Jira key in the title, and comments the pull request link on the issue.

## Start it with one API call

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

```json
{
  "agent": "claude",
  "input": "Read Jira issue PROJ-123 through the Atlassian connection, including its description, acceptance criteria, comments and linked issues, and list the criteria. Do the work in this ASP.NET Core solution following its existing Clean Architecture slices: domain changes in src/Domain, a command or query with its FluentValidation validator in src/Application, EF Core configuration and a migration in src/Infrastructure if the schema changes, and the endpoint in src/Web/Endpoints. Add NUnit tests in tests/Application.FunctionalTests for each criterion and unit tests in tests/Domain.UnitTests for new domain rules. Run dotnet build and dotnet test and fix what fails. Open a pull request titled with the issue key that maps each criterion to its test, then comment the pull request link on the Jira issue.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-dotnet-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 titled with the issue key and a comment on the Jira issue linking to it. In a solution shaped like CleanArchitecture, the diff is one vertical slice: the entity or value object under `src/Domain`, a command or query folder under `src/Application/<Feature>/` with its handler and validator, the EF Core configuration and a migration under `src/Infrastructure` when the schema changed, the endpoint in `src/Web/Endpoints/`, and test classes under `tests/Application.FunctionalTests/<Feature>/` and `tests/Domain.UnitTests`.

The description restates the acceptance criteria from Jira and names the test that covers each. The session's trajectory keeps every command with its output, including the `dotnet test` run against the database the functional tests start, so a reviewer can see that the new tests ran and passed rather than just compiled. The repository's own workflow (`.github/workflows/build.yml` in the template) runs on the pull request as usual.

Before merging, a reviewer checks the migration's `Up` and `Down`, that validation lives in the validator and not scattered in the handler, that the endpoint's authorization matches its neighbours in `src/Web/Endpoints/`, and that the NSwag client `src/Web/ClientApp-React/nswag.json` generates was regenerated if the API contract changed.

## Run it on every Jira issue labelled agent

Add a Jira automation rule or a Jira webhook that fires when an issue gets the label your team picks, and have your server send this request with the issue key in `input` and the repository in `resources`. Each issue gets its own run, its own sandbox and its own branch, so a sprint's worth of small issues labelled on Friday come back as separate pull requests to review one at a time.

Set a webhook URL on the API key and Rush POSTs `run.completed` or `run.failed` when each turn finishes, with the `session_url`, so your server can transition the issue to In Review. Send the issue key as the `Idempotency-Key` header so a rule that fires twice for one issue starts one run.

## Why run it on Rush?

Doing a Jira issue in this kind of solution on a laptop means the .NET 10 SDK, the Aspire tooling, a container runtime for the database the functional tests start, and a build that ties up the machine while it runs. On Rush the agent does all of that in its own sandbox with its own clone, started by one request from the terminal, and the work continues after you log off. Your local branch, database and IDE state are untouched.

What you come back to is checkable: a pull request with the tests that cover the issue's criteria, a CI run on it, and a trajectory with every `dotnet` command and its output. Several issues can run at the same time, each isolated from the others, each waiting for a person to review before it merges.

## Frequently asked questions

### Can I put the Jira link in resources?

No. `resources` takes a GitHub repository or a Linear issue, and any other URL is refused with `422 RESOURCE_UNSUPPORTED`. Put the issue key in `input` and name your Atlassian connection in `connections`, and the agent reads the issue through it.

### How do I connect Jira?

Atlassian is in Rush's MCP catalog and covers Jira and Confluence. Connect it once with `POST /me/connections`; it signs in with OAuth through an `authorize_url` you open while signed in to the console. Then name it in each run's `connections`, because a key run gets only the connections it names.

### Will the functional tests run without SQL Server on my machine?

They do not run on your machine at all. The agent runs `dotnet test` in its own sandbox, where `tests/TestAppHost` starts the database the template was generated with. If your fork uses SQL Server or PostgreSQL and the sandbox cannot start it, the agent says so in the pull request instead of skipping the tests quietly.

### What does "from my terminal" mean here?

One `curl -X POST https://api.prix.dev/o/$ORG/sessions` with your API key and this body. The `202` answer carries the `execution_id`; after that the run needs nothing from your terminal, and you read the result later from the session, the event stream or the key's webhook.
