All jobs

Fix Failing GitHub Actions Checks in a Django App

Yes. When your Django CI goes red, an agent reads the failed job's log, reproduces it with manage.py test, fixes the cause and opens a pull request.

Run this on RushIn a Project that has your repository.

What the agent does

The agent starts from the failed run, not from the whole repository. Your server passes GitHub's workflow_run event into the prompt, and the agent runs gh run view <run id> --log-failed to read only the steps that failed. In a Django project like wagtail/bakerydemo, .github/workflows/ci.yml has three jobs: lint-server (make lint-server, which runs ruff format --check, ruff check, curlylint and djhtml --check), lint-client, and test-server. test-server sets DJANGO_SETTINGS_MODULE: bakerydemo.settings.test and runs ./manage.py check, then ./manage.py makemigrations --check --noinput, then ./manage.py test. Which of those failed decides the whole job, so the agent names the step and quotes its error before anything else.

Then it rebuilds the same environment in its sandbox. The workflow installs with uv venv and uv pip install -r requirements/development.txt, which pulls in requirements/base.txt (Django >=6.0,<6.1, Wagtail >=8.0,<8.1); runtime.txt says python-3.12.1. With no DATABASE_URL set, bakerydemo/settings/base.py falls back to SQLite, and settings/test.py switches to a LocMemCache, the MD5 password hasher and an immediate task backend, so the agent exports the same settings module rather than running tests against the development settings and getting a different result.

It reproduces the exact failing command. A failed makemigrations --check means a model changed without a migration, and the fix is a new migration file generated for that app, not a code revert. A failed manage.py test points at a test such as HomePageRenderTest in bakerydemo/base/tests/test_home_page.py, a WagtailPageTestCase that builds the page tree in setUpTestData; the agent runs that test class alone with ./manage.py test bakerydemo.base.tests.test_home_page, reads the traceback into the page models in bakerydemo/base/models.py or the view in bakerydemo/search/views.py, and fixes the code that changed.

It changes a test only when the test is the thing that is wrong, such as an assertion on text a template legitimately changed, and says so in the pull request. Before pushing it reruns the full sequence the job runs, check, makemigrations --check and test, plus make lint-server when the change touches Python or templates, so the pull request does not trade one red step for another.

Start it with one API call

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

{
  "agent": "claude",
  "input": "The GitHub Actions workflow on this branch failed; the workflow_run event is at the end of this prompt. Read the failed job's log with gh run view <run id> --log-failed, name the step that failed and quote its error. Recreate the job's environment from the workflow file: the same Python, the same requirements file and the same DJANGO_SETTINGS_MODULE. Reproduce the failure with the same command the step runs (python manage.py check, makemigrations --check or python manage.py test), fix the cause in the code (add a migration if one is missing; change a test only if the test is wrong, and say so), then rerun every command in that job until they pass. Open a pull request against the failing branch that quotes the error it fixed.\n\nEvent: <workflow_run payload>",
  "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

A pull request against the branch that went red, with the smallest change that makes the failing step pass: a code fix in the model, view or template the traceback named, or a new file under the app's migrations/ when makemigrations --check was the step. The description quotes the failing line from the GitHub log, names the job and step, and lists the commands the agent reran with their result. The workflow runs again on the pull request, so its checks are the proof on GitHub, and the session's trajectory holds the same commands with their full output from the sandbox.

If the failure was not in the code, such as a runner image change, a network timeout fetching a package, or a flaky test that passes on rerun, the agent does not force a change. Its answer says what it saw and why it made no pull request, and that answer reaches your webhook with the run.

A reviewer checks that the fix addresses the error the log shows, that any edited test was genuinely wrong (the pull request has to say why), and that a generated migration matches the model change the author intended rather than one the agent guessed at.

Run it on every failed workflow run

Subscribe a repository or organization webhook to the workflow_run event and, when action is completed and conclusion is failure, have your server send this request with the event in input. Point resources at the failing branch with https://github.com/<owner>/<repo>/tree/<head_branch>, so the sandbox clones exactly what failed. Skip runs on your default branch if you want a person on those, and skip branches the agent itself opened, so a fix that fails does not start a loop.

Store the workflow_run.id with the execution_id Rush returns, and ignore a redelivery of the same id. Rush POSTs run.completed or run.failed to the webhook URL on your API key when each run finishes, with the answer and the session URL, which your server can post back as a comment on the original pull request.

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

Why run it on Rush?

Fixing a red build on a laptop means stashing what you were doing, checking out the branch, matching the Python and requirements CI used, and rerunning until the error appears. The agent does that in its own sandbox with its own clone and virtualenv, so your working tree and your local database stay as they were, and it starts within moments of the failure rather than when someone notices the red mark.

The fix comes with its proof. The trajectory keeps the GitHub log it read and every manage.py command it ran with the output, and the pull request's own checks run the same workflow again. When several branches fail at once, after a dependency bump for example, each failure gets its own run in parallel, and a reviewer approves each pull request.

Frequently asked questions

Will it just delete or skip the failing test?

No. The prompt tells it to fix the code and to change a test only when the test is wrong, and to say so in the pull request when it does. A reviewer can see any test change in the diff and reject it.

Our tests run against Postgres in CI, not SQLite. Does that work?

Yes. It reads the workflow's services and DATABASE_URL and starts the same database in its sandbox, because a test that passes on SQLite and fails on Postgres would otherwise look fixed. bakerydemo's test-server job uses SQLite, so there it does the same.

What if the failing step is the linter?

It runs the same lint command the job runs, such as make lint-server, and fixes what it reports, usually formatting or an unused import. It uses the versions of ruff and the other tools from your requirements file, not newer ones that would flag different things.

Does it push to my branch directly?

No. It opens a pull request against the failing branch, so the branch's author sees the fix and merges it into their own work. Nothing lands until a person merges.