From 149de37a96fea0245c88bbee734baa50c9f4bb92 Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Fri, 10 Apr 2026 17:24:50 +0200 Subject: [PATCH] feat(queue): add merge queue skill for Claude marketplace Add a new mergify-merge-queue skill covering queue status monitoring, PR inspection, pause/unpause management, and troubleshooting guidance. Distributed via the Claude marketplace plugin alongside mergify-stack. Change-Id: I5d9b25e09e3eaf03a84d5b7ccd829a9f3905a6ad --- .claude-plugin/marketplace.json | 5 ++ mergify_cli/queue/skill.md | 86 +++++++++++++++++++++++++++ mergify_cli/tests/queue/test_skill.py | 77 ++++++++++++++++++++++++ skills/mergify-merge-queue/SKILL.md | 1 + 4 files changed, 169 insertions(+) create mode 100644 mergify_cli/queue/skill.md create mode 100644 mergify_cli/tests/queue/test_skill.py create mode 120000 skills/mergify-merge-queue/SKILL.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 790a3e6c..361c8a38 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -8,6 +8,11 @@ "name": "mergify-stack", "source": "./", "description": "Stacked PRs, merge queues, and Git workflow automation" + }, + { + "name": "mergify-merge-queue", + "source": "./", + "description": "Monitor, inspect, pause, and manage the Mergify merge queue" } ] } diff --git a/mergify_cli/queue/skill.md b/mergify_cli/queue/skill.md new file mode 100644 index 00000000..5b9c568e --- /dev/null +++ b/mergify_cli/queue/skill.md @@ -0,0 +1,86 @@ +--- +name: mergify-merge-queue +description: Use Mergify merge queue to monitor, inspect, pause, and manage the merge queue. ALWAYS use this skill when checking queue status, investigating PR merge state, pausing/unpausing the queue, or debugging merge failures. Triggers on merge queue, queue status, queue pause, merge, CI checks. +--- + +# Mergify Merge Queue + +## Overview + +The merge queue serializes PR merges, running CI on temporary merge commits to catch integration failures before they reach the target branch. Use the CLI to monitor queue state, inspect individual PRs, and manage the queue. + +## Commands + +```bash +mergify queue status # Show queue status (batches, waiting PRs) +mergify queue status --branch main # Filter by branch +mergify queue status --json # Machine-readable JSON output +mergify queue show # Detailed state of a PR in the queue +mergify queue show -v # Full checks table and conditions tree +mergify queue show --json # Machine-readable JSON output +mergify queue pause --reason "..." # Pause the queue (requires reason) +mergify queue unpause # Resume the queue +``` + +## Checking Queue Status + +Use `mergify queue status` to see the current state of the merge queue: + +- **Batches**: groups of PRs being tested together, shown with their CI status and ETA +- **Waiting PRs**: PRs queued but not yet in a batch, shown with priority and queue time +- **Pause state**: whether the queue is paused and why + +Use `--json` when you need to parse the output programmatically. + +## Inspecting a PR + +Use `mergify queue show ` to check why a PR is stuck or how it's progressing: + +- **Position**: where the PR sits in the queue +- **Priority**: which priority rule matched +- **CI state**: whether checks are passing, pending, or failing +- **Conditions**: which merge conditions are met and which are blocking +- Use `-v` (verbose) for the full checks table and conditions tree + +## Queue States + +| State | Meaning | +|-------|---------| +| `running` | Batch is actively running CI | +| `preparing` | Batch is being set up | +| `bisecting` | Batch failed, bisecting to find the culprit | +| `failed` | CI failed for this batch | +| `merged` | PRs in this batch have been merged | +| `waiting_for_merge` | CI passed, waiting for GitHub to merge | +| `waiting_for_previous_batches` | Blocked on earlier batches completing | +| `waiting_for_batch` | Waiting to be picked up into a batch | +| `waiting_schedule` | Outside the configured merge schedule | +| `frozen` | Queue is paused | + +## Pausing and Unpausing + +Pause the queue to temporarily halt all merges (e.g., during incidents or deployments): + +```bash +mergify queue pause --reason "production incident — halting merges" +mergify queue unpause +``` + +- Pausing does **not** cancel running CI — it prevents new merges from starting +- The reason is visible to all team members in the queue status +- Use `--yes-i-am-sure` to skip the confirmation prompt in scripts + +## Troubleshooting + +**PR not entering the queue:** +- Check that the PR's merge conditions are met: `mergify queue show -v` +- Look at the conditions section for unmet requirements + +**PR stuck in queue:** +- Check CI state: `mergify queue show ` +- If checks are failing, inspect the failing checks with `-v` +- If the queue is paused, check who paused it: `mergify queue status` + +**Queue moving slowly:** +- Check for failing batches that trigger bisection: `mergify queue status` +- Bisecting batches test PRs individually, which is slower than batch merging diff --git a/mergify_cli/tests/queue/test_skill.py b/mergify_cli/tests/queue/test_skill.py new file mode 100644 index 00000000..4616b090 --- /dev/null +++ b/mergify_cli/tests/queue/test_skill.py @@ -0,0 +1,77 @@ +# +# Copyright © 2021-2026 Mergify SAS +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from __future__ import annotations + +import pathlib +import re + +import yaml + + +SKILL_PATH = pathlib.Path(__file__).parents[2] / "queue" / "skill.md" + + +def _get_skill_content() -> str: + return SKILL_PATH.read_text(encoding="utf-8") + + +def test_skill_content_is_readable() -> None: + content = _get_skill_content() + assert len(content) > 0 + + +def test_skill_has_valid_frontmatter() -> None: + content = _get_skill_content() + # Extract YAML frontmatter between --- markers + match = re.match(r"^---\n(.+?)\n---\n", content, re.DOTALL) + assert match is not None, "Skill must have YAML frontmatter" + + frontmatter = yaml.safe_load(match.group(1)) + assert isinstance(frontmatter, dict), "Frontmatter must be a YAML mapping" + assert "name" in frontmatter, "Frontmatter must have 'name'" + assert "description" in frontmatter, "Frontmatter must have 'description'" + assert frontmatter["name"] == "mergify-merge-queue" + + +REQUIRED_SECTIONS = [ + "## Commands", + "## Checking Queue Status", + "## Inspecting a PR", + "## Queue States", + "## Troubleshooting", +] + + +def test_skill_has_required_sections() -> None: + content = _get_skill_content() + for section in REQUIRED_SECTIONS: + assert section in content, f"Skill is missing required section: {section}" + + +def test_skill_references_valid_commands() -> None: + """Check that commands referenced in the skill exist in the CLI.""" + from mergify_cli.queue.cli import queue + + content = _get_skill_content() + # Extract `mergify queue ` references + referenced = set(re.findall(r"mergify queue ([\w-]+)", content)) + + available = set(queue.commands.keys()) + + for cmd in referenced: + assert cmd in available, ( + f"Skill references 'mergify queue {cmd}' but it's not a registered command. " + f"Available: {sorted(available)}" + ) diff --git a/skills/mergify-merge-queue/SKILL.md b/skills/mergify-merge-queue/SKILL.md new file mode 120000 index 00000000..0c6330a7 --- /dev/null +++ b/skills/mergify-merge-queue/SKILL.md @@ -0,0 +1 @@ +../../mergify_cli/queue/skill.md \ No newline at end of file