mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #16] [MERGED] feat(cursor-review): optional blocking gate for unresolved findings (BE-1891) #29
Labels
No labels
cursor-review-catalog-drift
groom
groom
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/github-workflows#29
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/github-workflows/pull/16
Author: @mattmillerai
Created: 6/27/2026
Status: ✅ Merged
Merged: 6/30/2026
Merged by: @mattmillerai
Base:
main← Head:matt/be-1891-cursor-review-blocking📝 Commits (1)
da45649feat(cursor-review): optional blocking gate for unresolved findings (BE-1891)📊 Changes
4 files changed (+258 additions, -1 deletions)
View changed files
📝
.github/cursor-review/README.md(+43 -0)➕
.github/cursor-review/gate-unresolved.py(+156 -0)📝
.github/workflows/cursor-review.yml(+58 -0)📝
README.md(+1 -1)📄 Description
ELI-5
The cursor-review bot posts its findings on your PR as review threads, but today
they're just advice — a red review doesn't stop a merge. This adds an opt-in
switch (
blocking: true) that makes those findings count: if any cursor-reviewthread is still unresolved, a "Blocking gate" check turns red. Resolve the
threads (or push a fix and re-review) and it goes green. Nothing changes for
anyone until they flip the switch on.
What
blocking(boolean, defaultfalse) on the reusablecursor-review.yml.false(default) → unchanged: review is advisory, the new gate job isskipped entirely, no caller behavior changes.
true→ a finalBlocking gatejob fails the check while the PR hasunresolved cursor-review finding threads.
.github/cursor-review/gate-unresolved.py: queries the PR'sreviewThreads(GraphQL, paginated) and exits non-zero when any cursor-reviewfinding thread is unresolved.
step the caller must do to actually block merges.
How "unresolved" is defined (and why)
A review thread counts as a cursor-review finding thread when its originating
review's body starts with the consolidated marker (
## 🔍 Cursor Review — Consolidated panel) — the same discriminator the workflow's existing dup-checkalready uses. I chose the body-marker over matching the posting identity
(
cloud-code-bot/github-actions[bot], per BE-1800/BE-1812) on purpose: it'sidentity-independent, so the gate works whether the review posts as
github-actions[bot](default) or under a dedicatedbot_app_idApp, with noneed to resolve a per-caller bot login. Only the inline-findings review creates
threads (the "no findings"/error/fallback reviews are body-only), so a matching
thread always means a real anchored finding.
Outdated threads (their hunk changed since the finding posted) are excluded —
a re-review re-posts anything still wrong as a fresh thread, so blocking on
outdated ones would force resolving superseded findings.
Idempotency
The gate queries live thread state on every run and its
if:doesn't dependon
already_reviewed, so: resolve the threads → re-run the check (re-add thelabel, or "Re-run jobs") → green, with no fresh panel needed.
Verification
Static:
actionlintclean on the workflow;py_compileclean on the script;YAML parses.
Behavioral — ran the gate script against real PRs (proves the marker matches
live GitHub data and the resolved/outdated filtering works):
Plus a unit-style logic test covering pagination + resolved/outdated/non-cursor/
empty-comment exclusion.
Acceptance criteria
blocking: true+ unresolved bot thread → check RED; resolving → GREEN.blocking: false/ unset → check passes regardless of findings (gate jobskipped; rest of pipeline untouched).
step.
Judgment calls / notes
the panel/judge itself fails (no review posted, or an error review with no
threads), the gate is green —
notify-completealready surfaces that failureseparately, and blocking merges on a transient cursor-agent/judge outage would
be too aggressive. Flagging in case fail-closed is preferred.
marking the
Blocking gatecheck as a required status check in the callerrepo (documented). Could not exercise the full GitHub Actions run here (no
live
blocking: truecaller yet) — the gate script is proven end-to-endagainst live PRs; the job wiring is
actionlint-clean and reuses the exactasset-checkout pattern of the existing
notify-*jobs.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.