Metadata-Version: 2.4
Name: pytest-mergify
Version: 2026.10.7
Requires-Dist: pytest>=6.2.5
Requires-Dist: pluggy>=1.2
Requires-Dist: pytest-timeout>=2.4.0
License-File: LICENSE
License-File: THIRD_PARTY_LICENSES
Summary: Pytest plugin for Mergify
Author-email: Julien Danjou <jd@mergify.com>
License-Expression: LicenseRef-Mergify-Proprietary
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Homepage, https://docs.mergify.com/test-engine/test-frameworks/pytest/
Project-URL: Issues, https://github.com/Mergifyio/mergify-cli/issues

# pytest-mergify

Pytest plugin for [Mergify Test Engine](https://docs.mergify.com/test-engine/).

More information at https://mergify.com

## Features

- **Test tracing** — Sends OpenTelemetry traces for every test to Mergify's API
- **Flaky test detection** — Intelligently reruns tests to detect flakiness with budget constraints
- **Test quarantine** — Quarantines failing tests so they don't block CI
- **Test selection** — Runs first the tests a merge-queue bisection step failed in the step above, and stops as soon as one fails again

## Installation

Install the package alongside `pytest` (>= 6.0.0):

```bash
pip install pytest-mergify
```

The plugin is auto-discovered by pytest — no manual registration required.

## Configuration

Set the `MERGIFY_TOKEN` environment variable with your Mergify API token.

The plugin activates automatically when running in CI (detected via the `CI` environment variable). To enable outside CI, set `MERGIFY_CI_ENABLE=true`.

### Environment Variables

| Variable | Description | Default |
|---|---|---|
| `MERGIFY_TOKEN` | Mergify API authentication token | (required) |
| `MERGIFY_API_URL` | Mergify API endpoint | `https://api.mergify.com` |
| `MERGIFY_CI_ENABLE` | Force-enable outside CI | `false` |
| `MERGIFY_CI_DEBUG` | Print spans to console instead of uploading | `false` |
| `MERGIFY_TRACEPARENT` | W3C distributed trace context | — |
| `MERGIFY_TEST_JOB_NAME` | Mergify test job name | — |
| `MERGIFY_TEST_SELECTION_ENABLE` | Opt this job into test selection (see below) | `false` |

The names these replace, `PYTEST_MERGIFY_ENABLE` and `PYTEST_MERGIFY_DEBUG`,
are deprecated: they still work when the new name is not set, and the plugin
says which one to switch to at the end of the session.

For detailed documentation, see the [official guide](https://docs.mergify.com/test-engine/test-frameworks/pytest/).

### Test selection

When Mergify's merge queue splits a failed batch, each bisection step only
needs to tell whether it is red. The plugin asks Mergify whether the current
run is such a step and, if so, runs first the tests this job failed in the run
the step was split from (Fail First). They run before every other test; if one
of them fails again, the step is red whatever the rest does, so the run stops
there (exit code 1, the remaining tests not run) and the queue can split again
without waiting for the suite. If they all pass, the rest of the suite runs as
usual. No test is ever skipped, so a green step still comes from a full suite.
A test a retry rescued, or a quarantined failure, does not stop the run.

**This is off until you turn it on, per job.** Installing the plugin is not
enough: set `MERGIFY_TEST_SELECTION_ENABLE=true` on the job you want to run
its failures first:

```yaml
      - name: Run tests
        run: pytest
        env:
          MERGIFY_TOKEN: ${{ secrets.MERGIFY_TOKEN }}
          MERGIFY_TEST_SELECTION_ENABLE: "true"
```

A job that does not set it never queries the endpoint and always runs its
suite in its usual order; everything else the plugin does — test tracing,
flaky detection, quarantine — is unaffected either way. Anything that is not a
recognised yes (unset, empty, `false`, or a value the plugin cannot parse)
means no.

Past that there is nothing to configure: the plugin uses the token and job
identity it already has, and Mergify decides. Every other situation — a run
that is not a bisection step, an unreachable API, an answer from a newer
Mergify this plugin does not understand — runs the full suite in its usual
order. It is also enabled per organization on Mergify's side, so a job that
opts in stays inactive until your organization is opted in too.

Under pytest-xdist this works with the `load` (the default with `-n`) and
`worksteal` schedulers; with `loadgroup`, tests marked `xdist_group` still run
before them. With `loadscope` and `loadfile`, xdist
schedules whole modules or classes by size, so those tests do not run first:
the run still stops once they have all run and one failed again. Workers on a
remote gateway (`--tx ssh=…`) run to the end.

An opted-in job also tells Mergify what it concluded when its session ends —
which tests failed, how many ran — in one small request sent before the test
results are uploaded. That is what the next bisection step of the job is
answered from, seconds after this one finished, without waiting for the
results to be processed. If that request fails, the run's own result is
untouched: the terminal says so, and the next step simply runs its full suite
in its usual order.

## Development

### Prerequisites

- Python >= 3.10
- [uv](https://docs.astral.sh/uv/)

### Setup

```bash
uv sync
```

### Running Tests

```bash
uv run poe test
```

`uv run poe build` builds the wheel into `dist/`; when one is there,
`poe test` runs against it rather than the project's own install, which is
how CI builds the extension once for every Python version. Every uv-driven
build of the extension uses Cargo's dev profile.

### Linting

```bash
uv run poe lint
```

## License

Proprietary. Use is governed by the
[Mergify Terms of Service](https://mergify.com/tos).

