Skip to content

ci-mode: fail the merge group of a pull request labelled merge-commit - #7

Merged
georgeh0 merged 2 commits into
mainfrom
ci-mode-merge-commit-guard
Oct 24, 2026
Merged

georgeh0 merged 2 commits into
mainfrom
ci-mode-merge-commit-guard

Conversation

@georgeh0

Copy link
Copy Markdown
Member

Summary

  • ci-mode fails the merge group of a pull request labelled merge-commit. The queue squashes, and CI.md already says such a pull request bypasses the queue, but nothing enforced it: cocoindex-plus#549 and #557, both OSS merges, went through the queue and lost their upstream parents (cocoindex-io/cocoindex-plus#561).
  • The guard sits in ci-mode because every conforming CI workflow already runs it, in the changes job that every other job needs. A failure there skips the expensive jobs and fails ci-gate, the required check, so the queue removes the pull request. No workflow file, required check or ruleset changes, so cocoindex-plus's CI.yml stays identical to OSS's and no merge-oss conflict follows.
  • The step reads the pull request number from the queue's branch (gh-readonly-queue/<base>/pr-<n>-<sha>) and its labels through the API. That needs pull-requests: read, which the starter workflow and cocoindex-plus already grant. Only merge groups use it, and only cocoindex-plus has a queue, so cocoindex-code, cocoindex-code-plus and reduce (which grant only checks and contents) are unaffected. The conformance check does not require it, for that reason.
  • A failed lookup fails the merge group: queueing again costs one build, and a squashed merge commit costs a repair merge.
  • Trade-off: the action's name says "mode", and it now also refuses. Renaming would break every ci-mode@v1 caller, so the description says it instead.

After merging, move v1 (CI.md, Changing this kit). The change is compatible: other events run the same code as before.

Test plan

  • pytest scripts (20 passed), conformance on the starter workflow, shellcheck on the step script.
  • The step script, run locally with a fake gh: labelled → exit 1 with the merge instruction; unlabelled → full=true; lookup failure → exit 1; a base branch with a slash, and a malformed or empty ref, parse as intended. With the real API: plus #549 (no label) passes; a pull_request event on plus still returns the fast tier.
  • Live, after v1 moves: a docs-only scratch pull request in cocoindex-plus labelled merge-commit must leave the queue with this error, and an unlabelled pull request must still land. Results go on cocoindex-io/cocoindex-plus#561.

🤖 Generated with Claude Code

georgeh0 and others added 2 commits October 24, 2026 12:23
The queue squashes, so a pull request that must land as a merge commit,
such as an upstream merge, bypasses it (CI.md, Merge commits). Nothing
enforced that: cocoindex-plus#549 and #557, both OSS merges, went through
the queue and lost their upstream parents (cocoindex-plus#561).

On a merge_group event ci-mode now reads the labels of the pull request
that the queue's branch names (gh-readonly-queue/<base>/pr-<n>-<sha>) and
fails when it has `merge-commit`. ci-mode runs in the `changes` job that
every other job needs, so the failure comes before any test runs, and
ci-gate fails with it, which removes the pull request from the queue. A
failed lookup fails too. Reading labels needs `pull-requests: read`, which
the starter workflow already grants; only merge groups use it, so
repositories without a queue are unaffected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@georgeh0
georgeh0 merged commit 40c736f into main Oct 24, 2026
2 checks passed
@georgeh0
georgeh0 deleted the ci-mode-merge-commit-guard branch October 24, 2026 19:25
georgeh0 added a commit that referenced this pull request Oct 24, 2026
…rge commits (#8)

An upstream merge must keep its upstream parent. With the queue squashing,
it had to bypass the queue with an admin merge, and twice it went through
the queue instead and lost its parent (cocoindex-plus#549, #557; #561).
#7 then made ci-mode refuse a labelled pull request,
but that still left a special path to remember.

Now there is one path. The queue merges with merge commits
(rulesets/repo/merge-queue.json), and apply_rulesets.py also sets the
merge settings of every queue repository from rulesets/repo-settings.json:
merge commits only, titled with the pull request's title. A pull request
keeps its history, so an upstream merge goes through the queue like any
change, and no merge method can squash it. Admins bypass only for
incidents, with --merge.

- ci-mode: back to the version before #7; the label guard has nothing
  left to guard.
- CI.md: the queue section, Merge commits (first-parent reading, revert
  with -m 1), the incident bypass, Enforcement, and what was verified in
  cocoindex-plus on 2026-10-24.

Already applied to cocoindex-plus with apply_rulesets.py; --check is clean.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant