feat(ci): review claims via claim / disclaim comments - #11
Conversation
|
Thank you for this pull-request (PR). If this is your first PR, welcome to the community! Below is what will happen next. Please read carefully if you are not familiar with the process. You may open other PRs while this one is being reviewed, and can stack PRs on top of each other, so don't let these steps slow you down.
Tip: The easiest way to get have a fast review is to submit a PR that is small and self-contained, and has clear documentation explaining why things are the way they are in your chages. If you have any problems or questions, please reach out to the community on the Zulip. |
37e01c3 to
24a20a0
Compare
reviewing-in-* review claim labelsclaim / disclaim comments
Replaces the fixed `reviewing-in-1/2/3-days` labels with comment commands, so a reviewer can say `claim 5 days` rather than being limited to the windows someone thought to make a label for, and can claim without repository permissions. claim -- claim this PR for review, for the default 2 day window claim 5 days -- ... for a specific window (hours / days / weeks) claim 2026-08-01 -- ... until a specific date disclaim -- release the claim early The bot requests a review from the claimant, assigns them, applies `review-claimed` and keeps one status comment per PR whose hidden marker carries the whole claim record, edited in place as the claim is extended, completed or released. Reviewing completes the claim; `review_claim_expiry.yml` reminds the claimant 48h and 24h before the deadline and releases stale claims hourly, so nothing stays blocked forever. A claim that runs out without a review takes the claimant back off the PR as reviewer and assignee, and is announced on the `PR reviews` Zulip topic so that somebody else can pick the PR up -- using the same bot credentials as the workers in Alex-Zughaid/PhysLibBots. Only failures are announced. Missing Zulip secrets or a Zulip outage downgrade to a warning: releasing the claim on GitHub matters more than announcing it. A claim is cooperative rather than a lock: anyone may review a claimed PR. The one thing the bot refuses is silently overwriting a live claim -- a second `claim` is answered with who holds it and until when -- while the claimant can always `disclaim` and maintainers can release a claim on someone else's behalf. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
24a20a0 to
c3195dc
Compare
Replaces the fixed `reviewing-in-1/2/3-days` labels with comment commands, so a reviewer can say `claim 5 days` rather than being limited to the windows someone thought to make a label for, and can claim without repository permissions. claim -- claim this PR for review, for the default 2 day window claim 5 days -- ... for a specific window (hours / days / weeks) claim 2026-08-01 -- ... until a specific date disclaim -- release the claim early The bot requests a review from the claimant, assigns them, applies `review-claimed` and keeps one status comment per PR whose hidden marker carries the whole claim record, edited in place as the claim is extended, completed or released. Reviewing completes the claim; `review_claim_expiry.yml` reminds the claimant 48h and 24h before the deadline and releases stale claims hourly, so nothing stays blocked forever. A claim that runs out without a review takes the claimant back off the PR as reviewer and assignee, and is announced on the `PR reviews` Zulip topic so that somebody else can pick the PR up -- using the same bot credentials as the workers in Alex-Zughaid/PhysLibBots. Only failures are announced. Missing Zulip secrets or a Zulip outage downgrade to a warning: releasing the claim on GitHub matters more than announcing it. A claim is cooperative rather than a lock: anyone may review a claimed PR. The one thing the bot refuses is silently overwriting a live claim -- a second `claim` is answered with who holds it and until when -- while the claimant can always `disclaim` and maintainers can release a claim on someone else's behalf. All three jobs are guarded on `github.repository`, as in `add_label_from_diff.yaml` and `pr_size_label.yaml`, so that forks do not run them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
c3195dc to
012ad62
Compare
Ports the claim logic from JavaScript running inside `actions/github-script` to Python, and moves it next to the repository's other Python tooling in `scripts/` rather than hiding it under `.github/scripts/`. The two workflows are now thin wrappers: each sparse-checks-out that one file and runs `python scripts/review_claim.py comment|review|expire`. The script is stdlib-only -- urllib against the REST API -- so the jobs need no dependency install, and it can be run by hand against a repository with a GITHUB_TOKEN. Behaviour is unchanged, except that the claim record in the status comment now stores ISO 8601 timestamps rather than epoch milliseconds, which reads better for anyone looking at the comment source. The jobs run the runner's preinstalled `python3` rather than setting up their own: the script is stdlib-only, so `actions/setup-python` bought nothing but a Node 20 deprecation warning and a slower job. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
f8c8aff to
dad2ba3
Compare
Replaces the fixed
reviewing-in-1/2/3-dayslabels from the first draft of this PR withcomment commands, modelled on the intentions bot.
Two reasons the label version was worse: a window had to have been thought of in advance
and made into a label, and applying a label needs repository permissions that a first-time
reviewer does not have.
The bot requests a review from the claimant, assigns them, applies
review-claimed, andkeeps a single status comment per PR. Claiming again extends the window; submitting a review completes the claim.
Stale claims are released hourly, so nothing stays blocked forever.
A claim is cooperative, not a lock: anyone may review a claimed PR. The one thing the bot
refuses is silently overwriting a live claim — a second
claimis answered with who holdsit and until when. The claimant can always
disclaim, and maintainers can release someoneelse's claim without waiting for it to time out.
Zulip
A claim that runs out without a review is announced on the
PR reviewstopic, so thatsomebody else can pick the PR up:
Only failures are announced — a claim that is honoured, extended or disclaimed is nobody
else's business. This uses the
ZULIP_SITE,ZULIP_BOT_EMAIL,ZULIP_BOT_API_KEYandZULIP_STREAMsecrets already set on this repository, hitting the same/api/v1/messagesendpoint as
postToZulipin PhysLibBots.Missing secrets or a Zulip outage downgrade to a warning: releasing the claim on GitHub
matters more than announcing it. The claimant is named rather than @-mentioned, since a
GitHub login is not a Zulip name.
Design notes
status comment, edited in place rather than reposted. Extending a claim moves the deadline
and resets its reminders with it, and a PR ends up with at most one status comment.
labels_from_comment.yml, so a comment discussingclaims does not trigger one. Any casing works; the last command in a comment wins.
GitHub silently skips scheduled runs under load, so reminders are checked smallest-first:
waking with 20h left sends the 24h reminder, not a wrong "48 hours are left" one.
GitHub refuses a review request for a non-collaborator or for the PR's own author, so
that call is allowed to fail while the label and assignee always land.
.github/scripts/review-claim.js, pulled in by both workflowsvia a sparse checkout, rather than being copied between them.
add_label_from_diff.yamlandpr_size_label.yaml, these carry nogithub.repository == 'leanprover-community/physlib'guard — that guard makes those twoworkflows no-ops in this fork, and these are meant to run here.
Testing
28 unit assertions over the command grammar, window parsing (including clamping, past dates
and garbage) and the marker round-trip, plus 20 scenarios driven through both workflows
against a mock Octokit: claim, extend, claim over someone else's claim, over-long window,
unparseable window, disclaim by claimant / by a non-claimant / by a maintainer / with
nothing held, prose that merely mentions claiming, review by the claimant and by a
stranger, every reminder threshold, an already-posted reminder, a skipped scheduled run, an
already-reviewed claimant, expiry with and without a review, and a stale label with no
claim record, plus the Zulip path with secrets present, with secrets absent, and with the
Zulip API returning 500 — in both failure cases the GitHub-side release still completes.
Label
review-claimedcreated; the three unusedreviewing-in-*labels have been deleted.🤖 Generated with Claude Code