Scopes with File Patterns
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
Section titled Defining File PatternsDefine scopes in your .mergify.yml configuration file using file patterns:
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: 5In this example:
- Changes to Python files in
api/orlibs/shared/get thepython-apiscope - Changes to frontend files in
web/get thefrontendscope - Documentation changes get the
docsscope
How Mergify Evaluates File-Pattern Scopes
Section titled How Mergify Evaluates File-Pattern ScopesMergify evaluates file-pattern scopes itself. For each pull request, it matches the changed files
against your include (and optional exclude) patterns and tags the pull request with the scopes
it touches. This happens in the merge queue automatically, with no CI job or GitHub Action to set
up: declare the patterns above and the queue batches by scope.
Conditioning CI Jobs on Scopes (Optional)
Section titled Conditioning CI Jobs on Scopes (Optional)The same scopes can also drive your CI, letting you skip jobs whose scope a pull request doesn’t touch. This is optional and independent of merge queue batching. To wire it up, follow the Monorepo CI GitHub Actions guide. It walks through:
-
Adding the
gha-mergify-ciworkflow 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
Section titled The Merge Queue ScopeThe 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
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:integrationExample: Multi-Language Monorepo
Section titled Example: Multi-Language MonorepoHere’s a real-world example for a monorepo with Python, JavaScript, and Go services:
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 minWith this configuration:
-
PRs affecting only
frontendwill batch together -
PRs affecting
python-apiwill batch together -
PRs affecting
shared-configwill batch with everything (since config affects all services)
Important Behaviors
Section titled Important BehaviorsScope Detection is PR-Specific
Section titled Scope Detection is PR-SpecificMergify evaluates the 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
Section titled Path Filtering vs ScopesGitHub Actions offers path filtering (on.pull_request.paths), but it has critical limitations in
merge queue scenarios:
# ❌ Don't use path filtering for merge queueson: 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
Was this page helpful?
Thanks for your feedback!