Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
2.7 KiB
name, description
| name | description |
|---|---|
| pr-watch | Wait for a GitHub PR's checks to finish before merging or reporting on it. Use whenever you need to know whether a PR is green. Do not hand-roll a polling loop over gh pr view. |
Waiting on a PR
scripts/pr-watch <pr-number> [--expect <sha>] [--timeout <sec>] [--interval <sec>]
exit 0 every check COMPLETED, none failed, and MERGEABLE with a state of
CLEAN, UNSTABLE or HAS_HOOKS
exit 1 a check failed (under any mergeability, BLOCKED included), or the
PR is not mergeable (CONFLICTING, DIRTY, BEHIND, DRAFT, or a state
it does not know)
exit 2 the head moved during the wait, or is not --expect
exit 3 timed out with checks still running, mergeability still UNKNOWN,
or still BLOCKED with every registered check green
exit 4 usage or environment error
exit 5 the PR is MERGED or CLOSED, at the head the watch pinned; it ends on
the first poll that sees it closed, which may be mid-wait
Exit 0 now means mergeable, not only green. GitHub computes mergeability
lazily and reports UNKNOWN for a while after the base moves. It also reports
BLOCKED for the moment before a required check that needs: another job has
registered. The watch waits out both, so you do not need to re-check
mergeable by hand after it. Exit 3 is not a pass. It may be a required
check that never ran. Why each
state counts the way it does: context/code/tooling.md, "pr-watch and
mergeability" (improvise-edpl).
Pass --expect <sha> whenever you know which commit you are asking about.
It is the difference between "this PR is green" and "the thing I pushed is
green", and a PR here was once merged at a head that predated its own fix.
Do not write the loop yourself
Four signals look like "finished" and are not:
- "nothing pending" — also true when no check has registered yet. Require a non-zero total as well.
conclusion == null—conclusionis a string, empty while running. Teststatus == "COMPLETED".- a verdict from before the head moved — re-check the head, or
--expect. mergeable: UNKNOWN— GitHub has not computed it yet. It is not a pass, and PRs #172 and #179 both went green on it.
gh is shell-aliased to a different tool in these shells; pr-watch locates a
real one itself. Do not reintroduce a bare gh call in a script here.
Before deciding a PR is stuck
Check suites can take several minutes to appear at all, and a Copilot review
takes about six. Compare date -u against the GitHub timeline rather than a
felt interval, and do not close and reopen a PR to unstick it.
scripts/pr-watch-test.sh drives every case from fixtures.