Skip to content

Commit edfbece

Browse files
authored
Merge of #9467
2 parents 4b8e3a4 + e415706 commit edfbece

File tree

4 files changed

+173
-6
lines changed

4 files changed

+173
-6
lines changed

src/content/docs/merge-queue.mdx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,18 @@ quickly consume significant compute resources and budget.
110110
**The Solution:** A merge queue enables several cost-saving strategies:
111111

112112
- **[Batch merging](/merge-queue/batches)**: Combine multiple PRs into a single
113-
batch and test them together. Instead of running CI separately for 5 PRs, run
114-
it once for all 5 together, drastically reducing CI usage.
113+
batch and test them together. Instead of running CI separately for 5 PRs, run
114+
it once for all 5 together, drastically reducing CI usage.
115+
116+
- **[Scope-aware batching](/merge-queue/scopes)**: Attach scopes to pull
117+
requests so Mergify groups related changes together. Shared test runs can be
118+
reused, making batching safer and more efficient—especially in monorepos.
115119

116120
- **[Two-step CI](/merge-queue/two-step)**: Move expensive tests (like E2E
117-
tests) to run only in the merge queue instead of on every PR update. Since
118-
PRs often get updated multiple times before merging—or may never merge at
119-
all—this can dramatically reduce CI costs while actually improving reliability
120-
by ensuring those critical tests run against the real merge state.
121+
tests) to run only in the merge queue instead of on every PR update. Since
122+
PRs often get updated multiple times before merging—or may never merge at
123+
all—this can dramatically reduce CI costs while actually improving reliability
124+
by ensuring those critical tests run against the real merge state.
121125

122126
With these strategies, you can significantly reduce CI costs compared to running
123127
all tests on every PR update, while simultaneously gaining better reliability

src/content/docs/merge-queue/monorepo.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ every change wastes time and CI resources. Mergify's **scopes** feature allows y
88
batch pull requests based on which parts of your codebase they modify, dramatically improving merge
99
queue efficiency.
1010

11+
For a deep dive into how scopes influence batching, see [Merge Queue Scopes](/merge-queue/scopes).
12+
1113
## Understanding Scopes
1214

1315
Scopes define discrete areas of your monorepo (like packages, services, or components). When a pull
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
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.

src/content/navItems.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
FaBug,
1919
FaCircleXmark,
2020
FaGear,
21+
FaLayerGroup,
2122
FaMoneyBill1,
2223
FaRegCircleCheck,
2324
FaRegCirclePause,
@@ -143,6 +144,7 @@ const navItems: NavItem[] = [
143144
{ title: 'Performance', path: '/merge-queue/performance', icon: SlSpeedometer },
144145
{ title: 'Parallel Checks', path: '/merge-queue/parallel-checks', icon: TiFlowParallel },
145146
{ title: 'Batches', path: '/merge-queue/batches', icon: TbPackages },
147+
{ title: 'Scopes', path: '/merge-queue/scopes', icon: FaLayerGroup },
146148
{ title: 'Two-Step CI', path: '/merge-queue/two-step', icon: FaStairs },
147149
{
148150
title: 'Monorepo',

0 commit comments

Comments
 (0)