[object Object]

← back to Cli Printing Press

ci(cli): add Mergify merge queue (#757)

ecb2cba0a31e122ff24a11f2fd405f006074f0ca · 2026-05-08 16:27:35 -0700 · Trevin Chow

Files touched

Diff

commit ecb2cba0a31e122ff24a11f2fd405f006074f0ca
Author: Trevin Chow <trevin@trevinchow.com>
Date:   Fri May 8 16:27:35 2026 -0700

    ci(cli): add Mergify merge queue (#757)
---
 .github/workflows/lint.yml     |  1 +
 .github/workflows/pr-title.yml |  1 +
 .mergify.yml                   | 41 +++++++++++++++++++++++++++++++++++++++++
 AGENTS.md                      |  3 +++
 docs/RELEASE.md                |  5 +++--
 5 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 0cecd8bd..d926fceb 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -12,6 +12,7 @@ permissions:
 
 jobs:
   lint:
+    name: go-lint
     runs-on: ubuntu-latest
     timeout-minutes: 15
     steps:
diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml
index ae4fb1ce..08713078 100644
--- a/.github/workflows/pr-title.yml
+++ b/.github/workflows/pr-title.yml
@@ -13,6 +13,7 @@ permissions:
 
 jobs:
   lint:
+    name: pr-title
     runs-on: ubuntu-latest
     timeout-minutes: 5
     steps:
diff --git a/.mergify.yml b/.mergify.yml
new file mode 100644
index 00000000..25b4514c
--- /dev/null
+++ b/.mergify.yml
@@ -0,0 +1,41 @@
+queue_rules:
+  - name: default
+    queue_conditions:
+      - base = main
+    merge_conditions:
+      - check-success = build-and-test
+      - check-success = generated-test
+      - check-success = go-lint
+      - check-success = golden
+      - check-success = pr-title
+      - check-success = test
+    merge_method: squash
+    update_method: rebase
+    batch_size: 1
+
+merge_queue:
+  queued_label: queued
+  dequeued_label: dequeued
+  status_comments: outcomes
+
+merge_protections_settings:
+  reporting_method: check-runs
+  auto_merge_conditions:
+    - label = ready-to-merge
+
+merge_protections:
+  - name: require-ready-label-and-ci
+    if:
+      - base = main
+    success_conditions:
+      - or:
+        - label = ready-to-merge
+        - and:
+          - head = release-please--branches--main
+          - "title ~= ^chore\\(main\\): release"
+      - check-success = build-and-test
+      - check-success = generated-test
+      - check-success = go-lint
+      - check-success = golden
+      - check-success = pr-title
+      - check-success = test
diff --git a/AGENTS.md b/AGENTS.md
index 002cf7d3..6d135e54 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -139,6 +139,9 @@ See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the human-facing contributor guide
 
 ## Versioning
 Releases are automated by release-please. Never manually edit version numbers.
+- Normal feature/fix PRs land through the Mergify queue: add the `ready-to-merge` label when the PR is ready to merge, and let Mergify rebase/test/merge it. Do not use the GitHub merge button for normal PRs once `Mergify Merge Protections` is required on `main`.
+- release-please PRs are the release control point. They collect already-merged conventional commits; merge the release PR only when you intend to cut a release. The Mergify config allows release-please PRs to satisfy merge protection without `ready-to-merge`, so maintainers can still merge the release PR manually after CI passes.
+- When enabling branch protection for the Mergify queue, require the `Mergify Merge Protections` status check and set `required_status_checks.strict=false`; Mergify owns latest-`main` validation through the queue, and GitHub's strict up-to-date requirement recreates the manual rebase loop.
 - The plugin version lives in exactly two places and must stay in sync: `.claude-plugin/plugin.json` -> `version`, and `internal/version/version.go` -> `var Version` (annotated `x-release-please-version`; goreleaser injects via ldflags).
 - `TestVersionConsistencyAcrossFiles` in [`internal/cli/release_test.go`](internal/cli/release_test.go#L57) fails if those two versions drift.
 - Do not add a `version` field to `.claude-plugin/marketplace.json` plugin entries. `TestMarketplaceJSONHasNoPluginVersion` in [`internal/cli/release_test.go`](internal/cli/release_test.go#L81) fails if a reviewer re-adds one.
diff --git a/docs/RELEASE.md b/docs/RELEASE.md
index d3342364..d1b37902 100644
--- a/docs/RELEASE.md
+++ b/docs/RELEASE.md
@@ -2,8 +2,9 @@
 
 Releases are fully automated by release-please + goreleaser; no manual steps. The flow:
 
-1. Merge PRs to `main` with conventional-commit titles.
+1. Merge normal feature/fix PRs through the Mergify queue by adding `ready-to-merge` after review and CI pass.
 2. release-please opens and updates a release PR with the accumulated changelog.
-3. When ready to ship, merge the release PR. release-please bumps the version files, creates a git tag, opens a GitHub release, and goreleaser builds and attaches cross-platform binaries.
+3. When ready to ship, merge the release PR. It does not need `ready-to-merge`; the Mergify config allows release-please PRs to satisfy merge protection after CI passes.
+4. release-please bumps the version files, creates a git tag, opens a GitHub release, and goreleaser builds and attaches cross-platform binaries.
 
 Do not manually edit version numbers or release artifacts to bypass this flow. If release behavior changes, update the inline `AGENTS.md` versioning rule in the same PR.

← 92d303ac fix(cli): infer bearer auth from prose-only specs (#753)  ·  back to Cli Printing Press  ·  ci(cli): skip title lint for merge queue batches (#760) ecb35ab0 →