From 2a76c632926e9fc13897f449e7aab675204a756f Mon Sep 17 00:00:00 2001 From: Mehdi ABAAKOUK Date: Fri, 29 May 2026 20:01:11 +0200 Subject: [PATCH] docs(merge-queue): reorganize section into grouped navigation Flatten the 19-item Merge Queue sidebar into 3 top-level entries (Overview, Setup, Queue Modes) plus 5 collapsible groups: Concepts, Configure, Scale & Tune, Integrations & Setup, and Operate. Rename the Parallel Scopes page to Queue Modes and reframe it as the single home for the serial / parallel / isolated modes, which were previously scattered. Add a redirect from the old URL and update inbound links. Pause moves to Operate (it is an action, not configuration). Change-Id: I4d5451984dea184e07a9f916744da6feea34bded --- public/_redirects | 2 + .../docs/merge-queue/merge-strategies.mdx | 4 +- .../migrate-partitions-to-scopes.mdx | 2 +- src/content/docs/merge-queue/monorepo.mdx | 2 +- .../{parallel-scopes.mdx => queue-modes.mdx} | 189 ++-- src/content/navItems.tsx | 852 +++++++++--------- 6 files changed, 545 insertions(+), 506 deletions(-) rename src/content/docs/merge-queue/{parallel-scopes.mdx => queue-modes.mdx} (69%) diff --git a/public/_redirects b/public/_redirects index 0353baa38c..f258231e99 100644 --- a/public/_redirects +++ b/public/_redirects @@ -74,4 +74,6 @@ /ci-insights/test-frameworks/* /test-insights/test-frameworks/:splat 301 /ci-insights/quarantine /test-insights/quarantine 301 /ci-insights/quarantine/ /test-insights/quarantine 301 +/merge-queue/parallel-scopes /merge-queue/queue-modes 301 +/merge-queue/parallel-scopes/ /merge-queue/queue-modes 301 diff --git a/src/content/docs/merge-queue/merge-strategies.mdx b/src/content/docs/merge-queue/merge-strategies.mdx index bb86fc2f9a..982ed302b5 100644 --- a/src/content/docs/merge-queue/merge-strategies.mdx +++ b/src/content/docs/merge-queue/merge-strategies.mdx @@ -205,7 +205,7 @@ commits** from folding each PR into the batch branch. - **`commit_message_format` has no effect** — fast-forward preserves the original commits, so custom commit messages are not applicable -- **[Parallel mode](/merge-queue/parallel-scopes) is not supported** — fast-forward +- **[Parallel mode](/merge-queue/queue-modes) is not supported** — fast-forward is not compatible with scope-based parallel queues - **Use case:** teams and OSS projects that care about commit identity and want @@ -297,7 +297,7 @@ were included in the batch (e.g., "Merge queue: merged #42, #43, #44"). - **Requires `batch_size > 1`** — this method is designed for batch merging and cannot be used with single PRs -- **Not compatible with [partition rules](/merge-queue/parallel-scopes)** +- **Not compatible with [partition rules](/merge-queue/queue-modes)** - **Use case:** teams that use batch merging and want a single merge commit per batch on the base branch, triggering only one deployment per batch diff --git a/src/content/docs/merge-queue/migrate-partitions-to-scopes.mdx b/src/content/docs/merge-queue/migrate-partitions-to-scopes.mdx index 43f4259fd9..fa3efa3f73 100644 --- a/src/content/docs/merge-queue/migrate-partitions-to-scopes.mdx +++ b/src/content/docs/merge-queue/migrate-partitions-to-scopes.mdx @@ -206,7 +206,7 @@ In parallel mode, PRs touching different scopes are tested and merged simultaneously — just like partition lanes, but with smarter dependency tracking when scopes overlap. -See [Parallel Scopes](/merge-queue/parallel-scopes) for details. +See [Queue Modes](/merge-queue/queue-modes) for details. ## Using a Build Tool Instead of File Patterns diff --git a/src/content/docs/merge-queue/monorepo.mdx b/src/content/docs/merge-queue/monorepo.mdx index 9e175e8563..c5baab37c7 100644 --- a/src/content/docs/merge-queue/monorepo.mdx +++ b/src/content/docs/merge-queue/monorepo.mdx @@ -75,7 +75,7 @@ of how you compute them. - [Scopes reference](/merge-queue/scopes): schema, file-pattern setup, and tooling guides (Nx, Bazel, Turborepo, custom uploaders). -- [Parallel Scopes](/merge-queue/parallel-scopes): once scopes are configured, enable parallel scopes to +- [Queue Modes](/merge-queue/queue-modes): once scopes are configured, enable parallel mode to test and merge pull requests that touch different scopes simultaneously — significantly reducing merge times in monorepos. diff --git a/src/content/docs/merge-queue/parallel-scopes.mdx b/src/content/docs/merge-queue/queue-modes.mdx similarity index 69% rename from src/content/docs/merge-queue/parallel-scopes.mdx rename to src/content/docs/merge-queue/queue-modes.mdx index 2b7403eedc..ae7f28cca7 100644 --- a/src/content/docs/merge-queue/parallel-scopes.mdx +++ b/src/content/docs/merge-queue/queue-modes.mdx @@ -1,32 +1,38 @@ --- -title: Parallel Scopes -description: Run independent pull requests through the merge queue simultaneously to merge faster in monorepos. +title: Queue Modes +description: Choose how the merge queue schedules pull requests — serial, parallel, or isolated. --- -By default, Mergify's merge queue operates in **serial mode**: every pull request is tested on top -of the previous one, forming a single ordered pipeline. This guarantees correctness but means -unrelated changes wait for each other. +The `merge_queue.mode` option controls how the merge queue schedules pull requests. There are three +modes: -**Parallel mode** removes that constraint. When two pull requests touch different areas of the -codebase — different **scopes** — Mergify tests and merges them independently, at the same time. Pull -requests that do share a scope are still queued together so they are tested as a group, preventing -semantic conflicts. +- **`serial`** (default) — every pull request is tested on top of the previous one, in a single + ordered pipeline. +- **`parallel`** — pull requests that touch different [scopes](/merge-queue/scopes) are tested and + merged at the same time. +- **`isolated`** — every batch runs as a fully independent unit, with no dependency on any other + batch. -:::tip - Parallel mode is designed for monorepos and large repositories where pull requests frequently - change independent parts of the codebase. If most of your pull requests touch the same files, - serial mode with [batching](/merge-queue/batches) may be a better fit. -::: +All three honor your [queue rules](/merge-queue/rules) and [batch sizing](/merge-queue/batches). +They differ only in **how batches depend on each other**. + +## Choosing a mode -**Isolated mode** goes one step further. Every batch runs as a fully independent unit with no -dependency on any other batch — even when their changes overlap. Scopes become optional: when set, -Mergify groups similar pull requests into the same batch; when omitted, it batches by priority and -arrival order. See [Isolated Mode](#isolated-mode) below. +| Mode | Batches depend on each other? | Requires scopes? | Best for | +|------|-------------------------------|------------------|----------| +| `serial` | Yes — each batch builds on the previous one | No | Most repositories; pull requests that often touch the same code | +| `parallel` | Only when their scopes overlap | Yes | Monorepos where pull requests usually touch independent areas | +| `isolated` | Never | No | Independent pull requests where you want maximum throughput | -## Serial, Parallel, and Isolated at a Glance +The rest of this page describes each mode in turn. Serial is the default, so if you do nothing you +are already using it. -In **serial mode**, every batch depends on the one before it. Even if PR #3 (docs) has nothing in -common with PR #1 (api) or PR #2 (frontend), it still waits: +## Serial Mode + +Serial mode is the **default** — you don't need to configure anything to use it. Every pull request +is tested on top of the one before it, forming a single ordered pipeline. This guarantees +correctness: each pull request is validated against the exact state it will merge into. The +trade-off is that unrelated changes still wait for each other. ```dot class="graph" strict digraph { @@ -47,8 +53,34 @@ strict digraph { } ``` -In **parallel mode**, Mergify groups pull requests by scope. Batches that share no scope run at the -same time: +Even though PR #3 (docs) has nothing in common with PR #1 (api) or PR #2 (frontend), it still waits +behind them. + +You can set it explicitly, though it is the default: + +```yaml +merge_queue: + mode: serial +``` + +Serial mode still uses [batches](/merge-queue/batches) and +[parallel checks](/merge-queue/parallel-checks) to increase throughput without giving up cumulative +testing. If most of your pull requests touch the same files, serial mode is usually the right +choice. + +## Parallel Mode + +Parallel mode tests and merges pull requests that touch different areas of the codebase — different +[scopes](/merge-queue/scopes) — at the same time. Pull requests that share a scope are still queued +together so they are tested as a group, preventing semantic conflicts. + +:::tip + Parallel mode is designed for monorepos and large repositories where pull requests frequently + change independent parts of the codebase. If most of your pull requests touch the same files, + serial mode may be a better fit. +::: + +Batches that share no scope run at the same time: ```dot class="graph" strict digraph { @@ -104,43 +136,12 @@ strict digraph { Here PR #4 touches the `api` scope, just like PR #1 — so it must wait for PR #1 to merge first. Meanwhile PR #3 (docs) proceeds independently. -In **isolated mode**, there are no dependencies at all. Every batch runs on its own, even when two -batches touch the same code, so an overlap like the one above never creates a wait: - -```dot class="graph" -strict digraph { - fontname="sans-serif"; - rankdir="TB"; - label="Isolated Mode\nEvery Batch Independent"; - nodesep=0.8; - ranksep=0.6; - - node [shape=box, style="rounded,filled", fontcolor="white", fontname="sans-serif", margin="0.3,0.18"]; - edge [style=invis]; - - subgraph cluster_running { - style="rounded,filled"; - fillcolor="#1CB893"; - color="#1CB893"; - fontcolor="#000000"; - label="Tested simultaneously"; - - PR1 [label="Batch 1\nPR #1", fillcolor="#347D39"]; - PR2 [label="Batch 2\nPR #2", fillcolor="#347D39"]; - PR3 [label="Batch 3\nPR #3", fillcolor="#347D39"]; - } - - { rank=same; PR1; PR2; PR3; } -} -``` - -## Setting Up Parallel Mode +### Set up parallel mode -Parallel mode requires two things: switching the queue mode and configuring -[scopes](/merge-queue/scopes) so Mergify knows which areas of the codebase each pull request -touches. +Parallel mode requires two things: configuring [scopes](/merge-queue/scopes) so Mergify knows which +areas of the codebase each pull request touches, and switching the mode. -### 1. Define scopes +#### 1. Define scopes Scopes can come from file patterns declared directly in `.mergify.yml`, or from an external build system (Nx, Bazel, Turborepo, …) via the @@ -163,7 +164,7 @@ scopes: See [Scopes](/merge-queue/scopes) for all configuration options and build-tool integrations. -### 2. Enable parallel mode +#### 2. Enable parallel mode Add `mode: parallel` under `merge_queue`: @@ -195,7 +196,7 @@ queue_rules: The `max_parallel_checks` setting controls how many batches Mergify tests at the same time across all scope queues. Tune it to match your CI capacity. -## How It Works +### How parallel mode works Once parallel mode is active, the merge queue follows these steps whenever it processes pull requests: @@ -216,16 +217,12 @@ requests: 5. **Merge.** As soon as a batch's CI passes and all its parent batches are merged, Mergify merges the pull requests in that batch. -### What happens when a batch fails? - -The failure handling works the same way as in serial mode: Mergify splits the failed batch and -retests the parts to isolate the problematic pull request. See -[Handling Batch Failures](/merge-queue/batches#handling-batch-failure-or-timeout) for details. - -Because batches in parallel mode are scoped, a failure in one scope queue does **not** block -unrelated scope queues. Only batches that depend on the failed one (via shared scopes) are affected. +When a batch fails, Mergify splits it and retests the parts to isolate the problematic pull request +(see [Handling Batch Failures](/merge-queue/batches#handling-batch-failure-or-timeout)). Because +batches are scoped, a failure in one scope queue does **not** block unrelated scope queues — only +batches that depend on the failed one (via a shared scope) are affected. -## The Monorepo Trade-Off +### The monorepo trade-off Parallel mode is built for the reality of monorepos: most pull requests are independent, but some do interact. @@ -246,6 +243,33 @@ Parallel mode keeps dependencies between batches that share a scope. **Isolated entirely: every batch is a self-contained unit that is tested and merged on its own, with no parent batch and no child batch. A failure in one batch never blocks any other. +```dot class="graph" +strict digraph { + fontname="sans-serif"; + rankdir="TB"; + label="Isolated Mode\nEvery Batch Independent"; + nodesep=0.8; + ranksep=0.6; + + node [shape=box, style="rounded,filled", fontcolor="white", fontname="sans-serif", margin="0.3,0.18"]; + edge [style=invis]; + + subgraph cluster_running { + style="rounded,filled"; + fillcolor="#1CB893"; + color="#1CB893"; + fontcolor="#000000"; + label="Tested simultaneously"; + + PR1 [label="Batch 1\nPR #1", fillcolor="#347D39"]; + PR2 [label="Batch 2\nPR #2", fillcolor="#347D39"]; + PR3 [label="Batch 3\nPR #3", fillcolor="#347D39"]; + } + + { rank=same; PR1; PR2; PR3; } +} +``` + Use isolated mode when your pull requests are genuinely independent and you want maximum throughput without maintaining a scope map — for example when each pull request targets its own service or package and you don't need Mergify to serialize overlapping changes. @@ -266,10 +290,9 @@ queue_rules: - check-success = ci ``` -### How batches form +### How isolated batches form -How Mergify fills a batch depends on whether you configure -[scopes](/merge-queue/scopes): +How Mergify fills a batch depends on whether you configure [scopes](/merge-queue/scopes): - **With scopes.** Mergify groups the most similar pull requests — those sharing the most scopes — into the same batch, using the same [scope-aware batching](/merge-queue/scopes) as the other @@ -277,22 +300,10 @@ How Mergify fills a batch depends on whether you configure - **Without scopes.** Mergify fills batches by queue priority and arrival order, up to `batch_size`. -Either way, the batches that result are fully independent. They run concurrently up to +Either way, the resulting batches are fully independent. They run concurrently up to `max_parallel_checks`, and Mergify merges each one as soon as its own CI passes — there is never a -parent batch to wait for. - -### Isolated vs. parallel - -| | Parallel mode | Isolated mode | -|--|--|--| -| Scopes | Required | Optional | -| Cross-batch dependencies | Yes, when scopes overlap | Never | -| A batch can block another | Yes (shared scope) | No | -| Batch formation | By shared scopes | By shared scopes, or by priority + arrival order when no scopes | - -Batch failure handling is the same as in the other modes: Mergify splits the failed batch and -retests the parts to isolate the culprit. See -[Handling Batch Failures](/merge-queue/batches#handling-batch-failure-or-timeout). +parent batch to wait for. Batch failures are handled the same way as in the other modes (see +[Handling Batch Failures](/merge-queue/batches#handling-batch-failure-or-timeout)). ## Compatibility and Limitations @@ -300,8 +311,8 @@ Parallel and isolated modes change how the queue operates. Some features that re single-queue ordering are not available: - **Scopes are required in parallel mode.** You must configure `scopes.source` (either `files` or - `manual`) so Mergify can tell which pull requests are independent. Isolated mode does not require - scopes — see [Isolated Mode](#isolated-mode). + `manual`) so Mergify can tell which pull requests are independent. Serial and isolated modes do + not require scopes. - **`fast-forward` merge is not supported.** Because batches merge independently, Mergify needs to rebase them. Use `merge` or `rebase` as your `merge_method`. diff --git a/src/content/navItems.tsx b/src/content/navItems.tsx index df28cb8115..ed1b59152e 100644 --- a/src/content/navItems.tsx +++ b/src/content/navItems.tsx @@ -1,426 +1,452 @@ import { v5 } from 'uuid'; export type NavItem = { - title: string; - path?: string; - children?: NavItem[]; - id?: string; - icon?: string; + title: string; + path?: string; + children?: NavItem[]; + id?: string; + icon?: string; }; const navItems: NavItem[] = [ - { title: 'Home', path: '/', icon: 'lucide:house' }, - { - title: 'Merge Queue', - icon: 'mergify:merge-queue', - path: '/merge-queue', - children: [ - { title: 'Overview', path: '/merge-queue', icon: 'lucide:lightbulb' }, - { title: 'Setup', path: '/merge-queue/setup', icon: 'lucide:settings' }, - { title: 'Queue Rules', path: '/merge-queue/rules', icon: 'lucide:layers' }, - { - title: 'Merge Strategies', - path: '/merge-queue/merge-strategies', - icon: 'octicon:git-merge-16', - }, - { title: 'Lifecycle', path: '/merge-queue/lifecycle', icon: 'lucide:refresh-cw' }, - { title: 'Priority', path: '/merge-queue/priority', icon: 'lucide:traffic-cone' }, - { title: 'Pause', path: '/merge-queue/pause', icon: 'lucide:circle-pause' }, - { title: 'Performance', path: '/merge-queue/performance', icon: 'lucide:gauge' }, - { - title: 'Parallel Checks', - path: '/merge-queue/parallel-checks', - icon: 'lucide:split', - }, - { title: 'Batches', path: '/merge-queue/batches', icon: 'lucide:boxes' }, - { title: 'Stacked PRs', path: '/merge-queue/stacks', icon: 'lucide:layers' }, - { - title: 'Scopes', - path: '/merge-queue/scopes', - icon: 'lucide:network', - children: [ - { title: 'Overview', path: '/merge-queue/scopes', icon: 'lucide:lightbulb' }, - { - title: 'File Patterns', - path: '/merge-queue/scopes/file-patterns', - icon: 'lucide:file', - }, - { title: 'Nx', path: '/merge-queue/scopes/nx', icon: 'simple-icons:nx' }, - { title: 'Bazel', path: '/merge-queue/scopes/bazel', icon: 'simple-icons:bazel' }, - { - title: 'Turborepo', - path: '/merge-queue/scopes/turborepo', - icon: 'simple-icons:turborepo', - }, - { - title: 'Other Build Tools', - path: '/merge-queue/scopes/others', - icon: 'lucide:settings', - }, - ], - }, - { title: 'Monorepo', path: '/merge-queue/monorepo', icon: 'lucide:boxes' }, - { - title: 'Parallel Scopes', - path: '/merge-queue/parallel-scopes', - icon: 'lucide:git-fork', - }, - { title: 'Two-Step CI', path: '/merge-queue/two-step', icon: 'lucide:arrow-right-left' }, - { title: 'Deployment', path: '/merge-queue/deploy', icon: 'lucide:rocket' }, - { - title: 'GitHub Rulesets Compatibility', - path: '/merge-queue/github-rulesets', - icon: 'simple-icons:github', - }, - { - title: 'Browser Extensions', - path: '/merge-queue/browser-extensions', - icon: 'lucide:puzzle', - }, - { title: 'Monitoring', path: '/merge-queue/monitoring', icon: 'lucide:layout-dashboard' }, - ], - }, - { - title: 'CI Insights', - path: '/ci-insights', - icon: 'mergify:ci-insights', - children: [ - { title: 'Overview', path: '/ci-insights', icon: 'lucide:lightbulb' }, - { title: 'Runners', path: '/ci-insights/runners', icon: 'lucide:server' }, - { title: 'Jobs', path: '/ci-insights/jobs', icon: 'lucide:list-checks' }, - { title: 'Auto-Retry', path: '/ci-insights/auto-retry', icon: 'lucide:rotate-cw' }, - { - title: 'Flaky Test Detection', - path: '/ci-insights/flaky-test-detection', - icon: 'lucide:bug', - }, - { - title: 'CI Setup', - icon: 'lucide:settings', - children: [ - { - title: 'GitHub Actions', - path: '/ci-insights/setup/github-actions', - icon: 'simple-icons:githubactions', - }, - { - title: 'Buildkite', - path: '/ci-insights/setup/buildkite', - icon: 'simple-icons:buildkite', - }, - { title: 'Jenkins', path: '/ci-insights/setup/jenkins', icon: 'simple-icons:jenkins' }, - ], - }, - ], - }, - { - title: 'Test Insights', - path: '/test-insights', - icon: 'mergify:test-insights', - children: [ - { title: 'Overview', path: '/test-insights', icon: 'lucide:lightbulb' }, - { title: 'Prevention', path: '/test-insights/prevention', icon: 'lucide:shield-half' }, - { title: 'Detection', path: '/test-insights/detection', icon: 'lucide:search' }, - { title: 'Mitigation', path: '/test-insights/mitigation', icon: 'lucide:radiation' }, - { title: 'Quarantine', path: '/test-insights/quarantine', icon: 'lucide:radiation' }, - { title: 'CLI', path: '/test-insights/cli', icon: 'lucide:terminal' }, - { - title: 'Test Frameworks Setup', - path: '/test-insights#test-framework-configuration', - icon: 'lucide:flask-conical', - children: [ - { - title: 'Cypress', - path: '/test-insights/test-frameworks/cypress', - icon: 'simple-icons:cypress', - }, - { title: 'Go', path: '/test-insights/test-frameworks/golang', icon: 'simple-icons:go' }, - { title: 'Jest', path: '/test-insights/test-frameworks/jest', icon: 'simple-icons:jest' }, - { - title: 'JUnit', - path: '/test-insights/test-frameworks/junit', - icon: 'simple-icons:junit5', - }, - { - title: 'minitest', - path: '/test-insights/test-frameworks/minitest', - icon: 'simple-icons:ruby', - }, - { - title: 'MSTest', - path: '/test-insights/test-frameworks/mstest', - icon: 'simple-icons:dotnet', - }, - { - title: 'NUnit', - path: '/test-insights/test-frameworks/nunit', - icon: 'simple-icons:dotnet', - }, - { title: 'Pest', path: '/test-insights/test-frameworks/pest', icon: 'simple-icons:php' }, - { - title: 'PHPUnit', - path: '/test-insights/test-frameworks/phpunit', - icon: 'simple-icons:php', - }, - { - title: 'Playwright', - path: '/test-insights/test-frameworks/playwright', - icon: 'simple-icons:playwright', - }, - { - title: 'pytest', - path: '/test-insights/test-frameworks/pytest', - icon: 'simple-icons:pytest', - }, - { - title: 'RSpec', - path: '/test-insights/test-frameworks/rspec', - icon: 'simple-icons:ruby', - }, - { title: 'Rust', path: '/test-insights/test-frameworks/rust', icon: 'simple-icons:rust' }, - { - title: 'TestNG', - path: '/test-insights/test-frameworks/testng', - icon: 'simple-icons:testinglibrary', - }, - { - title: 'Vitest', - path: '/test-insights/test-frameworks/vitest', - icon: 'simple-icons:vitest', - }, - ], - }, - ], - }, - { - title: 'Merge Protections', - path: '/merge-protections', - icon: 'mergify:merge-protections', - children: [ - { title: 'Overview', path: '/merge-protections', icon: 'lucide:lightbulb' }, - { title: 'Setup', path: '/merge-protections/setup', icon: 'lucide:settings' }, - { title: 'Auto-Merge', path: '/merge-protections/auto-merge', icon: 'lucide:zap' }, - { - title: 'Built‑in Protections', - path: '/merge-protections/builtin', - icon: 'lucide:shield-user', - }, - { title: 'Custom Rules', path: '/merge-protections/custom-rules', icon: 'lucide:ruler' }, - { title: 'Freezes', path: '/merge-protections/freeze', icon: 'lucide:snowflake' }, - { title: 'Examples', path: '/merge-protections/examples', icon: 'lucide:lightbulb' }, - ], - }, - { - title: 'Stacks', - path: '/stacks', - icon: 'mergify:stacks', - children: [ - { title: 'Overview', path: '/stacks', icon: 'lucide:lightbulb' }, - { title: 'Concepts', path: '/stacks/concepts', icon: 'lucide:network' }, - { title: 'Setup', path: '/stacks/setup', icon: 'lucide:wrench' }, - { title: 'Creating Stacks', path: '/stacks/creating', icon: 'lucide:layers' }, - { title: 'Updating Stacks', path: '/stacks/updating', icon: 'lucide:square-pen' }, - { title: 'Reviewing Stacks', path: '/stacks/reviewing', icon: 'lucide:search' }, - { title: 'Team Adoption', path: '/stacks/team', icon: 'lucide:users' }, - { - title: 'Compare Tools', - path: '/stacks/compare', - icon: 'lucide:scale', - children: [ - { title: 'Overview', path: '/stacks/compare', icon: 'lucide:lightbulb' }, - { title: 'vs gh-stack', path: '/stacks/compare/gh-stack', icon: 'simple-icons:github' }, - { - title: 'vs Graphite', - path: '/stacks/compare/graphite', - icon: 'simple-icons:graphite', - }, - ], - }, - ], - }, - { - title: 'Workflow Automation', - icon: 'lucide:zap', - path: '/workflow', - children: [ - { title: 'Workflow Automation', path: '/workflow/', icon: 'lucide:zap' }, - { title: 'Rule Syntax', path: '/workflow/rule-syntax', icon: 'lucide:badge-question-mark' }, - { - title: 'Actions', - icon: 'lucide:rocket', - path: '/workflow/actions', - children: [ - { title: 'Assign', path: '/workflow/actions/assign', icon: 'lucide:user-plus' }, - { title: 'Backport', path: '/workflow/actions/backport', icon: 'lucide:git-branch' }, - { title: 'Close', path: '/workflow/actions/close', icon: 'lucide:circle-x' }, - { title: 'Copy', path: '/workflow/actions/copy', icon: 'lucide:share-2' }, - { title: 'Comment', path: '/workflow/actions/comment', icon: 'lucide:list' }, - { - title: 'Delete Head Branch (Deprecated)', - path: '/workflow/actions/delete_head_branch', - icon: 'lucide:scissors', - }, - { - title: 'Dismiss Reviews', - path: '/workflow/actions/dismiss_reviews', - icon: 'lucide:message-square-x', - }, - { title: 'Edit', path: '/workflow/actions/edit', icon: 'lucide:type' }, - { - title: 'GitHub Actions', - path: '/workflow/actions/github_actions', - icon: 'simple-icons:githubactions', - }, - { title: 'Label', path: '/workflow/actions/label', icon: 'lucide:badge-check' }, - { title: 'Merge', path: '/workflow/actions/merge', icon: 'octicon:git-merge-16' }, - { - title: 'Post Check (Deprecated)', - path: '/workflow/actions/post_check', - icon: 'lucide:circle-check', - }, - { title: 'Queue', path: '/workflow/actions/queue', icon: 'mergify:merge-queue' }, - { title: 'Rebase', path: '/workflow/actions/rebase', icon: 'lucide:git-branch' }, - { - title: 'Request Reviews', - path: '/workflow/actions/request_reviews', - icon: 'octicon:code-review-16', - }, - { title: 'Review', path: '/workflow/actions/review', icon: 'lucide:message-square-text' }, - { title: 'Update', path: '/workflow/actions/update', icon: 'lucide:git-branch' }, - { title: 'Squash', path: '/workflow/actions/squash', icon: 'lucide:layers' }, - ], - }, - ], - }, - { - title: 'Monorepo CI', - path: '/monorepo-ci', - icon: 'lucide:network', - children: [ - { title: 'Overview', path: '/monorepo-ci', icon: 'lucide:network' }, - { - title: 'GitHub Actions', - path: '/monorepo-ci/github-actions', - icon: 'simple-icons:githubactions', - }, - { - title: 'Buildkite', - path: '/monorepo-ci/buildkite', - icon: 'simple-icons:buildkite', - }, - ], - }, - { - title: 'Rule Engine', - icon: 'lucide:book', - children: [ - { title: 'Configuration File', path: '/configuration/file-format', icon: 'lucide:file' }, - { - title: 'Conditions', - path: '/configuration/conditions', - icon: 'lucide:badge-question-mark', - }, - { title: 'Data Types', path: '/configuration/data-types', icon: 'lucide:type' }, - { - title: 'Sharing Configuration', - path: '/configuration/sharing', - icon: 'lucide:share-2', - }, - ], - }, - { - title: 'Commands', - icon: 'lucide:command', - children: [ - { title: 'About Commands', path: '/commands' }, - { title: 'Restrictions', path: '/commands/restrictions' }, - { title: 'Backport', path: '/commands/backport' }, - { title: 'Copy', path: '/commands/copy' }, - { title: 'Queue', path: '/commands/queue' }, - { title: 'Rebase', path: '/commands/rebase' }, - { title: 'Refresh', path: '/commands/refresh' }, - { title: 'Squash', path: '/commands/squash' }, - { title: 'Update', path: '/commands/update' }, - { title: 'Dequeue', path: '/commands/dequeue' }, - ], - }, - { - title: 'API', - icon: 'lucide:braces', - children: [ - { title: 'Usage', path: '/api/usage', icon: 'lucide:braces' }, - { - title: 'Reference', - path: '/api/', - icon: 'lucide:list', - children: [ - { title: 'Applications', path: '/api/applications' }, - { title: 'Queues', path: '/api/queues' }, - { title: 'Merge Queue', path: '/api/merge-queue' }, - { title: 'Statistics', path: '/api/statistics' }, - { title: 'Simulator', path: '/api/simulator' }, - { title: 'Event Logs', path: '/api/eventlogs' }, - { title: 'Badges', path: '/api/badges' }, - { title: 'Scheduled Freeze', path: '/api/scheduled-freeze' }, - { title: 'Test Insights', path: '/api/test-insights' }, - ], - }, - ], - }, - { - title: 'Integrations', - icon: 'lucide:blocks', - path: '/integrations', - children: [ - { title: 'GitHub', path: '/integrations/github', icon: 'simple-icons:github' }, - { title: 'GitHub Actions', path: '/integrations/gha', icon: 'simple-icons:githubactions' }, - { title: 'Buildkite', path: '/integrations/buildkite', icon: 'simple-icons:buildkite' }, - { title: 'Jenkins', path: '/integrations/jenkins', icon: 'simple-icons:jenkins' }, - { - title: 'Other CI (status checks)', - path: '/integrations/ci-status-checks', - icon: 'lucide:circle-check', - }, - { title: 'Datadog', path: '/integrations/datadog', icon: 'simple-icons:datadog' }, - { title: 'Slack', path: '/integrations/slack', icon: 'simple-icons:slack' }, - { title: 'Dependabot', path: '/integrations/dependabot', icon: 'simple-icons:dependabot' }, - { title: 'Terraform', path: '/integrations/terraform', icon: 'simple-icons:terraform' }, - ], - }, - { - title: 'Migrate to Mergify', - path: '/migrate', - icon: 'lucide:arrow-right-left', - children: [ - { title: 'Overview', path: '/migrate', icon: 'lucide:lightbulb' }, - { title: 'From Bulldozer', path: '/migrate/bulldozer', icon: 'lucide:truck' }, - { title: 'From Bors‑NG', path: '/migrate/bors-ng', icon: 'lucide:bot' }, - { - title: 'From GitHub Merge Queue', - path: '/migrate/github-merge-queue', - icon: 'simple-icons:github', - }, - ], - }, - { title: 'CLI', path: '/cli', icon: 'lucide:terminal' }, - { title: 'Security', path: '/security', icon: 'lucide:shield' }, - { title: 'Support', path: '/support', icon: 'lucide:life-buoy' }, - { title: 'Billing', path: '/billing', icon: 'lucide:banknote' }, - { title: 'Changelog', path: '/changelog', icon: 'lucide:list' }, + { title: 'Home', path: '/', icon: 'lucide:house' }, + { + title: 'Merge Queue', + icon: 'mergify:merge-queue', + path: '/merge-queue', + children: [ + { title: 'Overview', path: '/merge-queue', icon: 'lucide:lightbulb' }, + { title: 'Setup', path: '/merge-queue/setup', icon: 'lucide:settings' }, + { title: 'Queue Modes', path: '/merge-queue/queue-modes', icon: 'lucide:git-fork' }, + { + title: 'Concepts', + icon: 'lucide:book-open', + children: [ + { title: 'Lifecycle', path: '/merge-queue/lifecycle', icon: 'lucide:refresh-cw' }, + { title: 'Batches', path: '/merge-queue/batches', icon: 'lucide:boxes' }, + ], + }, + { + title: 'Configure', + icon: 'lucide:sliders-horizontal', + children: [ + { title: 'Queue Rules', path: '/merge-queue/rules', icon: 'lucide:layers' }, + { title: 'Priority', path: '/merge-queue/priority', icon: 'lucide:traffic-cone' }, + { + title: 'Merge Strategies', + path: '/merge-queue/merge-strategies', + icon: 'octicon:git-merge-16', + }, + { title: 'Deployment', path: '/merge-queue/deploy', icon: 'lucide:rocket' }, + ], + }, + { + title: 'Scale & Tune', + icon: 'lucide:gauge', + children: [ + { + title: 'Scopes', + path: '/merge-queue/scopes', + icon: 'lucide:network', + children: [ + { title: 'Overview', path: '/merge-queue/scopes', icon: 'lucide:lightbulb' }, + { + title: 'File Patterns', + path: '/merge-queue/scopes/file-patterns', + icon: 'lucide:file', + }, + { title: 'Nx', path: '/merge-queue/scopes/nx', icon: 'simple-icons:nx' }, + { title: 'Bazel', path: '/merge-queue/scopes/bazel', icon: 'simple-icons:bazel' }, + { + title: 'Turborepo', + path: '/merge-queue/scopes/turborepo', + icon: 'simple-icons:turborepo', + }, + { + title: 'Other Build Tools', + path: '/merge-queue/scopes/others', + icon: 'lucide:settings', + }, + ], + }, + { + title: 'Parallel Checks', + path: '/merge-queue/parallel-checks', + icon: 'lucide:split', + }, + { title: 'Performance', path: '/merge-queue/performance', icon: 'lucide:gauge' }, + ], + }, + { + title: 'Integrations & Setup', + icon: 'lucide:puzzle', + children: [ + { title: 'Two-Step CI', path: '/merge-queue/two-step', icon: 'lucide:arrow-right-left' }, + { title: 'Monorepo', path: '/merge-queue/monorepo', icon: 'lucide:boxes' }, + { title: 'Stacked PRs', path: '/merge-queue/stacks', icon: 'lucide:layers' }, + { + title: 'GitHub Rulesets Compatibility', + path: '/merge-queue/github-rulesets', + icon: 'simple-icons:github', + }, + { + title: 'Browser Extensions', + path: '/merge-queue/browser-extensions', + icon: 'lucide:puzzle', + }, + ], + }, + { + title: 'Operate', + icon: 'lucide:activity', + children: [ + { title: 'Pause', path: '/merge-queue/pause', icon: 'lucide:circle-pause' }, + { title: 'Monitoring', path: '/merge-queue/monitoring', icon: 'lucide:layout-dashboard' }, + ], + }, + ], + }, + { + title: 'CI Insights', + path: '/ci-insights', + icon: 'mergify:ci-insights', + children: [ + { title: 'Overview', path: '/ci-insights', icon: 'lucide:lightbulb' }, + { title: 'Runners', path: '/ci-insights/runners', icon: 'lucide:server' }, + { title: 'Jobs', path: '/ci-insights/jobs', icon: 'lucide:list-checks' }, + { title: 'Auto-Retry', path: '/ci-insights/auto-retry', icon: 'lucide:rotate-cw' }, + { + title: 'Flaky Test Detection', + path: '/ci-insights/flaky-test-detection', + icon: 'lucide:bug', + }, + { + title: 'CI Setup', + icon: 'lucide:settings', + children: [ + { + title: 'GitHub Actions', + path: '/ci-insights/setup/github-actions', + icon: 'simple-icons:githubactions', + }, + { + title: 'Buildkite', + path: '/ci-insights/setup/buildkite', + icon: 'simple-icons:buildkite', + }, + { title: 'Jenkins', path: '/ci-insights/setup/jenkins', icon: 'simple-icons:jenkins' }, + ], + }, + ], + }, + { + title: 'Test Insights', + path: '/test-insights', + icon: 'mergify:test-insights', + children: [ + { title: 'Overview', path: '/test-insights', icon: 'lucide:lightbulb' }, + { title: 'Prevention', path: '/test-insights/prevention', icon: 'lucide:shield-half' }, + { title: 'Detection', path: '/test-insights/detection', icon: 'lucide:search' }, + { title: 'Mitigation', path: '/test-insights/mitigation', icon: 'lucide:radiation' }, + { title: 'Quarantine', path: '/test-insights/quarantine', icon: 'lucide:radiation' }, + { title: 'CLI', path: '/test-insights/cli', icon: 'lucide:terminal' }, + { + title: 'Test Frameworks Setup', + path: '/test-insights#test-framework-configuration', + icon: 'lucide:flask-conical', + children: [ + { + title: 'Cypress', + path: '/test-insights/test-frameworks/cypress', + icon: 'simple-icons:cypress', + }, + { title: 'Go', path: '/test-insights/test-frameworks/golang', icon: 'simple-icons:go' }, + { title: 'Jest', path: '/test-insights/test-frameworks/jest', icon: 'simple-icons:jest' }, + { + title: 'JUnit', + path: '/test-insights/test-frameworks/junit', + icon: 'simple-icons:junit5', + }, + { + title: 'minitest', + path: '/test-insights/test-frameworks/minitest', + icon: 'simple-icons:ruby', + }, + { + title: 'MSTest', + path: '/test-insights/test-frameworks/mstest', + icon: 'simple-icons:dotnet', + }, + { + title: 'NUnit', + path: '/test-insights/test-frameworks/nunit', + icon: 'simple-icons:dotnet', + }, + { title: 'Pest', path: '/test-insights/test-frameworks/pest', icon: 'simple-icons:php' }, + { + title: 'PHPUnit', + path: '/test-insights/test-frameworks/phpunit', + icon: 'simple-icons:php', + }, + { + title: 'Playwright', + path: '/test-insights/test-frameworks/playwright', + icon: 'simple-icons:playwright', + }, + { + title: 'pytest', + path: '/test-insights/test-frameworks/pytest', + icon: 'simple-icons:pytest', + }, + { + title: 'RSpec', + path: '/test-insights/test-frameworks/rspec', + icon: 'simple-icons:ruby', + }, + { title: 'Rust', path: '/test-insights/test-frameworks/rust', icon: 'simple-icons:rust' }, + { + title: 'TestNG', + path: '/test-insights/test-frameworks/testng', + icon: 'simple-icons:testinglibrary', + }, + { + title: 'Vitest', + path: '/test-insights/test-frameworks/vitest', + icon: 'simple-icons:vitest', + }, + ], + }, + ], + }, + { + title: 'Merge Protections', + path: '/merge-protections', + icon: 'mergify:merge-protections', + children: [ + { title: 'Overview', path: '/merge-protections', icon: 'lucide:lightbulb' }, + { title: 'Setup', path: '/merge-protections/setup', icon: 'lucide:settings' }, + { title: 'Auto-Merge', path: '/merge-protections/auto-merge', icon: 'lucide:zap' }, + { + title: 'Built‑in Protections', + path: '/merge-protections/builtin', + icon: 'lucide:shield-user', + }, + { title: 'Custom Rules', path: '/merge-protections/custom-rules', icon: 'lucide:ruler' }, + { title: 'Freezes', path: '/merge-protections/freeze', icon: 'lucide:snowflake' }, + { title: 'Examples', path: '/merge-protections/examples', icon: 'lucide:lightbulb' }, + ], + }, + { + title: 'Stacks', + path: '/stacks', + icon: 'mergify:stacks', + children: [ + { title: 'Overview', path: '/stacks', icon: 'lucide:lightbulb' }, + { title: 'Concepts', path: '/stacks/concepts', icon: 'lucide:network' }, + { title: 'Setup', path: '/stacks/setup', icon: 'lucide:wrench' }, + { title: 'Creating Stacks', path: '/stacks/creating', icon: 'lucide:layers' }, + { title: 'Updating Stacks', path: '/stacks/updating', icon: 'lucide:square-pen' }, + { title: 'Reviewing Stacks', path: '/stacks/reviewing', icon: 'lucide:search' }, + { title: 'Team Adoption', path: '/stacks/team', icon: 'lucide:users' }, + { + title: 'Compare Tools', + path: '/stacks/compare', + icon: 'lucide:scale', + children: [ + { title: 'Overview', path: '/stacks/compare', icon: 'lucide:lightbulb' }, + { title: 'vs gh-stack', path: '/stacks/compare/gh-stack', icon: 'simple-icons:github' }, + { + title: 'vs Graphite', + path: '/stacks/compare/graphite', + icon: 'simple-icons:graphite', + }, + ], + }, + ], + }, + { + title: 'Workflow Automation', + icon: 'lucide:zap', + path: '/workflow', + children: [ + { title: 'Workflow Automation', path: '/workflow/', icon: 'lucide:zap' }, + { title: 'Rule Syntax', path: '/workflow/rule-syntax', icon: 'lucide:badge-question-mark' }, + { + title: 'Actions', + icon: 'lucide:rocket', + path: '/workflow/actions', + children: [ + { title: 'Assign', path: '/workflow/actions/assign', icon: 'lucide:user-plus' }, + { title: 'Backport', path: '/workflow/actions/backport', icon: 'lucide:git-branch' }, + { title: 'Close', path: '/workflow/actions/close', icon: 'lucide:circle-x' }, + { title: 'Copy', path: '/workflow/actions/copy', icon: 'lucide:share-2' }, + { title: 'Comment', path: '/workflow/actions/comment', icon: 'lucide:list' }, + { + title: 'Delete Head Branch (Deprecated)', + path: '/workflow/actions/delete_head_branch', + icon: 'lucide:scissors', + }, + { + title: 'Dismiss Reviews', + path: '/workflow/actions/dismiss_reviews', + icon: 'lucide:message-square-x', + }, + { title: 'Edit', path: '/workflow/actions/edit', icon: 'lucide:type' }, + { + title: 'GitHub Actions', + path: '/workflow/actions/github_actions', + icon: 'simple-icons:githubactions', + }, + { title: 'Label', path: '/workflow/actions/label', icon: 'lucide:badge-check' }, + { title: 'Merge', path: '/workflow/actions/merge', icon: 'octicon:git-merge-16' }, + { + title: 'Post Check (Deprecated)', + path: '/workflow/actions/post_check', + icon: 'lucide:circle-check', + }, + { title: 'Queue', path: '/workflow/actions/queue', icon: 'mergify:merge-queue' }, + { title: 'Rebase', path: '/workflow/actions/rebase', icon: 'lucide:git-branch' }, + { + title: 'Request Reviews', + path: '/workflow/actions/request_reviews', + icon: 'octicon:code-review-16', + }, + { title: 'Review', path: '/workflow/actions/review', icon: 'lucide:message-square-text' }, + { title: 'Update', path: '/workflow/actions/update', icon: 'lucide:git-branch' }, + { title: 'Squash', path: '/workflow/actions/squash', icon: 'lucide:layers' }, + ], + }, + ], + }, + { + title: 'Monorepo CI', + path: '/monorepo-ci', + icon: 'lucide:network', + children: [ + { title: 'Overview', path: '/monorepo-ci', icon: 'lucide:network' }, + { + title: 'GitHub Actions', + path: '/monorepo-ci/github-actions', + icon: 'simple-icons:githubactions', + }, + { + title: 'Buildkite', + path: '/monorepo-ci/buildkite', + icon: 'simple-icons:buildkite', + }, + ], + }, + { + title: 'Rule Engine', + icon: 'lucide:book', + children: [ + { title: 'Configuration File', path: '/configuration/file-format', icon: 'lucide:file' }, + { + title: 'Conditions', + path: '/configuration/conditions', + icon: 'lucide:badge-question-mark', + }, + { title: 'Data Types', path: '/configuration/data-types', icon: 'lucide:type' }, + { + title: 'Sharing Configuration', + path: '/configuration/sharing', + icon: 'lucide:share-2', + }, + ], + }, + { + title: 'Commands', + icon: 'lucide:command', + children: [ + { title: 'About Commands', path: '/commands' }, + { title: 'Restrictions', path: '/commands/restrictions' }, + { title: 'Backport', path: '/commands/backport' }, + { title: 'Copy', path: '/commands/copy' }, + { title: 'Queue', path: '/commands/queue' }, + { title: 'Rebase', path: '/commands/rebase' }, + { title: 'Refresh', path: '/commands/refresh' }, + { title: 'Squash', path: '/commands/squash' }, + { title: 'Update', path: '/commands/update' }, + { title: 'Dequeue', path: '/commands/dequeue' }, + ], + }, + { + title: 'API', + icon: 'lucide:braces', + children: [ + { title: 'Usage', path: '/api/usage', icon: 'lucide:braces' }, + { + title: 'Reference', + path: '/api/', + icon: 'lucide:list', + children: [ + { title: 'Applications', path: '/api/applications' }, + { title: 'Queues', path: '/api/queues' }, + { title: 'Merge Queue', path: '/api/merge-queue' }, + { title: 'Statistics', path: '/api/statistics' }, + { title: 'Simulator', path: '/api/simulator' }, + { title: 'Event Logs', path: '/api/eventlogs' }, + { title: 'Badges', path: '/api/badges' }, + { title: 'Scheduled Freeze', path: '/api/scheduled-freeze' }, + { title: 'Test Insights', path: '/api/test-insights' }, + ], + }, + ], + }, + { + title: 'Integrations', + icon: 'lucide:blocks', + path: '/integrations', + children: [ + { title: 'GitHub', path: '/integrations/github', icon: 'simple-icons:github' }, + { title: 'GitHub Actions', path: '/integrations/gha', icon: 'simple-icons:githubactions' }, + { title: 'Buildkite', path: '/integrations/buildkite', icon: 'simple-icons:buildkite' }, + { title: 'Jenkins', path: '/integrations/jenkins', icon: 'simple-icons:jenkins' }, + { + title: 'Other CI (status checks)', + path: '/integrations/ci-status-checks', + icon: 'lucide:circle-check', + }, + { title: 'Datadog', path: '/integrations/datadog', icon: 'simple-icons:datadog' }, + { title: 'Slack', path: '/integrations/slack', icon: 'simple-icons:slack' }, + { title: 'Dependabot', path: '/integrations/dependabot', icon: 'simple-icons:dependabot' }, + { title: 'Terraform', path: '/integrations/terraform', icon: 'simple-icons:terraform' }, + ], + }, + { + title: 'Migrate to Mergify', + path: '/migrate', + icon: 'lucide:arrow-right-left', + children: [ + { title: 'Overview', path: '/migrate', icon: 'lucide:lightbulb' }, + { title: 'From Bulldozer', path: '/migrate/bulldozer', icon: 'lucide:truck' }, + { title: 'From Bors‑NG', path: '/migrate/bors-ng', icon: 'lucide:bot' }, + { + title: 'From GitHub Merge Queue', + path: '/migrate/github-merge-queue', + icon: 'simple-icons:github', + }, + ], + }, + { title: 'CLI', path: '/cli', icon: 'lucide:terminal' }, + { title: 'Security', path: '/security', icon: 'lucide:shield' }, + { title: 'Support', path: '/support', icon: 'lucide:life-buoy' }, + { title: 'Billing', path: '/billing', icon: 'lucide:banknote' }, + { title: 'Changelog', path: '/changelog', icon: 'lucide:list' }, ]; function addUuidOnGroups(items: NavItem[]): NavItem[] { - return items.map((item) => { - if (item.children) { - return { - ...item, - id: v5(JSON.stringify(item.children), v5.DNS), - children: addUuidOnGroups(item.children), - }; - } + return items.map((item) => { + if (item.children) { + return { + ...item, + id: v5(JSON.stringify(item.children), v5.DNS), + children: addUuidOnGroups(item.children), + }; + } - return item; - }); + return item; + }); } export default addUuidOnGroups(navItems);