Skip to content

Commit aba79eb

Browse files
committed
ci: add auto-fix workflow for issues labeled auto-fix
1 parent 65f74e2 commit aba79eb

2 files changed

Lines changed: 180 additions & 0 deletions

File tree

.github/scripts/auto-fix.sh

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
MAIN=$(git rev-parse --abbrev-ref HEAD)
5+
NUM=$(echo "$ISSUE_JSON" | jq -r '.number')
6+
TITLE=$(echo "$ISSUE_JSON" | jq -r '.title')
7+
BODY=$(echo "$ISSUE_JSON" | jq -r '.body')
8+
BRANCH="auto-fix/issue-${NUM}"
9+
10+
echo "=== #${NUM}: ${TITLE} ==="
11+
12+
# Rollback label on failure
13+
cleanup_on_failure() {
14+
gh issue edit "$NUM" --repo "$REPO" --add-label auto-fix --remove-label auto-fix-in-progress 2>/dev/null || true
15+
}
16+
trap cleanup_on_failure ERR
17+
18+
# Skip if PR exists
19+
if [ "$(gh pr list --repo "$REPO" --head "$BRANCH" --json number --jq 'length')" -gt 0 ]; then
20+
echo "PR exists, skip"
21+
gh issue edit "$NUM" --repo "$REPO" --add-label auto-fix-done --remove-label auto-fix-in-progress
22+
exit 0
23+
fi
24+
25+
git checkout -b "$BRANCH"
26+
27+
# Step 1: Generate fix
28+
evot -p "Fix this issue in databend-docs by modifying files under docs/en/.
29+
Follow existing doc style. Read related files first.
30+
31+
The Databend source code is available at _databend/src/ for reference.
32+
Use it to check actual implementation details (settings, functions, SQL syntax, etc.)
33+
when writing documentation.
34+
35+
Issue #${NUM}: ${TITLE}
36+
${BODY}" \
37+
--model "$GENERATOR_MODEL" --env-file "$EVOT_ENV_FILE" \
38+
--max-turns 30 --max-duration 600 || true
39+
40+
if git diff --quiet; then
41+
echo "No changes"
42+
cleanup_on_failure
43+
exit 0
44+
fi
45+
46+
# Step 2: Review loop (max 2 rounds)
47+
APPROVED=false
48+
for round in 1 2; do
49+
DIFF=$(git diff)
50+
[ -z "$DIFF" ] && { APPROVED=true; break; }
51+
52+
REVIEW=$(evot -p "Review this diff for issue #${NUM}: ${TITLE}
53+
${BODY}
54+
55+
Respond ONLY with JSON: {\"approved\": bool, \"comments\": \"...\"}
56+
57+
${DIFF}" \
58+
--model "$REVIEWER_MODEL" --env-file "$EVOT_ENV_FILE" \
59+
--max-turns 1 --max-duration 60 2>&1 || true)
60+
61+
if echo "$REVIEW" | grep -q '"approved"[[:space:]]*:[[:space:]]*true'; then
62+
APPROVED=true; break
63+
fi
64+
65+
COMMENTS=$(echo "$REVIEW" | python3 -c "
66+
import sys,json,re
67+
t=sys.stdin.read(); m=re.search(r'\{[^}]*\}',t,re.DOTALL)
68+
try: print(json.loads(m.group())['comments']) if m else print(t[:500])
69+
except: print(t[:500])" 2>/dev/null || echo "$REVIEW" | head -10)
70+
71+
evot -p "Address this review for issue #${NUM}:
72+
${COMMENTS}" \
73+
--model "$GENERATOR_MODEL" --env-file "$EVOT_ENV_FILE" \
74+
--max-turns 20 --max-duration 300 || true
75+
done
76+
77+
# Step 3: PR
78+
git add -A
79+
git commit -m "docs: auto-fix #${NUM}" || { cleanup_on_failure; exit 0; }
80+
git push origin "$BRANCH" --force
81+
82+
STATUS=$( [ "$APPROVED" = true ] && echo "✅ Approved" || echo "⚠️ Needs human review" )
83+
gh pr create --repo "$REPO" --base "$MAIN" --head "$BRANCH" \
84+
--title "docs: auto-fix #${NUM}" \
85+
--body "Fixes #${NUM}. ${STATUS}
86+
Generated by \`${GENERATOR_MODEL}\`, reviewed by \`${REVIEWER_MODEL}\`." \
87+
--label auto-fix || true
88+
89+
# Mark done
90+
gh issue edit "$NUM" --repo "$REPO" --add-label auto-fix-done --remove-label auto-fix-in-progress
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
name: Auto Fix Issues
2+
on:
3+
schedule:
4+
- cron: '*/10 * * * *'
5+
workflow_dispatch:
6+
inputs:
7+
issue_number:
8+
description: 'Issue number (empty = pick oldest)'
9+
required: false
10+
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
issues: write
15+
16+
jobs:
17+
check:
18+
runs-on: ubuntu-latest
19+
outputs:
20+
issue: ${{ steps.pick.outputs.issue }}
21+
steps:
22+
- id: pick
23+
env:
24+
GH_TOKEN: ${{ secrets.GH_PAT }}
25+
ISSUE_NUMBER: ${{ inputs.issue_number || '' }}
26+
run: |
27+
REPO="${{ github.repository }}"
28+
if [ -n "$ISSUE_NUMBER" ]; then
29+
ISSUE=$(gh issue view "$ISSUE_NUMBER" --repo "$REPO" --json number,title,body -q '.')
30+
else
31+
ISSUE=$(gh issue list --repo "$REPO" --label auto-fix --state open --limit 1 --json number,title,body -q '.[0] // empty')
32+
fi
33+
if [ -z "$ISSUE" ]; then
34+
echo "No auto-fix issues"
35+
echo "issue=" >> "$GITHUB_OUTPUT"
36+
else
37+
NUM=$(echo "$ISSUE" | jq -r '.number')
38+
gh issue edit "$NUM" --repo "$REPO" --add-label auto-fix-in-progress --remove-label auto-fix
39+
echo "issue=$(echo "$ISSUE" | jq -c .)" >> "$GITHUB_OUTPUT"
40+
fi
41+
42+
fix:
43+
needs: check
44+
if: needs.check.outputs.issue != ''
45+
runs-on: ubuntu-latest
46+
steps:
47+
- uses: actions/checkout@v4
48+
49+
- name: Checkout databend source
50+
uses: actions/checkout@v4
51+
with:
52+
repository: databendlabs/databend
53+
path: _databend
54+
sparse-checkout: src
55+
fetch-depth: 1
56+
57+
- name: Install evot
58+
env:
59+
GH_TOKEN: ${{ secrets.GH_PAT }}
60+
run: |
61+
TAG=$(gh release list --repo evotai/evot --limit 1 --json tagName --jq '.[0].tagName')
62+
gh release download "$TAG" --repo evotai/evot --pattern "evot-*-x86_64-unknown-linux-gnu.tar.gz"
63+
tar -xzf evot-*.tar.gz && chmod +x bin/evot
64+
echo "$PWD/bin" >> "$GITHUB_PATH"
65+
66+
- name: Write evot.env
67+
run: |
68+
cat > /tmp/evot.env << EOF
69+
EVOT_LLM_PROVIDER=${{ secrets.EVOT_LLM_PROVIDER }}
70+
EVOT_LLM_ANTHROPIC_BASE_URL=${{ secrets.EVOT_LLM_ANTHROPIC_BASE_URL }}
71+
EVOT_LLM_ANTHROPIC_API_KEY=${{ secrets.EVOT_LLM_ANTHROPIC_API_KEY }}
72+
EVOT_LLM_ANTHROPIC_MODEL=${{ secrets.EVOT_LLM_ANTHROPIC_MODEL }}
73+
EVOT_LLM_OPENAI_BASE_URL=${{ secrets.EVOT_LLM_OPENAI_BASE_URL }}
74+
EVOT_LLM_OPENAI_API_KEY=${{ secrets.EVOT_LLM_OPENAI_API_KEY }}
75+
EVOT_LLM_OPENAI_MODEL=${{ secrets.EVOT_LLM_OPENAI_MODEL }}
76+
EOF
77+
78+
- name: Run
79+
run: |
80+
git config user.name "github-actions[bot]"
81+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
82+
bash .github/scripts/auto-fix.sh
83+
env:
84+
REPO: ${{ github.repository }}
85+
ISSUE_JSON: ${{ needs.check.outputs.issue }}
86+
GENERATOR_MODEL: anthropic
87+
REVIEWER_MODEL: openai
88+
EVOT_ENV_FILE: /tmp/evot.env
89+
EVOT_ID: auto-fix-ci
90+
GH_TOKEN: ${{ secrets.GH_PAT }}

0 commit comments

Comments
 (0)