From a4173f07e30ec46d9b567de88ab46c40464ad2d3 Mon Sep 17 00:00:00 2001 From: devops-engineer Date: Mon, 18 May 2026 06:05:42 +0000 Subject: [PATCH] =?UTF-8?q?fix(ci):=20review-check.sh=20=E2=80=94=20diagno?= =?UTF-8?q?se=20wrong-event-string=20PENDING=20reviews=20(internal#503)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The #1 recurring-red (~78%) on qa-review/security-review 'approved' was NOT a Gitea bug: reviewers submitted approvals with event='APPROVE' (or lowercase) instead of the exact enum 'APPROVED'. Gitea silently (HTTP 200) files those as state=PENDING, invisible to this gate's state==APPROVED filter -> false red + manual DB-flip toil. Diagnostic-ONLY: when there are no APPROVED candidates, if a non-author review exists with state=PENDING and a non-empty body (impossible via the correct enum; real drafts have an empty body), emit an actionable error naming the review id/author and the exact re-submit fix. Pass/ fail logic unchanged (still fail-closed). Proof: internal#503. --- .gitea/scripts/review-check.sh | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.gitea/scripts/review-check.sh b/.gitea/scripts/review-check.sh index 5bc004482..a693a71b2 100755 --- a/.gitea/scripts/review-check.sh +++ b/.gitea/scripts/review-check.sh @@ -206,6 +206,29 @@ CANDIDATES=$(jq -r --arg author "$PR_AUTHOR" --arg head "$PR_HEAD_SHA" "$JQ_FILT debug "candidate non-author approvers: $(echo "$CANDIDATES" | tr '\n' ' ')" if [ -z "$CANDIDATES" ]; then + # --- Guardrail (internal#503): explain the most common false + # "no candidates" red. Gitea's review event enum is EXACTLY + # APPROVED/REQUEST_CHANGES/COMMENT/PENDING. A wrong value ("APPROVE", + # lowercase, ...) is silently accepted (HTTP 200) and stored as + # state=PENDING. A correctly-started draft review has an EMPTY body; + # a NON-empty body + state==PENDING by a non-author == an intended + # verdict mis-filed by a wrong event string. Surface it actionably. + # This does NOT change the gate result (still fail-closed below) — it + # only converts a mystery red into a named, self-fixing error. + MISFILED_FILTER='.[] + | select(.state == "PENDING") + | select(.dismissed != true) + | select(.user.login != $author) + | select(((.body // "") | gsub("^\\s+|\\s+$";"") | length) > 0) + | "\(.id)\t\(.user.login)"' + MISFILED=$(jq -r --arg author "$PR_AUTHOR" "$MISFILED_FILTER" "$REVIEWS_JSON" 2>/dev/null || true) + if [ -n "$MISFILED" ]; then + echo "::error::${TEAM}-review: non-author review(s) were SUBMITTED but stored as PENDING — almost certainly the wrong Gitea review event string (internal#503)." + echo "::error::Gitea accepts ONLY the exact enum APPROVED / REQUEST_CHANGES / COMMENT. 'APPROVE' or lowercase is silently (HTTP 200) filed as PENDING and is invisible to this gate." + printf '%s\n' "$MISFILED" | while IFS="$(printf '\t')" read -r _rid _rl; do + [ -n "${_rid:-}" ] && echo "::error:: review id=${_rid} by '${_rl}': RE-SUBMIT via POST ${API}/repos/${OWNER}/${NAME}/pulls/${PR_NUMBER}/reviews with {\"event\":\"APPROVED\"} (correct enum) — do NOT edit the DB." + done + fi echo "::error::${TEAM}-review awaiting non-author APPROVE from ${TEAM} team (no candidates yet)" exit 1 fi -- 2.52.0