---
title: Vitest Integration with Mergify
description: Report your test results from Vitest to Mergify
---

<IntegrationLogo src={vitestLogo} alt="Vitest logo" />

This guide explains how to integrate [Vitest](https://vitest.dev/) with Test
Engine using the `@mergifyio/vitest` reporter. Once installed, test results
are automatically uploaded to Test Engine without any extra workflow changes.

## Installation

You need to install the
[`@mergifyio/vitest`](https://www.npmjs.com/package/@mergifyio/vitest) package
to automatically upload your test results to **Test Engine**.

### npm

```bash
npm install --save-dev @mergifyio/vitest
```

### yarn

```bash
yarn add --dev @mergifyio/vitest
```

### pnpm

```bash
pnpm add --save-dev @mergifyio/vitest
```

## Configuration

Add the Mergify reporter to your `vitest.config.ts` (or `vite.config.ts`):

```typescript
import { defineConfig } from 'vitest/config';
import MergifyReporter from '@mergifyio/vitest';

export default defineConfig({
  test: {
    reporters: ['default', new MergifyReporter()],
  },
});
```

The `'default'` reporter keeps the standard console output alongside the
Mergify reporter.

## Update Your CI Workflow

<CIInsightsSetupNote />

Your workflow should run your tests as usual while exporting the secret
`MERGIFY_TOKEN` as an environment variable.

### GitHub Actions

Add the following to the GitHub Actions step running your tests:

```yaml
env:
  MERGIFY_TOKEN: ${{ secrets.MERGIFY_TOKEN }}
```

For example:

```yaml
- name: Run Tests 🧪
  env:
    MERGIFY_TOKEN: ${{ secrets.MERGIFY_TOKEN }}
  run: npm test
```

### Buildkite

Set `MERGIFY_TOKEN` in the environment of the agents running your tests.
The step itself then needs no Mergify-specific configuration:

```yaml
steps:
  - label: "Run Tests 🧪"
    command: npm test
```

<BuildkiteTokenNote plugin={false} />

The reporter automatically collects your test results and sends them to Test
Engine.

## Quarantine and Crashed Runs

The reporter applies [quarantine](/test-engine/quarantine) through a test
runner it installs for you. When a quarantined test fails, that runner records
it as passed, so it does not change Vitest's exit code. The exit code of your
test step already accounts for quarantine, so the step needs nothing more:

- Do not add `continue-on-error: true`. The recipes that upload a JUnit report
  with the `mergifyio/gha-mergify-ci` action need it because the action decides
  the job's result after the tests. Here nothing does, so it would let every
  real failure through.

- There is no step `id` to set and no `test_step_outcome` to pass: both belong
  to that action, which this setup does not use.

:::caution
  Vitest does not load that runner in
  [browser mode](https://vitest.dev/guide/browser/), and the reporter does not
  install it when your configuration sets its own `runner` (it logs a warning
  instead). In both cases quarantined tests that fail still fail the run.
:::

A crash cannot pass for a green run either. Quarantine only covers failing
tests. Errors that Vitest reports outside a test result, such as an unhandled
error or a test file that fails to load, still make it exit non-zero and fail
the step, and so does Vitest dying mid-run. The reporter uploads results
when the test run ends, so a process killed outright before then, such as by
the out-of-memory killer, sends nothing to Test Engine.

If the reporter cannot fetch the quarantine list, it quarantines nothing for
that run, and a quarantined test that fails makes the step fail as usual.

## Matrix Runs

The reporter uploads each run's results under your CI job's name. On GitHub
Actions, that name is the job's identifier (`GITHUB_JOB`), which every leg of
a matrix shares. The job name is
[part of a test's identity](/ci-insights/setup/github-actions#configuration-tips)
in Test Engine, so when the legs run the same suite on several Node.js
versions, their results merge into one test.

Set `MERGIFY_TEST_JOB_NAME` on each leg and include the matrix value, so each
leg reports under its own name:

```yaml
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [20, 22, 24]
    steps:
      # ...
      - name: Run Tests 🧪
        env:
          MERGIFY_TOKEN: ${{ secrets.MERGIFY_TOKEN }}
          MERGIFY_TEST_JOB_NAME: test (node ${{ matrix.node-version }})
        run: npm test
```

If you split the suite with Vitest's `--shard`, leave the shard index out of
the name: the shards run different tests, and a test can move to another shard
when tests are added or removed, so a name per shard would split its history.

Setting `MERGIFY_TEST_JOB_NAME` on a job that already reports changes its
name, so its tests start a new history in Test Engine.

## Verify and Review in Test Engine

After pushing these changes, your next CI run reports its Vitest results
automatically.

<ReviewInTestInsights />

## Environment Variables

| Variable | Purpose | Default |
|----------|---------|---------|
| `MERGIFY_TOKEN` | API authentication token | **Required** |
| `MERGIFY_API_URL` | API endpoint location | `https://api.mergify.com` |
| `VITEST_MERGIFY_ENABLE` | Force-enable outside CI | `false` |
| `MERGIFY_CI_DEBUG` | Print spans to console instead of uploading | `false` |
| `MERGIFY_TRACEPARENT` | W3C distributed trace context | Optional |
| `MERGIFY_TEST_JOB_NAME` | Name this job reports under; set one per environment, never per shard | CI job name |

:::tip
  The reporter auto-activates in CI environments (detected via the `CI`
  environment variable). To enable it outside CI, set
  `VITEST_MERGIFY_ENABLE=true`.
:::
