Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions ai-review/ai_review_publish.sh
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,19 @@ apply_fixes() {

remote="https://x-access-token:${PUSH_TOKEN:-}@github.com/${GITHUB_REPOSITORY}.git"

# Describes the fix PR: each fix commit's subject and the fixes its message lists (apply_fixes
# already checked the messages for secrets). Comment openers are escaped so nothing in the agents'
# text is hidden from the reader, and it stays under GitHub's limit.
fix_pr_body() {
local commit body
body="Fixes from the AI review of #${PR_NUMBER} at ${HEAD_SHA}. Merge this PR to apply them to \`${HEAD_REF}\`; the full review summary is on #${PR_NUMBER}."$'\n\n'"### What changed"$'\n'
for commit in $(git rev-list --reverse "$HEAD_SHA..HEAD"); do
body+=$'\n'"$(git log -1 --format='**%s**' "$commit")"$'\n'
body+="$(git log -1 --format=%b "$commit" | grep '^- ' || true)"$'\n'
done
printf '%s' "${body:0:60000}" | sed 's/<!--/\&lt;!--/g'
}

# Pushes the fixes to a branch of their own and opens a PR from it into HEAD_REF; prints what it
# did, or why it failed. The PR is opened with PUSH_TOKEN: one opened with GITHUB_TOKEN would start
# neither CI nor the Malicious Code Scan.
Expand All @@ -129,9 +142,7 @@ open_fix_pr() {
export GH_TOKEN="$PUSH_TOKEN"
url="$(gh pr list --repo "$GITHUB_REPOSITORY" --head "$branch" --state open --json url --jq '.[0].url // empty' 2> /dev/null || true)"
if [[ -z "$url" ]]; then
body="$(printf '%s\n' \
"Fixes from the AI review of #${PR_NUMBER} at ${HEAD_SHA}. Merge this PR to apply them to \`${HEAD_REF}\`; the review summary is on #${PR_NUMBER}." \
"" "$(git log --reverse --format='- %s' "$HEAD_SHA..HEAD")")"
body="$(fix_pr_body)"
if ! url="$(gh pr create --repo "$GITHUB_REPOSITORY" --base "$HEAD_REF" --head "$branch" \
--title "AI review fixes for #${PR_NUMBER}" --body "$body" 2> /dev/null | tail -n 1)" || [[ -z "$url" ]]; then
echo "the fix PR from $branch could not be opened (does AI_REVIEW_PUSH_TOKEN have pull-requests:write?)"
Expand Down
12 changes: 11 additions & 1 deletion tests/test_ai_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,11 @@ def test_publish_opens_a_fix_pr_by_default(self):
{"number": 8, "headRefName": "ai-review/pr-12-100"},
{"number": 9, "headRefName": "other"},
]
self.fix_patches(git, head, ["echo fixed >> feature.py"])
message = (
"fix(review): apply Claude review fixes (turn 1)\n\n- feature.py:1 - <!-- hidden --> printed the wrong value\n\n"
"AI-Review-Bot: true\nAI-Review-Run: 456"
)
self.fix_patches(git, head, ["echo fixed >> feature.py"], message=message)
body = "## AI adversarial review\n\n### Turn 1: Claude (commit abc1234)\n"
run, status, comment, pushed = self.publish(repository, remote, head, body=body, mode="pull_request")
self.assertEqual(run.returncode, 0, run.stderr)
Expand All @@ -728,6 +732,12 @@ def test_publish_opens_a_fix_pr_by_default(self):
create = next(call for call in calls if call[1] == "create")
self.assertEqual(create[create.index("--base") + 1], "feature")
self.assertEqual(create[create.index("--head") + 1], "ai-review/pr-1-123")
# The fix PR describes its changes rather than only pointing back at the reviewed PR
pr_body = create[create.index("--body") + 1]
self.assertIn("### What changed", pr_body)
self.assertIn("**fix(review): apply Claude review fixes (turn 1)**", pr_body)
self.assertIn("- feature.py:1 - &lt;!-- hidden --> printed the wrong value", pr_body)
self.assertNotIn("AI-Review-Bot", pr_body)
# Only the superseded fix PR of this PR is closed
self.assertEqual([call[2] for call in calls if call[1] == "close"], ["7"])
# The author is asked to review it
Expand Down
Loading