Skip to content

Commit 9021b2c

Browse files
committed
fix(ci): simplify review script, add evot health check
1 parent 59c10de commit 9021b2c

1 file changed

Lines changed: 59 additions & 107 deletions

File tree

.github/scripts/auto-fix-review.sh

Lines changed: 59 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,28 @@ set -euo pipefail
33

44
echo "=== PR #${PR_NUMBER}: Addressing review comments ==="
55

6-
# Collect inline review comments with file context and comment id
6+
# Collect inline review comments (exclude our own bot replies)
77
COMMENTS=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/comments" \
8-
--jq '[.[] | select(.user.login != "github-actions[bot]") | {id, path, line, body, user: .user.login}]' 2>/dev/null || echo '[]')
8+
--jq '[.[] | select(.user.login != "github-actions[bot]" and (.in_reply_to_id == null)) | {id, path, line, body, user: .user.login}]' 2>/dev/null || echo '[]')
99

10-
COMMENT_COUNT=$(echo "$COMMENTS" | jq 'length')
11-
if [ "$COMMENT_COUNT" -eq 0 ]; then
10+
# Also get PR-level reviews
11+
PR_REVIEWS=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/reviews" \
12+
--jq '[.[] | select(.user.login != "github-actions[bot]" and .body != "") | {id, user: .user.login, state: .state, body}]' 2>/dev/null || echo '[]')
13+
14+
INLINE_COUNT=$(echo "$COMMENTS" | jq 'length')
15+
REVIEW_COUNT=$(echo "$PR_REVIEWS" | jq 'length')
16+
TOTAL=$((INLINE_COUNT + REVIEW_COUNT))
17+
18+
if [ "$TOTAL" -eq 0 ]; then
1219
echo "No review comments to address"
1320
exit 0
1421
fi
1522

16-
echo "Found ${COMMENT_COUNT} review comment(s)"
23+
echo "Found ${INLINE_COUNT} inline comment(s), ${REVIEW_COUNT} review(s)"
1724

18-
# Also get PR-level review comments
19-
PR_REVIEWS=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/reviews" \
20-
--jq '[.[] | select(.user.login != "github-actions[bot]" and .body != "") | {id, user: .user.login, state: .state, body}]' 2>/dev/null || echo '[]')
25+
# Format for prompt
26+
FORMATTED=$(echo "$COMMENTS" | jq -r '.[] | "Comment #\(.id) by \(.user) on \(.path):\(.line):\n\(.body)\n---"')
27+
PR_REVIEW_TEXT=$(echo "$PR_REVIEWS" | jq -r '.[] | "Review by \(.user) (\(.state)):\n\(.body)\n---"')
2128

2229
# Get PR info
2330
PR_TITLE=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json title --jq '.title')
@@ -26,100 +33,34 @@ PR_TITLE=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json title --jq '.title')
2633
git config user.name "github-actions[bot]"
2734
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
2835

29-
# --- Step 1: Triage each comment (accept/reject + plan) ---
30-
echo "--- Triaging comments ---"
31-
FORMATTED=$(echo "$COMMENTS" | jq -r '.[] | "Comment #\(.id) by \(.user) on \(.path):\(.line)\n\(.body)\n---"')
32-
PR_REVIEW_TEXT=$(echo "$PR_REVIEWS" | jq -r '.[] | "Review by \(.user) (\(.state)):\n\(.body)\n---"')
36+
# Verify evot works
37+
echo "--- Testing evot ---"
38+
evot -p "say ok" --max-turns 1 --max-duration 10 2>&1 | tail -3 || echo "evot test failed"
3339

