Skip to content

Commit 4632132

Browse files
committed
feat: add Automated Code Review workflow
Setup a read-only code review pipeline using the google-antigravity SDK and GitHub Actions. The workflow runs on pull_request and triggers on maintainer PR opens or /review comments. It runs the review-pr skill to evaluate code quality, correctness, and architecture, outputting findings as GHA warning annotations.
1 parent b5d754e commit 4632132

4 files changed

Lines changed: 164 additions & 0 deletions

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Automated Code Review
2+
3+
# TODO: Eventually, use pull_request_target instead of pull_request.
4+
# pull_request_target runs in the base branch context and has access
5+
# to secrets (like GEMINI_API_KEY) even for fork PRs.
6+
# Using pull_request for now during setup/testing.
7+
on:
8+
pull_request:
9+
types: [opened]
10+
pull_request_review_comment:
11+
types: [created]
12+
13+
permissions:
14+
contents: read
15+
pull-requests: read
16+
17+
jobs:
18+
review:
19+
runs-on: ubuntu-latest
20+
# Trigger only if:
21+
# 1. It is a pull_request event, it is NOT a draft, and the author is a maintainer
22+
# (OWNER, MEMBER, or COLLABORATOR).
23+
# 2. OR it is a pull_request_review_comment event, the comment body has a line starting with "/review",
24+
# and the commenter is a maintainer.
25+
if: >
26+
(github.event_name == 'pull_request' && !github.event.pull_request.draft &&
27+
contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.pull_request.author_association)) ||
28+
(github.event_name == 'pull_request_review_comment' &&
29+
(startsWith(github.event.comment.body, '/review') || contains(github.event.comment.body, '\n/review')) &&
30+
contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association))
31+
steps:
32+
- name: Checkout PR Branch
33+
uses: actions/checkout@v7
34+
with:
35+
ref: ${{ github.event.pull_request.head.sha }}
36+
persist-credentials: false
37+
38+
- name: Checkout Reviewbot (Base Branch)
39+
uses: actions/checkout@v7
40+
with:
41+
sparse-checkout: |
42+
tools/private/reviewbot
43+
path: reviewbot
44+
45+
- name: Install uv
46+
uses: astral-sh/setup-uv@v8.3.0
47+
48+
- name: Set up Python
49+
run: uv python install 3.13
50+
51+
- name: Install Dependencies
52+
run: |
53+
uv pip install google-antigravity requests
54+
55+
- name: Run Antigravity Review
56+
env:
57+
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
58+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
59+
run: |
60+
uv run reviewbot/tools/private/reviewbot/antigravity_review.py \
61+
--prompt reviewbot/tools/private/reviewbot/prompt.txt
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import argparse
2+
import asyncio
3+
from pathlib import Path
4+
5+
from google.antigravity import Agent, CapabilitiesConfig, LocalAgentConfig
6+
7+
8+
def parse_args():
9+
parser = argparse.ArgumentParser()
10+
parser.add_argument("--prompt", required=True, help="Path to prompt file")
11+
return parser.parse_args()
12+
13+
14+
async def main():
15+
args = parse_args()
16+
17+
# Read prompt file
18+
prompt = Path(args.prompt).read_text()
19+
20+
# Initialize the Antigravity Agent in read-only mode for security.
21+
# Register the review-pr skill from the local reviewbot folder.
22+
config = LocalAgentConfig(
23+
skills_paths=["tools/private/reviewbot/skills/review-pr"],
24+
capabilities=CapabilitiesConfig(
25+
allow_filesystem_read=True,
26+
allow_filesystem_write=False,
27+
allow_network=False,
28+
),
29+
)
30+
31+
# General coordinator instructions for the reviewer agent.
32+
system_instructions = (
33+
"You are a code review assistant. Use your available skills to perform "
34+
"reviews on pull requests."
35+
)
36+
37+
async with Agent(config, system_instructions=system_instructions) as agent:
38+
response = await agent.chat(prompt)
39+
report = await response.text()
40+
41+
print("--- REVIEW REPORT GENERATED ---")
42+
print(report)
43+
44+
# TODO: Use GITHUB_TOKEN to post the report back to the PR comments.
45+
46+
47+
if __name__ == "__main__":
48+
asyncio.run(main())

tools/private/reviewbot/prompt.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Use the review-pr skill to review the files modified in this pull request.
2+
Summarize your findings and suggest specific, actionable improvements.
3+
Group your findings into clear, descriptive nits or suggestions.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
name: review-pr
3+
description: Perform a read-only code review on a pull request.
4+
---
5+
6+
# review-pr
7+
8+
You are an expert Starlark, Python, and Bazel code reviewer. Analyze the changed files for
9+
correctness, edge cases, and performance. Focus strictly on logical
10+
correctness, concurrency safety, system architecture, performance bottlenecks,
11+
and resource management. Do not comment on style nits or formatting issues
12+
that an automated formatter can handle. Be constructive and concise.
13+
14+
For every issue or improvement you identify, you MUST output the finding in the
15+
GitHub Actions workflow command warning format. Specify the exact file path
16+
and line numbers that the comment applies to.
17+
18+
Format each finding exactly as a single line to stdout matching this template:
19+
`::warning file={file_path},line={line_number},endLine={end_line},title={category}::{comment_body}`
20+
21+
Where:
22+
* `file_path` is the relative file path from the repository root.
23+
* `line_number` is the starting line number in the file where the comment applies.
24+
* `end_line` is the ending line number in the file where the comment applies (equal to line_number if the issue is on a single line).
25+
* `category` is a short tag for the type of issue (e.g., "Error Handling", "Correctness", "Performance").
26+
* `comment_body` is your constructive and concise feedback.
27+
28+
Do not write any markdown commentary outside of these GHA command formatted lines.
29+
30+
Follow these checklists during your review:
31+
32+
### General Quality & Architecture Checklist
33+
* **PR Description Audit**: Verify the description contains the Why
34+
(business/technical reason), a brief high level overview of changes,
35+
Issue/Bug Link, and explicit Testing Evidence.
36+
* **Separation of Concerns**: Suggest extracting large hardcoded data structures
37+
(e.g., massive templates, complex regexes) to resource files.
38+
* **Logic Correctness**: Verify calculations, negative values, division-by-zero,
39+
and null safety before member access.
40+
* **Error Handling**: Flag silent failures (e.g., empty except blocks) and
41+
unconditional defaults that override configs.
42+
* **Deterministic Operations**: Sort collections/keys to guarantee
43+
reproducible/deterministic execution.
44+
45+
### Skeptical Critic (Adversarial Specialist Review)
46+
* **Dynamic Filtering**: Filter the PR diff and run only the specialist checks
47+
that have relevant files changed (e.g. skip the C++ checks if only Python
48+
files are modified).
49+
* **Specialist Review Pillars**: Run parallel audits focusing on:
50+
1. Crash Regression: Null safety and resource lifecycle.
51+
2. Performance & Latency: Thread bottlenecks, locks, and network calls.
52+
3. Test Integrity: Coverage validity, change detectors defense.

0 commit comments

Comments
 (0)