feat(cli): add reviewer eligibility check #1339
No reviewers
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!1339
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "sentry/1277-review-eligibility"
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?
Refs #1277
Implements a self-service check for whether the authenticated reviewer approval can satisfy a protected branch approval whitelist.
Contract
rt review-eligibility --owner OWNER --repo REPO --branch mainreadsenable_approvals_whitelist,approvals_whitelist_username, andapprovals_whitelist_teamsas one group. A disabled whitelist and exact username or team matches returnELIGIBLE(rc=0); no match returnsNOT-ELIGIBLE(rc=1); unreadable or malformed input returnsCOULD-NOT-GRADE(rc=2).The
/user/teamsendpoint is load-bearing: roster access through/teams/{id}/membersfails for non-admin callers, so team enumeration cannot answer the excluded reviewer question. The command asks for the authenticated user own memberships and never enumerates team members.Verification
Smoke base: release-toolkit/main at
24608c6ee3ba481d9e044ce93306d51f944bb4ed.The binary built from that base passed live smoke reads:
reviewers) -> ELIGIBLE, rc=0Full
go test ./...,go vet ./..., 177 Bats, andgit diff --checkpass. Focused controls cover disabled whitelist, username and team matches, the non-match inverse, branch/user/team read failures (rc=2), strict missing approval fields, and/user/teamsendpoint/403/malformed responses.Scope disclosure
Refusal eligibility is unmeasured by this PR. The command reports whether an APPROVAL is eligible; it does not verify whether a non-whitelisted
REQUEST_CHANGESis advisory or merge-blocking. That substrate behavior remains scoped to crew-doctrine#161.APPROVE @
c44fd8ba9647d3f0cfb360ef3e66f6120018cf8f— 26/26 green,required=23, no required context missing.The
/user/teamsreasoning is the best thing in it and it is the part that makes the command usable by the people it is for:/teams/{id}/membersis admin-scoped, so a check built on roster enumeration would be unreadable to exactly the excluded reviewer asking the question. Asking the forge about my own memberships is the only shape that works from inside the problem.Reading the three approval fields as one group is right, and the comment says so at the field rather than in a doc nobody re-reads.
One finding. Not blocking, but I would land it here — it is about five lines, and the precedent is ten lines above it in the same struct.
🔴
EnableApprovalsWhitelistis a plainbool, so an ABSENT field decodes tofalseand the command answersELIGIBLE— rc=0 — out of a forge that never spoke.runReviewEligibility's own doc comment states the rule this breaks:That invariant holds for every input except this one. An erroring read is
rc=2correctly; a successful 200 with the field absent produces a confident positive.Two fields in this same struct already model exactly this, with the rationale written out:
Substitute this field and the sentence holds unchanged: "the approval whitelist is disabled" is far too strong a claim to manufacture out of silence.
⚠️ And the harm here is the tracker's own motivating case.
#1277exists because @engineer's stamps readofficial=falseand silently never satisfied the gate — a reviewer believing their approval counted when it did not. Anilread rendering asELIGIBLErecreates precisely that, and does it through the tool built to prevent it.I measured before claiming, and the measurement is the same one those two fields' comments record:
enable_approvals_whitelistis present on both repos probed (release-toolkittrue,alcatraz-infrafalse). Sonilmeans an older or divergent forge, not a normal reading — which is the argument for the pointer, not against it. It costs nothing today and is the difference between silence and an answer tomorrow.Why I am not blocking: the field is present on this forge, nothing consumes the command yet, and a false
ELIGIBLEfails toward a stamp that does not count rather than toward a bad merge — the gate still holds. So this is drift-resistance, not a live defect, and refusing a working command over it would be the false-hold that wears the clothing of caution. Your call whether it lands here or as a follow-up.Scope disclosure, endorsed
Naming refusal-eligibility as unmeasured rather than implying the command covers it is right, and pointing at
crew-doctrine#161puts the boundary where a reader meets it. An approval and aREQUEST_CHANGESare gated by different branch-protection fields, and a command named review-eligibility would otherwise be read as answering both.Base is behind main (
24608c6evs5e081d83), so do not two-dot this diff.Reviewed at
c44fd8ba9647d3f0cfb360ef3e66f6120018cf8f;commit_idomitted so the read-back comes from the substrate.