Skip to content
Open
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
90 changes: 90 additions & 0 deletions .github/workflows/pr-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# GitHub Action: Automated PR Review
# Triggers on pull request events and posts a structured review comment.
#
# Usage: Copy this file to your repo's .github/workflows/ directory.
# Set GITHUB_TOKEN (automatic) or a PAT with repo scope for cross-repo reviews.

name: PR Review Agent

on:
pull_request:
types: [opened, synchronize]

permissions:
contents: read
pull-requests: write

jobs:
review:
runs-on: ubuntu-latest
name: Automated PR Review
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Fetch PR diff
id: diff
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_URL="${{ github.event.pull_request.html_url }}"
echo "pr_url=${PR_URL}" >> $GITHUB_OUTPUT

# Fetch diff via GitHub API
curl -s -H "Authorization: token ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github.v3.diff" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}" \
> /tmp/pr.diff

echo "Diff saved: $(wc -l < /tmp/pr.diff) lines"

- name: Generate review
id: review
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python3 ${{ github.workspace }}/claude_review.py \
--pr "${{ steps.diff.outputs.pr_url }}" \
--output /tmp/review.md

# Store review content for the comment step
cat /tmp/review.md >> $GITHUB_OUTPUT

- name: Post review comment
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const review = fs.readFileSync('/tmp/review.md', 'utf8');

// Find existing bot comment to update
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});

const botComment = comments.find(c =>
c.user.type === 'Bot' && c.body.includes('Automated PR Review')
);

if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: review,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: review,
});
}
172 changes: 172 additions & 0 deletions agents/pr-reviewer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# πŸ€– claude-review β€” Automated PR Review Agent

A CLI tool and GitHub Action that analyzes GitHub Pull Requests and generates structured Markdown review reports.

> **$150 Bounty Submission** β€” [Issue #4](https://github.com/claude-builders-bounty/claude-builders-bounty/issues/4)

## Features

- πŸ” **CLI tool** β€” Review any GitHub PR from the command line
- πŸ€– **GitHub Action** β€” Auto-review PRs on every push
- πŸ“‹ **Structured output** β€” Summary, risks, suggestions, confidence score
- πŸš€ **Zero dependencies** β€” Pure Python standard library
- πŸ”’ **Security detection** β€” Flags common vulnerabilities in diffs

## Quick Start

### CLI Usage

```bash
# Install (no pip needed β€” single file)
git clone https://github.com/zlplzp123wyt/claude-builders-bounty
cd claude-builders-bounty
pip install -e . # or just run python3 claude_review.py directly

# Review a PR
claude-review --pr https://github.com/psf/requests/pull/7310

# Save to file
claude-review --pr https://github.com/owner/repo/pull/42 -o review.md

# JSON output
claude-review --pr https://github.com/owner/repo/pull/42 --json

# Read diff from stdin
git diff | claude-review --stdin --pr https://github.com/owner/repo/pull/42
```

### Environment Variables

| Variable | Description |
|----------|-------------|
| `GITHUB_TOKEN` | GitHub personal access token (optional, increases rate limits) |

```bash
export GITHUB_TOKEN=ghp_xxxxxxxxxxxx
claude-review --pr https://github.com/owner/repo/pull/42
```

### GitHub Action

Add this workflow to your repository (`.github/workflows/pr-review.yml`):

```yaml
name: PR Review Agent

on:
pull_request:
types: [opened, synchronize]

permissions:
contents: read
pull-requests: write

jobs:
review:
runs-on: ubuntu-latest
name: Automated PR Review
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Generate review
id: review
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python3 ${{ github.workspace }}/claude_review.py \
--pr "${{ github.event.pull_request.html_url }}" \
--output /tmp/review.md

- name: Post review comment
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const review = fs.readFileSync('/tmp/review.md', 'utf8');
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner, repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(c =>
c.user.type === 'Bot' && c.body.includes('Automated PR Review')
);
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner, repo: context.repo.repo,
comment_id: botComment.id, body: review,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner, repo: context.repo.repo,
issue_number: context.issue.number, body: review,
});
}
```

## Output Format

Each review includes:

### πŸ“‹ Summary of Changes
2–3 sentence overview: PR title, author, files changed, line counts, and purpose.

### ⚠️ Identified Risks
- πŸ”’ Security risks (hardcoded secrets, eval/exec, SQL injection, XSS)
- πŸ“ Large PR warnings (>500 lines)
- πŸ§ͺ Missing test coverage
- πŸ“¦ Dependency changes
- βš™οΈ Configuration/deployment changes
- πŸ—‘οΈ Removed tests
- ⚠️ TODO/FIXME markers

### πŸ’‘ Improvement Suggestions
- Debug statement removal
- Bare except clause warnings
- Magic number extraction
- Missing comments on complex code
- Documentation updates

### πŸ“Š Confidence Score
- 🟒 **High** β€” Small, well-scoped changes
- 🟑 **Medium** β€” Moderate complexity, manual review recommended
- πŸ”΄ **Low** β€” High complexity/risk, thorough review needed

## Sample Output

See [`examples/`](examples/) for real-world review outputs:

- **sample_review_1.md** β€” [psf/requests#7310](https://github.com/psf/requests/pull/7310) (DigestAuth FIPS fix)
- **sample_review_2.md** β€” [fastapi/fastapi#15263](https://github.com/fastapi/fastapi/pull/15263) (pygments bump)

## CLI Arguments

| Argument | Description |
|----------|-------------|
| `--pr URL` | GitHub PR URL (required) |
| `-o`, `--output FILE` | Output file path (default: stdout) |
| `--json` | Output as JSON instead of Markdown |
| `--stdin` | Read diff from stdin instead of fetching |
| `--token TOKEN` | GitHub token (or use `GITHUB_TOKEN` env) |

## How It Works

1. **Parse** the GitHub PR URL to extract owner, repo, and PR number
2. **Fetch** the PR diff and metadata via GitHub API
3. **Analyze** the diff for security issues, size, test coverage, patterns
4. **Generate** a structured Markdown report with summary, risks, suggestions, and confidence

## Requirements

- Python 3.8+
- Internet access (to fetch PRs from GitHub API)
- No external dependencies

## License

MIT
Loading
Loading