From b5c854c7a70c18f6e635037df651bd4baf046744 Mon Sep 17 00:00:00 2001 From: openhands Date: Thu, 19 Mar 2026 20:09:22 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20review-pr.sh=20exits=20after=20REQUEST?= =?UTF-8?q?=5FCHANGES=20=E2=80=94=20should=20wait=20for=20new=20commits=20?= =?UTF-8?q?and=20re-review=20(#300)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After REQUEST_CHANGES/DISCUSS, review-pr.sh now writes PHASE:awaiting_changes (with the reviewed SHA) instead of PHASE:review_complete. review-poll.sh gains a re-review section that detects awaiting_changes sessions with new commits and CI passing, then re-invokes review-pr.sh in the same tmux session. Co-Authored-By: Claude Opus 4.6 (1M context) --- review/review-poll.sh | 49 +++++++++++++++++++++++++++++++++++++++++++ review/review-pr.sh | 16 ++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/review/review-poll.sh b/review/review-poll.sh index 20dda63..1b0e584 100755 --- a/review/review-poll.sh +++ b/review/review-poll.sh @@ -178,6 +178,55 @@ Instructions: touch "/tmp/review-injected-${PROJECT_NAME}-${pr_num}" } +# --- Re-review: trigger review for awaiting_changes sessions with new commits --- +if [ -n "${REVIEW_SESSIONS:-}" ]; then + while IFS= read -r session; do + pr_num="${session#review-"${PROJECT_NAME}"-}" + phase_file="/tmp/review-session-${PROJECT_NAME}-${pr_num}.phase" + + current_phase=$(head -1 "$phase_file" 2>/dev/null | tr -d '[:space:]' || true) + [ "$current_phase" = "PHASE:awaiting_changes" ] || continue + + reviewed_sha=$(sed -n 's/^SHA://p' "$phase_file" 2>/dev/null | tr -d '[:space:]' || true) + [ -n "$reviewed_sha" ] || continue + + pr_json=$(curl -sf -H "Authorization: token ${CODEBERG_TOKEN}" \ + "${API_BASE}/pulls/${pr_num}" 2>/dev/null || true) + [ -n "$pr_json" ] || continue + + pr_state=$(printf '%s' "$pr_json" | jq -r '.state // "unknown"') + [ "$pr_state" = "open" ] || continue + + current_sha=$(printf '%s' "$pr_json" | jq -r '.head.sha // ""') + pr_branch=$(printf '%s' "$pr_json" | jq -r '.head.ref // ""') + if [ -z "$current_sha" ] || [ "$current_sha" = "$reviewed_sha" ]; then continue; fi + + ci_state=$(curl -sf -H "Authorization: token ${CODEBERG_TOKEN}" \ + "${API_BASE}/commits/${current_sha}/status" | jq -r '.state // "unknown"') + + if ! ci_passed "$ci_state"; then + if ci_required_for_pr "$pr_num"; then + log " #${pr_num} awaiting_changes: new SHA ${current_sha:0:7} CI=${ci_state}, waiting" + continue + fi + fi + + log " #${pr_num} re-review: new commits (${reviewed_sha:0:7}→${current_sha:0:7})" + + if "${SCRIPT_DIR}/review-pr.sh" "$pr_num" 2>&1; then + REVIEWED=$((REVIEWED + 1)) + FRESH_SHA=$(curl -sf -H "Authorization: token ${CODEBERG_TOKEN}" \ + "${API_BASE}/pulls/${pr_num}" | jq -r '.head.sha // ""') || true + inject_review_into_dev_session "$pr_num" "${FRESH_SHA:-$current_sha}" "$pr_branch" + else + log " #${pr_num} re-review failed" + matrix_send "review" "❌ PR #${pr_num} re-review failed" 2>/dev/null || true + fi + + [ "$REVIEWED" -lt "$MAX_REVIEWS" ] || break + done <<< "$REVIEW_SESSIONS" +fi + while IFS= read -r line; do PR_NUM=$(echo "$line" | awk '{print $1}') PR_SHA=$(echo "$line" | awk '{print $2}') diff --git a/review/review-pr.sh b/review/review-pr.sh index ce5b200..b37e1e1 100755 --- a/review/review-pr.sh +++ b/review/review-pr.sh @@ -871,3 +871,19 @@ if [ -n "$EVENT_ID" ]; then fi log "DONE: ${VERDICT} (re-review: ${IS_RE_REVIEW})" + +# --- Write phase based on verdict --- +# Claude wrote PHASE:review_complete to signal JSON is ready; now overwrite +# with the correct lifecycle phase so review-poll.sh knows what to do next. +case "$VERDICT" in + APPROVE) + echo "PHASE:review_complete" > "${PHASE_FILE}" + ;; + REQUEST_CHANGES|DISCUSS) + printf 'PHASE:awaiting_changes\nSHA:%s\n' "$PR_SHA" > "${PHASE_FILE}" + log "awaiting new commits (PHASE:awaiting_changes)" + ;; + *) + echo "PHASE:review_complete" > "${PHASE_FILE}" + ;; +esac