Skip to content

Commit cba09f9

Browse files
authored
Added AI PR review (#211)
1 parent c164e52 commit cba09f9

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed

.github/workflows/ai-pr-review.yml

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
name: AI PR Review (Incremental)
2+
3+
on:
4+
pull_request_target:
5+
types: [opened, synchronize, reopened]
6+
7+
permissions:
8+
contents: read
9+
pull-requests: write
10+
11+
jobs:
12+
ai-review:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout repo
17+
uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0
20+
21+
- name: Install dependencies
22+
run: |
23+
pip install requests jq
24+
25+
- name: Get incremental diff
26+
id: diff
27+
run: |
28+
BASE_SHA="${{ github.event.pull_request.base.sha }}"
29+
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
30+
git diff $BASE_SHA...$HEAD_SHA > pr.diff
31+
32+
if [ ! -s pr.diff ]; then
33+
echo "EMPTY_DIFF=true" >> $GITHUB_ENV
34+
fi
35+
36+
- name: Run OpenAI review
37+
if: env.EMPTY_DIFF != 'true'
38+
run: |
39+
python3 << 'EOF'
40+
import os, json, requests
41+
42+
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
43+
DIFF = open("pr.diff").read()[:15000]
44+
45+
prompt = f"""
46+
Review this incremental pull request diff.
47+
48+
Tasks:
49+
1. Write a concise PR summary (overall risks, design issues).
50+
2. Provide inline review comments with:
51+
- file
52+
- line
53+
- comment
54+
55+
Respond ONLY in valid JSON with this schema:
56+
{{
57+
"summary": "string",
58+
"comments": [
59+
{{
60+
"file": "path/to/file",
61+
"line": 123,
62+
"comment": "text"
63+
}}
64+
]
65+
}}
66+
67+
Diff:
68+
{DIFF}
69+
"""
70+
71+
response = requests.post(
72+
"https://api.openai.com/v1/responses",
73+
headers={
74+
"Authorization": f"Bearer {OPENAI_API_KEY}",
75+
"Content-Type": "application/json"
76+
},
77+
json={
78+
"model": "gpt-4.1-mini",
79+
"input": prompt,
80+
"temperature": 0.2
81+
}
82+
)
83+
84+
data = response.json()
85+
text = data["output"][0]["content"][0]["text"]
86+
87+
parsed = json.loads(text)
88+
with open("ai_output.json", "w") as f:
89+
json.dump(parsed, f, indent=2)
90+
EOF
91+
env:
92+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
93+
94+
- name: Post PR summary comment
95+
if: env.EMPTY_DIFF != 'true'
96+
run: |
97+
SUMMARY=$(jq -r '.summary' ai_output.json)
98+
gh pr comment ${{ github.event.pull_request.number }} \
99+
--body "## 🤖 AI PR Review Summary\n\n$SUMMARY"
100+
env:
101+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
102+
103+
- name: Post inline review comments
104+
if: env.EMPTY_DIFF != 'true'
105+
run: |
106+
jq -c '.comments[]' ai_output.json | while read c; do
107+
FILE=$(echo $c | jq -r '.file')
108+
LINE=$(echo $c | jq -r '.line')
109+
COMMENT=$(echo $c | jq -r '.comment')
110+
111+
gh api \
112+
repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/comments \
113+
-f body="$COMMENT" \
114+
-f commit_id="${{ github.event.pull_request.head.sha }}" \
115+
-f path="$FILE" \
116+
-f line="$LINE" \
117+
-f side="RIGHT"
118+
done
119+
env:
120+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)