---
title: Scopes with File Patterns
description: Configure merge queue scopes using file patterns to batch pull requests intelligently.
---

Mergify allows you to define scopes using file patterns to intelligently batch pull requests 
based on which parts of your monorepo they modify. This approach is simple to set up and works 
well when your monorepo structure follows clear directory boundaries.

## Defining File Patterns

Define scopes in your `.mergify.yml` configuration file using file patterns:

```yaml
scopes:
  source:
    files:
      python-api:
        include:
          - api/**/*.py
          - libs/shared/**/*.py
      frontend:
        include:
          - web/**/*.js
          - web/**/*.jsx
          - web/**/*.ts
          - web/**/*.tsx
      docs:
        include:
          - docs/**/*.md
          - docs/**/*.mdx

queue_rules:
  - name: default
    batch_size: 5
```

In this example:
- Changes to Python files in `api/` or `libs/shared/` get the `python-api` scope
- Changes to frontend files in `web/` get the `frontend` scope
- Documentation changes get the `docs` scope

:::tip
Mergify will intelligently batch PRs with overlapping scopes together. For example, if PR1 affects
`python-api` and PR2 affects both `python-api` and `frontend`, they'll be batched together since
they share a common scope.
:::

## Setting Up CI with Scopes

To wire scopes into GitHub Actions, follow the
[Monorepo CI GitHub Actions guide](/monorepo-ci/github-actions). It walks through:

- Adding the [`gha-mergify-ci`](https://github.com/Mergifyio/gha-mergify-ci)
  workflow step that reads your file-pattern scopes and exposes them as outputs.

- Conditioning downstream jobs (frontend, backend, docs, etc.) on those scope outputs.

- Waiting on the right set of jobs so required checks always report, even when work is skipped.

That guide already includes complete workflow samples, so you do not need to duplicate the config
here—just reuse the same scopes you declared above.

## The Merge Queue Scope

The `gha-mergify-ci` action automatically provides a special `merge-queue` scope that returns `true`
only when running in a merge queue context (on temporary merge queue branches).

This is useful for:

- **Integration tests** that only need to run before merging
- **End-to-end tests** that are expensive and should only run on final batches
- **Deployment validation** that needs to happen before code reaches the main branch

```yaml
integration-tests:
  if: ${{ needs.scopes.outputs.merge-queue == 'true' }}
  needs: scopes
  runs-on: ubuntu-22.04
  steps:
    - uses: actions/checkout@v5
    - name: Run expensive integration tests
      run: npm run test:integration
```

## Example: Multi-Language Monorepo

Here's a real-world example for a monorepo with Python, JavaScript, and Go services:

```yaml
scopes:
  source:
    files:
      python-api:
        include:
          - services/api/**/*.py
          - libs/python/**/*.py
      user-service:
        include:
          - services/users/**/*.go
      frontend:
        include:
          - apps/web/**/*.{js,jsx,ts,tsx}
      shared-config:
        include:
          - config/**/*
          - docker/**/*

queue_rules:
  - name: default
    batch_size: 8
    batch_max_wait_time: 5 min
```

With this configuration:
- PRs affecting only `frontend` will batch together

- PRs affecting `python-api` will batch together

- PRs affecting `shared-config` will batch with everything (since config affects all
  services)

## Important Behaviors

### Scope Detection is PR-Specific

The `gha-mergify-ci` action only analyzes files changed by the specific pull request, **not** files
from other PRs in the merge queue batch. This ensures:

- Each PR's scopes reflect only its own changes
- Batching decisions remain consistent even as the queue changes
- Tests run for the correct scopes regardless of what else is in the batch

### Path Filtering vs Scopes

GitHub Actions offers path filtering (`on.pull_request.paths`), but it has critical limitations in
merge queue scenarios:

```yaml
# ❌ Don't use path filtering for merge queues
on:
  pull_request:
    paths:
      - 'api/**'
```

**Problems with path filtering:**

- When a job doesn't run, you can't distinguish between "filtered out" and "CI failed to start"

- Required status checks fail if jobs are skipped due to filtering

- In merge queues, you don't want to skip tests on PR2 just because PR1 in the batch modified
  different files

**✅ Use scopes instead:**

- Jobs always run but can conditionally skip work based on scope detection
- Status checks always report (success or skipped)
- Merge queue batching respects scope boundaries
