All jobs

Fix Jira Bug Tickets With Pull Requests in an ASP.NET Core App

Yes. An agent reads the Jira bug, reproduces it with a test in your ASP.NET Core services, fixes it, opens a pull request and links it on the ticket.

Run this on RushIn a Project that has your repository.

What the agent does

The run starts when someone files a bug. A Jira automation rule posts the new work item's key and summary to a handler on your server, which sends the request on this page with them appended to the prompt. The agent clones the repository into its own cloud sandbox and, through your Atlassian connection, reads the full ticket: description, steps to reproduce, environment, attachments listed on it and every comment. The summary in the webhook is a starting point; the comments are often where the real repro lives.

Then it finds the code. In a solution like dotnet/eShop the services sit side by side under src/, so a ticket about orders or the basket narrows to two projects. Ordering.API maps its minimal API under api/orders in Apis/OrdersApi.cs: PUT /cancel and PUT /ship take an x-requestid header and return BadRequest for an empty GUID, and a cancel the mediator refuses becomes a Problem with status 500 and "Cancel order failed to process." Basket.API is gRPC, defined in Proto/basket.proto (GetBasket, UpdateBasket, DeleteBasket) and implemented in Grpc/BasketService.cs, which throws RpcException with Unauthenticated or NotFound. The agent matches the ticket's symptom to one of these paths before changing anything.

It reproduces the bug as a failing test in the framework that project already uses, because eShop uses two. Basket.UnitTests and Ordering.UnitTests are MSTest.Sdk projects with NSubstitute (BasketServiceTests substitutes IBasketRepository and calls the service with a TestServerCallContext). Ordering.FunctionalTests and Basket.FunctionalTests are xUnit v3 (xunit.v3.mtp-v2) on the Aspire app host SDK: OrderingApiFixture starts Postgres through AddPostgres("OrderingDB") and RedisFixture starts Redis, which need Docker. The agent writes the narrowest test that shows the bug, a unit test when the logic is in a handler or the gRPC service and a functional [Fact] when the bug only shows over HTTP.

Once the test fails for the reason in the ticket, it fixes the code, builds with dotnet build eShop.Web.slnf and runs dotnet test (the repository's global.json pins SDK 10.0.302 and selects Microsoft.Testing.Platform as the runner). It opens a pull request whose title and branch carry the ticket key, so Jira's development panel links them, and adds a comment on the ticket through the Atlassian connection with the pull request link and one line on the cause.

Start it with one API call

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

{
  "agent": "codex",
  "input": "A Jira bug ticket was created; its key and summary follow this prompt. Use the Atlassian connection to read the ticket, its description and all comments. Find the code in the ordering and basket services (src/Ordering.API/Apis/OrdersApi.cs, the Ordering.API command handlers, src/Basket.API/Grpc/BasketService.cs). Reproduce the bug with a failing test in the framework that project already uses: MSTest with NSubstitute in Ordering.UnitTests or Basket.UnitTests, or an xUnit [Fact] in Ordering.FunctionalTests or Basket.FunctionalTests when it only shows over HTTP. Fix the code, run dotnet build eShop.Web.slnf and dotnet test until they pass, and say which tests could not run in the sandbox and why. Open a pull request with the ticket key in its title and branch name, then add a comment on the ticket with the pull request link and the cause in one sentence. If you cannot reproduce it, comment on the ticket with what you tried and open no pull request.",
  "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 named after the ticket, such as <KEY>: return 404 when cancelling an order that does not exist. In eShop it usually changes one file under src/Ordering.API or src/Basket.API and adds one test to the matching test project. The description restates the ticket in a sentence, explains the cause with the file and method, shows the test that failed before the change, and lists the dotnet test result per project.

On the Jira side the ticket gets one comment with the pull request link, so whoever filed it sees progress without leaving Jira. The pull request's checks run your own workflow; in eShop pr-validation.yml builds eShop.Web.slnf and runs dotnet test --solution eShop.Web.slnf, which includes the Aspire functional tests on GitHub's runners. The session's transcript keeps every command and its output, from the first failing test to the last passing run.

Before merging, a reviewer checks that the new test fails on main and passes on the branch, that the fix is in the service that owns the behaviour rather than a guard in the caller, and that the HTTP status or gRPC StatusCode it now returns is what the ticket's reporter expected. When the agent could not reproduce the bug, there is no pull request: the ticket's comment says what it tried.

Run it on every new Jira bug

In Jira, create an automation rule with the trigger "Work item created", a condition on the issue type Bug (or a label such as agent-fix), and the action "Send web request" to your handler with {{issue.key}} and {{issue.summary}} in the body. The handler appends them to input and sends one request per ticket, naming your Atlassian connection in connections so the agent can read and comment on the ticket.

Set a webhook URL on the API key and Rush POSTs run.completed or run.failed with the session_url when the turn finishes. A key runs at most max_concurrent sessions at once (4 by default) and answers 429 past that, so a bug bash that files twenty tickets should queue in the handler.

The use case this job follows, with its automation and trigger: Fix a bug from an alert.

Why run it on Rush?

Reproducing a bug in a solution with nine test projects, an Aspire app host and containers for Postgres and Redis is exactly the setup a developer does not want to rebuild for each ticket. In a Rush sandbox the agent installs the .NET SDK from global.json, restores the solution and runs the tests on its own machine, so nobody's local Docker or SDK is touched and each ticket starts from a clean checkout.

The proof is the test and its history. The transcript shows the failing test before the fix and the passing run after, the pull request's checks repeat it on GitHub, and the Jira comment ties the two together. Several tickets filed in the same hour each get their own sandbox and their own pull request instead of waiting in one person's queue.

Frequently asked questions

Can I put the Jira ticket URL in resources?

No. resources takes a GitHub repository or a Linear issue; any other URL is 422 RESOURCE_UNSUPPORTED. For Jira, put the key in the prompt and name your Atlassian connection in connections, and the agent reads the ticket through it.

eShop has both MSTest and xUnit. Which does the test use?

Whichever the project it lands in already uses. The unit test projects are MSTest.Sdk with NSubstitute and the functional test projects are xUnit v3 on Aspire. The agent does not add a third framework or move tests between them.

What about functional tests that need Postgres and Redis?

OrderingApiFixture and RedisFixture start them through Aspire, which needs a container runtime. The agent reports whether those tests ran in its sandbox or were skipped, and your pull request workflow runs them on GitHub's runners either way.

What if the ticket is too vague to reproduce?

The prompt tells the agent to comment on the ticket with what it tried and open no pull request. The reporter can add steps in a comment, and a follow-up message on the same session (or a new run) picks them up.