# Fix Jira Bug Tickets With Pull Requests in a Django App

Yes. An agent reads the Jira bug, reproduces it with a Django TestCase, fixes the view or integration, opens a pull request and comments the link on the ticket.

[Run this on Rush](https://cloud.getrush.ai/run/fix-jira-bugs/django/), in a Project that has your repository.

## What the agent does

A Jira automation rule sends the new bug's key and summary to a handler on your server, and the handler sends the request on this page. The agent clones the repository into its own cloud sandbox and reads the ticket through your Atlassian connection: the description, the reporter's environment and every comment. For a monitoring service the details that matter are usually in there, such as the exact ping URL, the HTTP method, the exit status in the path or which integration failed to deliver.

In a Django project like healthchecks/healthchecks, the ping API is a short list of routes in `hc/api/urls.py`: `views.ping` behind `/ping/<uuid:code>` with `fail`, `start`, `log` and `<int:exitstatus>` variants, and `views.ping_by_slug` for the same actions by project ping key and slug. `ping` in `hc/api/views.py` answers `not found` for an unknown check and `invalid url format` for an exit status above 255, and reads the client address from `X-Forwarded-For` before `REMOTE_ADDR`. Alert integrations live one per directory under `hc/integrations/` (30 of them, from slack and webhook to telegram and opsgenie), each with a `transport.py` subclassing `Transport` or `HttpTransport` from `hc/api/transports.py`. The agent maps the ticket to one of these before it edits.

It reproduces the bug as a test next to the existing ones. The ping tests are in `hc/api/tests/test_ping.py` and `test_ping_by_slug.py`; each integration has its own `tests/` folder with `test_notify.py`, which patches `hc.api.transports.curl.request` so no real request leaves the sandbox. Tests inherit `BaseTestCase` from `hc/test.py`, which sets up users, a project and API keys. The agent writes the failing case first, so the pull request can show it failing before the fix.

Then it fixes the code and runs `python manage.py test`, first for the one module and then for the whole suite. `hc/settings.py` uses SQLite unless the `DB` environment variable is `postgres`, `mysql` or `mariadb`, so the sandbox run is on SQLite. Once the suite passes it opens a pull request with the ticket key in the title and branch, and comments on the ticket with the pull request link and the cause in a sentence.

## Start it with one API call

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

```json
{
  "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 in the ping API (hc/api/urls.py, ping and ping_by_slug in hc/api/views.py) or in the alert integration it names (hc/integrations/<name>/transport.py and hc/api/transports.py). Reproduce the bug with a failing Django TestCase that extends BaseTestCase from hc/test.py, in hc/api/tests/ or the integration's tests/ folder, patching hc.api.transports.curl.request as the existing notify tests do. Fix the code and run python manage.py test until it passes. Open a pull request with the ticket key in its title and branch name, then comment on the ticket with the pull request link and the cause in one sentence. If you cannot reproduce it, comment 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. In healthchecks it typically changes one view in `hc/api/views.py` or one `transport.py` under `hc/integrations/`, and adds a test method to the matching `test_ping.py`, `test_ping_by_slug.py` or `test_notify.py`. The description restates the bug, names the file and function at fault, quotes the test that failed before the change, and gives the `python manage.py test` result.

The ticket gets one comment with the pull request link. The pull request's checks are your workflows: in healthchecks, `tests.yml` runs `python manage.py test` across SQLite, Postgres, MySQL and MariaDB and Python 3.12 to 3.15, and `mypy.yml` runs `mypy --strict` over `hc`. That matters here, because the sandbox run is on SQLite and a fix that touches a query has to pass on all four databases. The transcript keeps every command and its output.

Before merging, a reviewer checks that the new test fails on `main`, that a fix to one integration did not change the shared `HttpTransport` behaviour the others depend on, and that the type hints still satisfy `mypy --strict`. If the agent could not reproduce the bug, there is no pull request, and the ticket comment says what it tried.

## Run it on every new Jira bug

Create a Jira automation rule: trigger "Work item created", condition issue type is Bug (narrow it with a component such as Ping API or Integrations if you like), action "Send web request" to your handler with `{{issue.key}}` and `{{issue.summary}}`. The handler appends them to `input`, names your Atlassian connection in `connections`, and sends one request per ticket.

With a webhook URL set on the API key, Rush POSTs `run.completed` or `run.failed` and the `session_url` when the agent's turn finishes. A key runs at most `max_concurrent` sessions at once (4 by default) and answers `429` past that.

## Why run it on Rush?

Fixing a Django bug well means running the suite, not reading code and guessing. In a Rush sandbox the agent installs `requirements.txt` (Django 6.1, pycurl and psycopg among them), creates the SQLite database the tests use and runs them on its own machine. Nothing installs on a developer's laptop, and each ticket starts from a clean clone instead of a branch someone was halfway through.

The proof travels with the result: the failing test and the passing run are in the transcript, the database matrix runs on the pull request, and the Jira comment points the reporter at it. A batch of tickets filed after a release each get their own sandbox and their own pull request, so one hard bug does not hold up the easy ones.

## Frequently asked questions

### Will the tests send real Slack or webhook notifications?

No. The integration tests patch `hc.api.transports.curl.request`, and the agent writes its test the same way. Nothing is delivered from the sandbox.

### Does it test against Postgres or MySQL?

In the sandbox it runs on SQLite, the default in `hc/settings.py`. Put `DB=postgres` in the prompt if you want it to install Postgres and run the suite there too; otherwise the pull request's `tests.yml` matrix covers all four databases.

### Can I put the Jira ticket URL in resources?

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

### What if the bug is in a third-party service, not our code?

Then the test cannot fail for a reason in the repository. The prompt tells the agent to comment on the ticket with what it found, for example that the integration's API rejected the request, and to open no pull request.
