Skip to content

docs(merge-gate-watcher): ask git whether a PR merged, and reach REST when GraphQL is dead - #177

Merged
CybotTM merged 3 commits into
mainfrom
retro/watch-merges-without-the-api
Aug 13, 2026
Merged

docs(merge-gate-watcher): ask git whether a PR merged, and reach REST when GraphQL is dead#177
CybotTM merged 3 commits into
mainfrom
retro/watch-merges-without-the-api

Conversation

@CybotTM

@CybotTM CybotTM commented Aug 13, 2026

Copy link
Copy Markdown
Member

Two additions to merge-gate-watcher.md, both from burning the GraphQL budget twice in one session while doing nothing unusual.

"Has it merged yet?" needs no API at all

The existing "Watcher cost" section makes a watcher cheaper — one per subject, REST over GraphQL, 180 s. It does not say that the commonest watcher question is free: once a PR is queued, the only thing left to learn is whether its head landed on the base, and git merge-base --is-ancestor answers that from the local graph. It keeps working while both budgets are exhausted, which is exactly when a watcher is still running.

Added with the trap that bit me: git log --grep="#<pr>" is not that test. --grep searches the whole commit message, so an older commit whose body mentions the number matches. A watcher on PR #765 reported MERGED from its first tick because a months-old dependency bump mentioned that number; the PR was actually CONFLICTING. Same asymmetry as the section's own empty-result rule, inverted — an empty result is first a broken query, and a positive result from a text search is first a coincidence.

REST still opens a PR when GraphQL is dead

gh pr create is GraphQL. With graphql: 0/5000 and core: 4700/5000 the whole gh pr * surface is unusable while REST is fine, and gh api repos/$O/$R/pulls -X POST takes the same arguments. Same for PR comments. Both used on 2026-08-13 to finish work that gh pr create refused.

Plus one flag trap found next to it: gh api --paginate --slurp is rejected together with --jq, so paginated check-runs need a file and then jq.

Not added

The section already says to sleep to the reset in one background command rather than retrying into the limit. I violated that rule rather than found it missing, so it needs no more prose.

Copilot AI lite review requested due to automatic review settings August 13, 2026 13:04
@github-actions github-actions Bot added documentation Improvements or additions to documentation skill labels Aug 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@CybotTM

CybotTM commented Aug 13, 2026

Copy link
Copy Markdown
Member Author

Self-review (Copilot has been quota-blocked all day across both repos, so this is the review of record — and re-requesting a fourth time is the exact "retry into a known-exhausted resource" this PR argues against).

Two findings, both fixed here rather than after merge.

The false-positive example was unverified prose. It said "a months-old dependency bump mentioned #765 in its body" — I had not looked. Checked: the matched commit is this January dependency bump from 2026-01-12, seven months before the watcher ran, and the #765 in it is an issue number belonging to actions/attest-build-provenance — a different repository, embedded in the changelog Dependabot pastes into the body. A sharper trap than the one I described, so the text names it.

The ancestry check silently fails under squash. A squash merge writes one new commit with a new hash, so the original head is never an ancestor and the check reads "not merged" forever — a watcher built on this advice would hang in any squash-merge repo. Added the limit and the one-REST-call alternative. This is the finding I care about: the recommendation was correct for the repo I was standing in and wrong as a general rule.

Refutations that did not hold:

  • A fetch costs budget too. It does not — the git protocol is neither the REST nor the GraphQL quota. That is the entire point of the section.
  • The REST fallback is speculative. Used twice on 2026-08-13 to open fix(dashboard): give context_blocked a colour and a label t3x-nr-llm#764 and #765 after gh pr create returned GraphQL: API rate limit already exceeded.
  • This duplicates the existing budget rules. It does not restate them; the section says so explicitly and adds only what they omit — that the commonest watcher question needs no budget at all.

… when GraphQL is dead

Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
A squash merge writes a new commit, so the original head is never an ancestor
and the check would read 'not merged' forever. Found while reviewing the
patch, not after shipping it.

Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
@CybotTM
CybotTM force-pushed the retro/watch-merges-without-the-api branch from 2e52e71 to 6863568 Compare August 13, 2026 13:28
@sonarqubecloud

Copy link
Copy Markdown

@CybotTM
CybotTM merged commit 9af71aa into main Aug 13, 2026
23 checks passed
@CybotTM
CybotTM deleted the retro/watch-merges-without-the-api branch August 13, 2026 13:40
@CybotTM CybotTM mentioned this pull request Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation skill

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants