|
| 1 | +--- |
| 2 | +title: Merge Queue Scopes |
| 3 | +description: Understand how Mergify groups pull requests by scope to build the most effective batches. |
| 4 | +--- |
| 5 | + |
| 6 | +Mergify scopes describe the areas of your codebase that a pull request touches. By attaching scopes |
| 7 | +to pull requests, the merge queue can build smarter batches, reuse the same CI work, and avoid |
| 8 | +mixing unrelated changes. |
| 9 | + |
| 10 | +## Scope-aware batching at a glance |
| 11 | + |
| 12 | +When several pull requests are eligible for the next batch, Mergify compares their scopes and |
| 13 | +prioritizes the combination that shares the most scopes in common. Pull requests that overlap in |
| 14 | +scope are tested together first, while unrelated changes stay in the queue until a compatible batch |
| 15 | +is available or Mergify needs them to fill the requested batch size. |
| 16 | + |
| 17 | +```dot class="graph" |
| 18 | +strict digraph { |
| 19 | + fontname="sans-serif"; |
| 20 | + rankdir="LR"; |
| 21 | + label="Scope-aware Batch Selection"; |
| 22 | + nodesep=0.9; |
| 23 | + ranksep=1.2; |
| 24 | + splines=polyline; |
| 25 | +
|
| 26 | + edge [fontname="sans-serif", color="#374151", arrowhead=none, penwidth=1.2]; |
| 27 | +
|
| 28 | + subgraph cluster_preferred { |
| 29 | + style="rounded"; |
| 30 | + color="#1CB893"; |
| 31 | + label="Preferred batch"; |
| 32 | +
|
| 33 | + PR1 [shape=box, style="rounded,filled", fillcolor="#347D39", fontcolor="white", color="#165B33", margin="0.35,0.22", fontname="sans-serif", label="PR #101\nScopes: frontend, api"]; |
| 34 | + PR2 [shape=box, style="rounded,filled", fillcolor="#347D39", fontcolor="white", color="#165B33", margin="0.35,0.22", fontname="sans-serif", label="PR #214\nScopes: frontend"]; |
| 35 | + PR3 [shape=box, style="rounded,filled", fillcolor="#347D39", fontcolor="white", color="#165B33", margin="0.35,0.22", fontname="sans-serif", label="PR #305\nScopes: api, docs"]; |
| 36 | + } |
| 37 | +
|
| 38 | + PR4 [shape=box, style="rounded,filled", fillcolor="#6B7280", fontcolor="white", color="#4B5563", margin="0.35,0.22", fontname="sans-serif", label="PR #412\nScope: tooling"]; |
| 39 | +
|
| 40 | + frontend [shape=oval, style="filled", fillcolor="#1CB893", fontcolor="#063C2C", color="#0B7A5C", margin="0.3,0.18", fontname="sans-serif", label="frontend"]; |
| 41 | + api [shape=oval, style="filled", fillcolor="#1CB893", fontcolor="#063C2C", color="#0B7A5C", margin="0.3,0.18", fontname="sans-serif", label="api"]; |
| 42 | + docs [shape=oval, style="filled", fillcolor="#1CB893", fontcolor="#063C2C", color="#0B7A5C", margin="0.3,0.18", fontname="sans-serif", label="docs"]; |
| 43 | + tooling [shape=oval, style="filled", fillcolor="#1CB893", fontcolor="#063C2C", color="#0B7A5C", margin="0.3,0.18", fontname="sans-serif", label="tooling"]; |
| 44 | +
|
| 45 | + PR1 -> frontend; |
| 46 | + PR1 -> api; |
| 47 | + PR2 -> frontend; |
| 48 | + PR3 -> api; |
| 49 | + PR3 -> docs; |
| 50 | + PR4 -> tooling; |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +In the example above, the queue selects the three pull requests that share the `frontend` and `api` |
| 55 | +scopes first. The change that only touches the `tooling` scope is kept aside unless Mergify needs it |
| 56 | +later to complete the batch. |
| 57 | + |
| 58 | +## How Mergify builds scope-aware batches |
| 59 | + |
| 60 | +Scope-aware batching follows these steps: |
| 61 | + |
| 62 | +1. **Collect candidates:** Mergify looks at the next pull requests in queue order that pass the |
| 63 | + queue rules and are ready to batch. |
| 64 | + |
| 65 | +2. **Score overlap:** It evaluates how many scopes each candidate shares with the already selected |
| 66 | + pull requests and prefers combinations with the highest overlap. |
| 67 | + |
| 68 | +3. **Fill the batch:** If the required `batch_size` is not reached with strongly overlapping scopes, |
| 69 | + Mergify expands the selection to the best remaining options so the batch can |
| 70 | + still start. |
| 71 | + |
| 72 | +4. **Fallback safely:** When no scope overlap exists, the queue still batches the oldest pull |
| 73 | + requests together to honor throughput, but these situations are the exception rather than the |
| 74 | + rule. |
| 75 | + |
| 76 | +This strategy maximizes CI reuse: tests that run for one pull request are likely valid for the other |
| 77 | +changes in the batch because they touch the same areas of the codebase. |
| 78 | + |
| 79 | +## Scope assignment lifecycle |
| 80 | + |
| 81 | +Scopes can be attached to pull requests automatically or manually: |
| 82 | + |
| 83 | +- **File pattern detection:** Define scopes directly in your configuration so Mergify infers them |
| 84 | + from changed paths once your CI uploads the results via |
| 85 | + [`gha-mergify-ci`](https://github.com/Mergifyio/gha-mergify-ci) or an equivalent integration. |
| 86 | + See [file-pattern scopes](/merge-queue/monorepo/file-patterns) for a |
| 87 | + step-by-step setup. |
| 88 | + |
| 89 | +- **Manual upload:** Use the [`gha-mergify-ci`](https://github.com/Mergifyio/gha-mergify-ci) |
| 90 | + GitHub Action, the REST API, or the `mergify scopes-send` CLI to push scopes computed by your own |
| 91 | + tooling (Nx, Bazel, Turborepo, etc.). Examples are available in the build tool guides under |
| 92 | + [Monorepo integrations](/merge-queue/monorepo). |
| 93 | + |
| 94 | +## Configuration schema |
| 95 | + |
| 96 | +Declare scopes at the top level of your `.mergify.yml` file: |
| 97 | + |
| 98 | +```yaml |
| 99 | +scopes: |
| 100 | + source: |
| 101 | + files: |
| 102 | + frontend: |
| 103 | + includes: |
| 104 | + - apps/web/**/* |
| 105 | + api: |
| 106 | + includes: |
| 107 | + - services/api/**/*.py |
| 108 | + docs: |
| 109 | + includes: |
| 110 | + - docs/**/* |
| 111 | + merge_queue_scope: merge-queue |
| 112 | + |
| 113 | +queue_rules: |
| 114 | + - name: default |
| 115 | + batch_size: 3 |
| 116 | +``` |
| 117 | +
|
| 118 | +### Top-level keys |
| 119 | +
|
| 120 | +- `scopes.source`: selects how scopes are provided. |
| 121 | + - `files`: map scope names to the file patterns that define them. Each entry accepts `includes` |
| 122 | + and optional `excludes` lists. |
| 123 | + |
| 124 | + - `manual`: instructs Mergify to expect scopes from external systems via the API or GitHub |
| 125 | + Action. |
| 126 | + |
| 127 | + - `null`: disables scopes entirely. |
| 128 | + |
| 129 | +- `scopes.merge_queue_scope`: optional name automatically applied to temporary merge queue pull |
| 130 | + requests (defaults to `merge-queue`). Set it to `null` to disable. |
| 131 | + |
| 132 | +### Manual source example |
| 133 | + |
| 134 | +```yaml |
| 135 | +scopes: |
| 136 | + source: |
| 137 | + manual: |
| 138 | +
|
| 139 | +queue_rules: |
| 140 | + - name: default |
| 141 | + batch_size: 5 |
| 142 | +``` |
| 143 | + |
| 144 | +With the configuration above you must push scopes yourself—typically from a CI job that analyses the |
| 145 | +pull request and calls `gha-mergify-ci` with the `scopes-upload` action. This is the recommended |
| 146 | +approach when build systems such as Bazel, Nx, or Turborepo already know which projects are affected. |
| 147 | + |
| 148 | +## Best practices |
| 149 | + |
| 150 | +- Keep scope names stable and small in number so batches stay meaningful. |
| 151 | + |
| 152 | +- Prefer scopes that align with your CI topology—if a test suite covers a specific service or |
| 153 | + package, create a scope with the same boundary. |
| 154 | + |
| 155 | +- Still configure sane `batch_max_wait_time` values: scopes help Mergify pick the right pull |
| 156 | + requests, but you control how long it waits for an ideal batch. |
| 157 | + |
| 158 | +- Monitor merge queue analytics to verify that scope-aware batching increases success rate and |
| 159 | + reduces redundant CI runs; adjust scope definitions when you see batches mixing unrelated changes. |
0 commit comments