# Fix Ansible Errors from Sentry Alerts

Yes. An agent reads the Sentry event from the service that runs your Ansible role, reproduces the failing task with Molecule, fixes it and opens a pull request.

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

## What the agent does

Ansible itself does not report to Sentry; the service that runs your playbooks does. A deployment service or a runner written in Python with the Sentry SDK captures the exception when a play fails, and the event carries the failed task's name, the host, the module's `msg` and, when the service attaches them, the host facts such as `ansible_facts.distribution` and `distribution_release`. The agent reads that payload after the prompt, opens the issue and its latest event through the Sentry connection, and keeps three facts as the test's target: the task name, the distribution and release, and the module message.

Then it reads the role. In a role shaped like geerlingguy/ansible-role-docker, `tasks/main.yml` loads `vars/<distribution>.yml` or `vars/<os_family>.yml` with `first_found`, includes `tasks/setup-Debian.yml`, `setup-RedHat.yml` or `setup-Suse.yml` by `os_family`, installs `docker_packages` with `allow_downgrade` on Ansible 2.12 and later, writes `/etc/docker/daemon.json` from `docker_daemon_options`, starts the service, and then handles the Compose binary in `tasks/docker-compose.yml` and the `docker` group in `tasks/docker-users.yml`. `tasks/setup-Debian.yml` is where most distribution-specific failures land: it removes legacy sources, installs `ca-certificates` and `python3-debian`, and adds the repository with `ansible.builtin.deb822_repository` using `docker_apt_repo_url`, built from `docker_apt_ansible_distribution`, and `suites: "{{ ansible_facts.distribution_release }}"`. `defaults/main.yml` maps Pop!_OS and Linux Mint to `ubuntu` for the repository, but the release codename still comes from the facts, so a derivative whose codename Docker does not publish fails at that task with an apt error, which is the kind of message an alert carries. `meta/main.yml` lists the supported platforms and `min_ansible_version: 2.15.1`.

Reproduction runs through Molecule, the role's own harness. `molecule/default/molecule.yml` uses the Docker driver with `geerlingguy/docker-${MOLECULE_DISTRO:-rockylinux9}-ansible:latest`, privileged with the host cgroup namespace; `converge.yml` updates the apt cache on Debian, waits for systemd, and applies the role; `verify.yml` checks `docker version`, `systemctl is-active docker` and a `docker pull hello-world`. The agent sets `MOLECULE_DISTRO` to the image that matches the alert's distribution from the seven `ci.yml` uses, or the closest base when the derivative has no image, and adds the facts the failure depends on as `converge.yml` vars or a dedicated scenario directory under `molecule/`. It runs `molecule converge` and confirms the same task fails with the same module message before touching the role.

The fix stays inside the task or the variable that produced the failure: a `vars/` file for a distribution, a new default such as a release override that `tasks/setup-Debian.yml` reads instead of the raw fact, or a `when` guard, and never an `ignore_errors` that would hide the task. A new variable gets its line in `defaults/main.yml` and its paragraph in `README.md`. Then `molecule test` runs the whole sequence, including the second converge that proves idempotence and the verify playbook, and `yamllint .` and `ansible-lint` run as `ci.yml` and `.ansible-lint` define them. The pull request quotes the failing converge, the passing `molecule test` and the distros it ran on.

## Start it with one API call

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

```json
{
  "agent": "claude",
  "input": "A Sentry alert fired from the service that runs this Ansible role; its payload follows this prompt. Use the Sentry connection to read the issue and its latest event: the failed task name, the host, the module message, and the distribution and release facts if the event carries them. Read meta/main.yml, defaults/main.yml, tasks/main.yml, the setup file for that OS family under tasks/, the matching file under vars/, and the Molecule scenario under molecule/default. Reproduce the failure with Molecule: set MOLECULE_DISTRO to the image that matches the alert's distribution, add any facts or variables the failure depends on to the converge playbook or a new scenario, run molecule converge, and confirm the same task fails with the same message. Fix the cause in that task or variable without ignore_errors, document a new variable in defaults/main.yml and README.md, and run molecule test, yamllint and ansible-lint. Open a pull request that links the Sentry issue, quotes the task failure and the passing Molecule output with the distributions it ran on, and explains the cause. If it does not reproduce, stop and report what you tried.\n\nAlert payload:\n{payload}",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ],
  "connections": [
    "sentry"
  ]
}
```

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 that changes one task file or variable file, adds the Molecule scenario or converge vars that reproduce the failure, and, when a variable was introduced, a line in `defaults/main.yml` and a paragraph in `README.md`. Its description links the Sentry issue, quotes the failed task and its module message as the alert carried them, shows `molecule converge` failing on the matching distro before the change and `molecule test` passing after, with the idempotence pass and the verify output, and the `yamllint` and `ansible-lint` results.

Before merging, a reviewer checks that the distro Molecule converged is the one in the alert, or that the description names the gap when a derivative had no image; that the fix is a guard or a variable rather than a swallowed error; and that the second converge changed nothing. The transcript on the session keeps every Molecule step, so the failing converge can be read next to the passing one.

## Run it on every Sentry issue alert

Create an alert rule in the Sentry project your deployment service reports to, with a webhook action pointed at a handler on your server. Sentry signs its own requests and cannot add the `Authorization: Bearer` header a Rush `webhook` trigger requires, so the handler receives the alert, places its JSON after the prompt and sends this request with the Sentry issue id as `Idempotency-Key`, which makes a redelivery return the run already started.

Set a `webhook_url` on the API key and Rush POSTs `run.completed` with the `session_url` when the turn ends; the handler reads the pull request link and posts it on the issue. A play that fails on many hosts of one distribution produces one Sentry issue, so one issue is one run, and the handler can skip an issue that already has an open pull request.

## Why run it on Rush?

Reproducing a role failure means a privileged container for the right distribution, a full converge, and often a second converge to check idempotence; on a laptop that is slow, needs a working Docker-in-Docker setup, and leaves containers behind. The sandbox runs Molecule's whole sequence for the distro in the alert and keeps every step's output on the session.

The pull request carries its own proof: the task failure quoted from the alert, the same failure from `molecule converge` on the matching image, and the green `molecule test` after the change. Several alerts for several distributions run in several sandboxes at once, and a reviewer judges a small diff with the evidence attached.

## Frequently asked questions

### How does an Ansible role end up in Sentry?

Through whatever runs it. A Python deployment service, a scheduler or a runner that wraps `ansible-playbook` and has the Sentry SDK installed captures the failure and attaches the task name, host and module message. The role itself has no Sentry dependency, and the pull request adds none.

### What if the alert's distribution has no Molecule image?

The agent converges on the nearest base image from the `ci.yml` matrix, such as `ubuntu2404` for an Ubuntu derivative, sets the facts the failure depends on as converge vars, and says in the pull request which image stood in and why. If the failure cannot be reproduced that way, it stops and reports what it tried.

### Will it add ignore_errors or failed_when: false to make the play pass?

No. The prompt forbids it, and such a change would hide the alert rather than fix its cause. The fix is a guard, a variable or a corrected task; `changed_when: false` on a read-only `command` task is fine, since the role already uses it in `tasks/docker-compose.yml`.

### Does it run every distro in the CI matrix?

It runs the one in the alert, and names it. A change to `tasks/main.yml` or `defaults/main.yml` can affect every platform in `meta/main.yml`, so a reviewer who wants the full seven-way matrix converged says so in the prompt, and the pull request lists each result.