34-
TRIAGE_OUTPUT=$(evot -p "You are triaging review comments on a documentation PR.
40+
# --- Run evot to triage + fix in one pass ---
41+
echo "--- Processing review feedback ---"
42+
OUTPUT=$(evot -p "You are addressing review feedback on a documentation PR.
3543
3644
PR #${PR_NUMBER}: ${PR_TITLE}
3745
3846
The Databend source code is available at _databend/src/ for reference.
3947
40-
## Inline comments:
48+
## Inline review comments:
4149
${FORMATTED}
4250
4351
## PR-level reviews:
4452
${PR_REVIEW_TEXT}
4553
46-
For each comment, decide whether to accept or reject it.
47-
Output a JSON array:
48-
[
49-
{\"id\": <comment_id>, \"accepted\": true/false, \"reason\": \"brief explanation\"},
50-
...
51-
]
52-
53-
Accept if the feedback is valid and actionable. Reject if it's incorrect, out of scope, or already addressed." \
54-
--output-format stream-json \
55-
--max-turns 1 --max-duration 120 2>&1 || true)
56-
57-
TRIAGE_TEXT=$(echo "$TRIAGE_OUTPUT" | grep '"run_finished"' | tail -1 | jq -r '.payload.text // ""' 2>/dev/null || true)
58-
59-
# Reply to each inline comment with triage result
60-
TRIAGE_JSON=$(echo "$TRIAGE_TEXT" | python3 -c "
61-
import sys, json, re
62-
t = sys.stdin.read()
63-
m = re.search(r'\[.*\]', t, re.DOTALL)
64-
if m:
65-
try:
66-
arr = json.loads(m.group())
67-
print(json.dumps(arr))
68-
except: print('[]')
69-
else: print('[]')
70-
" 2>/dev/null || echo '[]')
71-
72-
TRIAGE_COUNT=$(echo "$TRIAGE_JSON" | jq 'length')
73-
for i in $(seq 0 $((TRIAGE_COUNT - 1))); do
74-
CID=$(echo "$TRIAGE_JSON" | jq -r ".[$i].id")
75-
ACCEPTED=$(echo "$TRIAGE_JSON" | jq -r ".[$i].accepted")
76-
REASON=$(echo "$TRIAGE_JSON" | jq -r ".[$i].reason")
77-
78-
if [ "$ACCEPTED" = "true" ]; then
79-
REPLY="✅ **Accepted** — ${REASON}"
80-
else
81-
REPLY="❌ **Declined** — ${REASON}"
82-
fi
83-
84-
gh api "repos/${REPO}/pulls/${PR_NUMBER}/comments/${CID}/replies" \
85-
-f body="$REPLY" 2>/dev/null || true
86-
done
87-
88-
# Check if any comments were accepted
89-
ACCEPTED_COUNT=$(echo "$TRIAGE_JSON" | jq '[.[] | select(.accepted == true)] | length')
90-
if [ "$ACCEPTED_COUNT" -eq 0 ]; then
91-
echo "No comments accepted, nothing to fix"
92-
exit 0
93-
fi
94-
95-
# --- Step 2: Apply accepted fixes ---
96-
echo "--- Applying ${ACCEPTED_COUNT} accepted fix(es) ---"
97-
ACCEPTED_COMMENTS=$(echo "$TRIAGE_JSON" | jq -r '[.[] | select(.accepted == true)] | .[] | "Comment #\(.id): \(.reason)"')
98-
99-
# Get the full comment bodies for accepted ones
100-
ACCEPTED_IDS=$(echo "$TRIAGE_JSON" | jq -r '[.[] | select(.accepted == true) | .id] | @csv')
101-
ACCEPTED_DETAILS=$(echo "$COMMENTS" | jq -r --argjson triage "$TRIAGE_JSON" '
102-
[.[] | . as $c | if ($triage | map(select(.id == $c.id and .accepted == true)) | length > 0) then . else empty end]
103-
| .[] | "File: \(.path), Line: \(.line)\n\(.body)\n---"
104-
')
105-
106-
OUTPUT=$(evot -p "You are fixing a documentation PR based on accepted review feedback.
107-
108-
PR #${PR_NUMBER}: ${PR_TITLE}
109-
110-
The Databend source code is available at _databend/src/ for reference.
111-
112-
## Accepted feedback to address:
113-
${ACCEPTED_DETAILS}
114-
11554
Task:
116-
1. Read each accepted comment and the referenced file.
117-
2. Make the requested changes.
118-
3. If you modify docs/en/, also update the corresponding docs/cn/ file.
55+
1. For each comment, decide: accept (valid, actionable) or decline (incorrect, out of scope, already addressed).
56+
2. Output your triage as a summary first.
57+
3. Then make the accepted changes to the files.
58+
4. If you modify docs/en/, also update the corresponding docs/cn/ file.
11959
12060
Rules:
12161
- Only modify files under docs/en/ and docs/cn/.
122-
- Do NOT run git, gh, or any shell commands that modify the repository state." \
62+
- Do NOT run git, gh, or any shell commands that modify the repository state.
63+
- The CI script handles git commit, push, and PR replies." \
12364
--output-format stream-json \
12465
--max-turns 300 --max-duration 600 2>&1 || true)
12566

@@ -129,14 +70,36 @@ STATS=$(echo "$OUTPUT" | grep '"run_finished"' | tail -1 | jq -r '{
12970
duration_s: ((.payload.duration_ms // 0) / 1000 | floor),
13071
input: .payload.usage.input,
13172
output: .payload.usage.output
132-
}' 2>/dev/null || echo '{}')
133-
echo "Stats: $(echo "$STATS" | jq -c .)"
73+
}' 2>/dev/null || echo '{"turns":"?","duration_s":0,"input":"?","output":"?"}')
74+
75+
TURNS=$(echo "$STATS" | jq -r '.turns // "?"')
76+
DURATION=$(echo "$STATS" | jq -r '.duration_s // 0')
77+
INPUT_T=$(echo "$STATS" | jq -r '.input // "?"')
78+
OUTPUT_T=$(echo "$STATS" | jq -r '.output // "?"')
79+
echo "Stats: turns=${TURNS} duration=${DURATION}s tokens=${INPUT_T}/${OUTPUT_T}"
80+
81+
# Extract assistant log
82+
ASSISTANT_LOG=$(echo "$OUTPUT" | grep '"assistant_completed"' | jq -r '
83+
.payload.content[]? | select(.type=="text") | .text // empty
84+
' 2>/dev/null | head -100)
13485

13586
# Check for changes
13687
if git diff --quiet && git diff --cached --quiet && [ -z "$(git ls-files --others --exclude-standard docs/)" ]; then
137-
echo "No changes made"
88+
echo "No file changes"
13889
gh pr comment "$PR_NUMBER" --repo "$REPO" \
139-
--body "Reviewed the feedback — accepted ${ACCEPTED_COUNT} comment(s) but no file changes were needed." || true
90+
--body "### Review feedback processed
91+
92+
Reviewed ${TOTAL} comment(s) — no file changes needed.
93+
94+
Turns: ${TURNS} | Duration: ${DURATION}s | Tokens: ${INPUT_T} in / ${OUTPUT_T} out
95+
96+
<details><summary>Agent log</summary>
97+
98+
\`\`\`
99+
${ASSISTANT_LOG}
100+
\`\`\`
101+
102+
</details>" || true
140103
exit 0
141104
fi
142105

@@ -145,27 +108,16 @@ git add docs/
145108
git commit -m "docs: address review feedback on PR #${PR_NUMBER}" || exit 0
146109
git push origin HEAD --force-with-lease
147110

148-
# Extract assistant log
149-
ASSISTANT_LOG=$(echo "$OUTPUT" | grep '"assistant_completed"' | jq -r '
150-
.payload.content[]? | select(.type=="text") | .text // empty
151-
' 2>/dev/null | head -80)
152-
153-
TURNS=$(echo "$STATS" | jq -r '.turns // "?"')
154-
DURATION=$(echo "$STATS" | jq -r '.duration_s // 0')
155-
INPUT_T=$(echo "$STATS" | jq -r '.input // "?"')
156-
OUTPUT_T=$(echo "$STATS" | jq -r '.output // "?"')
157-
158-
# Summary comment on PR
159-
COMMENT_BODY="### Addressed review feedback
111+
# Comment on PR
112+
gh pr comment "$PR_NUMBER" --repo "$REPO" \
113+
--body "### Addressed review feedback
160114
161-
**Accepted:** ${ACCEPTED_COUNT}/${COMMENT_COUNT} comments | Turns: ${TURNS} | Duration: ${DURATION}s | Tokens: ${INPUT_T} in / ${OUTPUT_T} out
115+
Reviewed ${TOTAL} comment(s) | Turns: ${TURNS} | Duration: ${DURATION}s | Tokens: ${INPUT_T} in / ${OUTPUT_T} out
162116
163117
<details><summary>Agent log</summary>
164118
165119
\`\`\`
166120
${ASSISTANT_LOG}
167121
\`\`\`
168122
169-
</details>"
170-
171-
gh pr comment "$PR_NUMBER" --repo "$REPO" --body "$COMMENT_BODY" || true
123+
</details>" || true

0 commit comments

Comments
 (0)