fix: read live review requests from each forge

This commit is contained in:
codex-bot-andresmgsl 2026-08-24 12:38:03 +00:00
parent 7bdae45c98
commit 0160f6a883
3 changed files with 85 additions and 0 deletions

View file

@ -452,6 +452,15 @@ forge_pr_view() {
}' }'
} }
# forge_pr_review_requests <n> — logins with a live review request.
# Forgejo review.go deletes REQUEST_REVIEW rows when the reviewer submits any
# review, so these rows are the exact live set rather than review history (#238).
forge_pr_review_requests() {
local n="${1:?forge_pr_review_requests: number required}"
forge_api --paginate "repos/$REPO/pulls/$n/reviews" \
--jq '.[] | select(.state == "REQUEST_REVIEW") | .user.login' | sort -u
}
forge_label_list() { forge_api --paginate "repos/$REPO/labels" --jq '.[].name'; } forge_label_list() { forge_api --paginate "repos/$REPO/labels" --jq '.[].name'; }
# forge_label_create — an UPSERT, matching `gh label create --force` (#4743). # forge_label_create — an UPSERT, matching `gh label create --force` (#4743).

View file

@ -101,6 +101,12 @@ forge_pr_view() {
gh pr view "$n" -R "$REPO" --json mergeable,statusCheckRollup gh pr view "$n" -R "$REPO" --json mergeable,statusCheckRollup
} }
# forge_pr_review_requests <n> — logins with a live review request.
forge_pr_review_requests() {
local n="${1:?forge_pr_review_requests: number required}"
forge_api "repos/$REPO/pulls/$n" --jq '.requested_reviewers[].login' | sort -u
}
# forge_label_list — every label name in the repo. # forge_label_list — every label name in the repo.
forge_label_list() { forge_label_list() {
gh label list -R "$REPO" --limit 200 --json name --jq '.[].name' gh label list -R "$REPO" --limit 200 --json name --jq '.[].name'

View file

@ -581,6 +581,76 @@ check "...never deriving them from reviews, as forgejo must" 1 "" \
unset -f gh unset -f gh
. "$ROOT/lib/forge-forgejo.sh" . "$ROOT/lib/forge-forgejo.sh"
# --- forge_pr_review_requests: the forge's live request set -------------
# A stale verdict is not itself evidence that anybody was re-requested. The
# backend reads the forge's request representation directly, so the state
# machine can distinguish the builder's ball from the panel's (#238).
review_requests_stub() {
fake_forge "$FAKE_REVIEWS_N" "$FAKE_REVIEWS"
}
# crew!96 after the builder pushed: two approvals and one requested change
# belong to the older head, but no live REQUEST_REVIEW row exists.
FAKE_REVIEWS_N=3
FAKE_REVIEWS='[
{"user":{"login":"kimi-bot"},"state":"APPROVED","commit_id":"old","submitted_at":"2026-08-22T23:05:01Z"},
{"user":{"login":"glm-bot"},"state":"APPROVED","commit_id":"old","submitted_at":"2026-08-22T23:14:45Z"},
{"user":{"login":"claude-bot"},"state":"REQUEST_CHANGES","commit_id":"old","submitted_at":"2026-08-22T23:03:39Z"}
]'
review_requests_stub
check "supersedes: a stale approver who was never re-requested is not requested" 0 "" \
eq "" forge_pr_review_requests 96
check "supersedes: a merged PR whose requested_reviewers still lists the whole panel yields nobody" 0 "" \
eq "" forge_pr_review_requests 146
# crew!97's opening request rows. Deliberately unordered with one duplicate:
# the public contract is sorted unique logins, independent of API row order.
FAKE_REVIEWS_N=5
FAKE_REVIEWS='[
{"user":{"login":"kimi-bot"},"state":"REQUEST_REVIEW","commit_id":"","submitted_at":"2026-08-22T22:51:12Z"},
{"user":{"login":"claude-bot"},"state":"REQUEST_REVIEW","commit_id":"","submitted_at":"2026-08-22T22:51:11Z"},
{"user":{"login":"codex-bot"},"state":"REQUEST_REVIEW","commit_id":"","submitted_at":"2026-08-22T22:51:11Z"},
{"user":{"login":"glm-bot"},"state":"REQUEST_REVIEW","commit_id":"","submitted_at":"2026-08-22T22:51:12Z"},
{"user":{"login":"kimi-bot"},"state":"REQUEST_REVIEW","commit_id":"","submitted_at":"2026-08-22T22:51:13Z"}
]'
review_requests_stub
check "forgejo returns the four opening request logins sorted and deduplicated" 0 "" \
eq $'claude-bot\ncodex-bot\nglm-bot\nkimi-bot' forge_pr_review_requests 97
FAKE_REVIEWS_N=2
FAKE_REVIEWS='[
{"user":{"login":"claude-bot"},"state":"REQUEST_CHANGES","commit_id":"old","submitted_at":"2026-08-22T23:03:39Z"},
{"user":{"login":"claude-bot"},"state":"REQUEST_REVIEW","commit_id":"","submitted_at":"2026-08-22T23:16:17Z"}
]'
review_requests_stub
check "supersedes: a reviewer re-requested while holding REQUEST_CHANGES is requested" 0 "" \
eq "claude-bot" forge_pr_review_requests 97
FAKE_REVIEWS_N=1
FAKE_REVIEWS='[{"user":{"login":"kimi-bot"},"state":"REQUEST_REVIEW","commit_id":"","submitted_at":"2026-08-22T22:51:12Z"}]'
review_requests_stub
check "supersedes: a login whose only row is REQUEST_REVIEW is requested" 0 "" \
eq "kimi-bot" forge_pr_review_requests 97
# GitHub already exposes the exact live set on the PR object. Stub only the
# network boundary and assert the same backend-neutral output contract.
. "$ROOT/lib/forge-github.sh"
# shellcheck disable=SC2317 # invoked indirectly, by forge_api
gh() {
case "$1 $2" in
"api repos/o/r/pulls/55")
jq -r '.requested_reviewers[].login' <<'JSON'
{"requested_reviewers":[{"login":"glm-bot"},{"login":"claude-bot"}]}
JSON
;;
*) return 1 ;;
esac
}
check "github returns requested_reviewers from the PR object unchanged" 0 "" \
eq $'claude-bot\nglm-bot' forge_pr_review_requests 55
unset -f gh
. "$ROOT/lib/forge-forgejo.sh"
# --- forge_pr_view: newest verdict per context must win ------------------ # --- forge_pr_view: newest verdict per context must win ------------------
# checks_state groups repeated contexts and selects the newest by # checks_state groups repeated contexts and selects the newest by
# [.startedAt, .createdAt, .completedAt]. Mapping only {context,state} left # [.startedAt, .createdAt, .completedAt]. Mapping only {context,state} left