All jobs

Fix Jira Bug Tickets With Pull Requests in a Next.js App

Yes. An agent reads the Jira bug through the Atlassian connection, reproduces it in your Next.js team or billing code, opens a pull request and comments the link.

Run this on RushIn a Project that has your repository.

What the agent does

The agent reads the ticket key and summary after the prompt, then fetches the full issue, its description and every comment through the Atlassian connection. Bug tickets written by support rarely name a file, so it reads for the user-visible symptom: a team member who could not be removed, a checkout that sent someone back to pricing, a subscription that stayed on the old plan after Stripe changed it.

In a Next.js app like nextjs/saas-starter that symptom maps to a small set of files. package.json pins next to 15.6.0-canary.59 with React 19.1, drizzle-orm, postgres, stripe, jose and zod, with a pnpm-lock.yaml and no test runner at all. The team code is the server actions in app/(login)/actions.ts, inviteTeamMember, removeTeamMember, updateAccount, updatePassword and deleteAccount, each wrapped in validatedActionWithUser from lib/auth/middleware.ts, plus app/api/team/route.ts, which returns getTeamForUser() from lib/db/queries.ts. The tables are users, teams, teamMembers, activityLogs and invitations in lib/db/schema.ts.

The billing code is lib/payments/stripe.ts and lib/payments/actions.ts. checkoutAction and customerPortalAction are withTeam actions; createCheckoutSession redirects to /sign-up when there is no team or user and otherwise creates a subscription checkout with a 14-day trial and a client_reference_id of the user id; app/api/stripe/checkout/route.ts reads that session back, expands customer and subscription and throws when either is missing; and app/api/stripe/webhook/route.ts verifies the Stripe signature and passes customer.subscription.updated and deleted to handleSubscriptionChange, which writes planName, stripeProductId and subscriptionStatus through updateTeamSubscription. Each throw new Error in that path is a place a ticket can originate.

Because the repository has no tests, the agent adds Vitest as a dev dependency with a minimal vitest.config.ts, writes one test that calls the action or handler with the inputs the ticket describes, with getUser, db or stripe stubbed, and watches it fail. Then it changes the code until npx vitest run passes, runs pnpm build so the Next.js type check runs, and opens a pull request whose title starts with the ticket key. Last, it comments the pull request link on the Jira issue through the same connection.

Start it with one API call

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

{
  "agent": "claude",
  "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 the report describes in the team actions (app/(login)/actions.ts, app/api/team/route.ts, lib/db/queries.ts) or the billing code (lib/payments/stripe.ts, lib/payments/actions.ts, app/api/stripe/checkout/route.ts, app/api/stripe/webhook/route.ts). This repository has no test runner: add vitest as a dev dependency with a minimal vitest.config.ts, write one test that reproduces the ticket with getUser, db and stripe stubbed, and confirm it fails. Fix the cause, not the symptom, until npx vitest run passes, then run pnpm build. Open a pull request whose title starts with the ticket key and whose description quotes the failing test output, and comment the pull request link on the ticket. If you cannot reproduce the bug, comment on the ticket with what you tried and open no pull request.",
  "connections": [
    "atlassian"
  ],
  "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 key. In a saas-starter shaped app it usually changes one action in app/(login)/actions.ts or one function in lib/payments/stripe.ts, adds a test file beside it, and adds vitest plus vitest.config.ts if the repository had none. The description restates the ticket in one line, names the file and function at fault, quotes the test output before and after, and lists the commands it ran, npx vitest run and pnpm build.

The reviewer checks that the test exercises the real action and not a copy of it, that any stub of stripe or db returns a shape the real client would return, and that the change leaves the other actions alone; a fix in handleSubscriptionChange must not alter what createCheckoutSession does. A Stripe-related change also deserves a look at whether the webhook path still answers 400 on a bad signature.

On the Jira side the ticket gains one comment with the pull request link and a one-sentence cause. Nothing else on the ticket changes: no transition, no assignee, so the team's workflow decides when it moves to done.

Run it on every new Jira bug

Create a Jira automation rule with the trigger "Work item created", a condition that the issue type is Bug, and the action "Send web request" to a handler on your server with {{issue.key}} and {{issue.summary}} in the body. The handler appends them after the prompt, names your Atlassian connection in connections, sends the ticket key as Idempotency-Key and calls POST /o/{org}/sessions once per ticket. Jira cannot call a Rush webhook trigger itself, because the trigger needs Authorization: Bearer with its secret.

With a webhook URL on the API key, Rush POSTs run.completed or run.failed with the session_url when the turn finishes, so the handler can add a second Jira comment if the agent stopped without a pull request. A key runs at most max_concurrent sessions at once and answers 429 past that, which is the ceiling for a bug-bash afternoon.

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

Why run it on Rush?

Reproducing a billing bug on a laptop means a local Postgres, a Stripe test key, a webhook forwarder and a browser, and most tickets are abandoned at that step. The agent sets that up in its own sandbox each time, from pnpm install through pnpm db:migrate, and the engineer only reads the pull request. Ten tickets from a triage session can be ten sessions.

The pull request carries proof rather than a promise: the transcript shows the test failing before the change and passing after, and the pnpm build output that the type check ran. Because Vitest is added in the same pull request, the next ticket starts with a test runner already in place.

Frequently asked questions

The repository has no tests. Is adding Vitest in a bug-fix pull request acceptable?

It is the smallest honest way to show the bug existed. The pull request adds vitest as a dev dependency, one config file and one test file; nothing else in the toolchain changes. If you would rather keep that separate, say so in the prompt and the agent reproduces the bug with a script instead.

How does the agent read Jira?

Through the Atlassian connection named in connections, which is the Atlassian remote MCP server signed in as you. It reads the issue and its comments, and at the end posts one comment with the pull request link. It changes no fields and performs no transition.

Can it call Stripe?

Not in the test. stripe from lib/payments/stripe.ts is stubbed so the test runs without a key and without network. If the fix needs a real Stripe object shape, the agent reads the Stripe.Subscription and Stripe.Checkout.Session types the stripe package ships and builds the stub from them.

What if the ticket is not a bug in this code?

The agent comments on the ticket with what it tried, for example that removeTeamMember behaves as described only when the caller has no team, and opens no pull request. The run's result says the same, so the handler can route the ticket back to a person.

Will it touch the database migrations?

Only if the cause is in the schema, which is rare for a bug ticket. If it must, the pull request includes a new file under lib/db/migrations/ generated with pnpm db:generate and says so in the description, so the reviewer can plan the deploy.