feat: cancel pending pull review requests (Closes #1340)
CI / lint (pull_request) Successful in 3m17s
CI / build-release (pull_request) Successful in 7s
CI / browser-journey (pull_request) Failing after 5m18s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-24 08:01:25 +00:00
1 parent 7517d81046
commit d776a2b003
6 files changed
+284 -1

No files matched your search

+47
View File
@@ -2028,6 +2028,53 @@ async def request_assigned_pull_review(
}
async def cancel_assigned_pull_review(
repository: str, number: int, reviewer: str, expected_head_sha: str
) -> dict:
login, pull = await _current_login_and_target(
f"repos/{repository}/pulls/{number}"
)
head = pull.get("head") if isinstance(pull.get("head"), dict) else {}
requested = [
item["login"] for item in (pull.get("requested_reviewers") or [])
if isinstance(item, dict) and isinstance(item.get("login"), str)
]
if (
pull.get("state") != "open"
or pull.get("merged") is True
or not _login_in_users(login, pull.get("assignees"))
or head.get("sha") != expected_head_sha
or reviewer not in requested
):
raise IssueNotAvailableError("Pending review request changed")
response = await _get_client().request(
"DELETE",
f"/api/v1/repos/{repository}/pulls/{number}/requested_reviewers",
headers=_auth(),
json={"reviewers": [reviewer]},
)
response.raise_for_status()
confirmed_response = await _get_client().get(
f"/api/v1/repos/{repository}/pulls/{number}", headers=_auth()
)
confirmed_response.raise_for_status()
confirmed = confirmed_response.json()
remaining = [
item["login"] for item in (confirmed.get("requested_reviewers") or [])
if isinstance(item, dict) and isinstance(item.get("login"), str)
] if isinstance(confirmed, dict) else []
confirmed_head = confirmed.get("head") if isinstance(confirmed, dict) and isinstance(confirmed.get("head"), dict) else {}
if reviewer in remaining or confirmed_head.get("sha") != expected_head_sha:
raise ValueError("Gitea did not confirm reviewer cancellation")
return {
"repository": repository,
"number": number,
"head_sha": expected_head_sha,
"requested_reviewers": remaining,
"reviewer": reviewer,
}
async def _change_assigned_pull_owners(
repository: str, number: int, recipient: str | None
) -> dict:
+28
View File
@@ -6773,6 +6773,34 @@ async def request_assigned_pull_review(
return JSONResponse(result)
@app.delete("/api/v1/repos/{owner}/{repo}/pulls/{number}/request-review")
async def cancel_assigned_pull_review(
request: PullReviewRequest,
owner: str,
repo: str,
number: int = PathParam(gt=0),
) -> JSONResponse:
try:
result = await asyncio.wait_for(
gitea_proxy.cancel_assigned_pull_review(
f"{owner}/{repo}", number, request.reviewer, request.expected_head_sha
),
timeout=ISSUE_ACTION_TIMEOUT_SECONDS,
)
except gitea_proxy.IssueNotAvailableError:
return JSONResponse(
{"error": "The pull request or reviewer changed. Reload before cancelling the request."},
status_code=409,
)
except Exception:
return JSONResponse(
{"error": "The cancellation could not be confirmed. Refresh review data before retrying."},
status_code=503,
headers={"Retry-After": "1"},
)
return JSONResponse(result)
@app.patch("/api/v1/repos/{owner}/{repo}/pulls/{number}/release")
async def release_assigned_pull(
owner: str, repo: str, number: int = PathParam(gt=0)