name: Claude Code Review
on:
pull_request:
types: [opened] # Only run when PR is first created, not on every commit
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
# - "src/**/*.tsx"
# - "src/**/*.js"
# - "src/**/*.jsx"
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to review'
required: true
type: number
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.inputs.pr_number }}
cancel-in-progress: true
jobs:
claude-review:
# For automatic runs: only allow members/collaborators/owners
# For manual runs: always allow (since only repo members can trigger workflows)
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' &&
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'),
github.event.pull_request.author_association))
runs-on:
group: neondatabase-protected-runner-group
labels: linux-ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/pull/{0}/head', github.event.inputs.pr_number) || '' }}
- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
prompt: |
# Code Review Task
**REPO:** ${{ github.repository }}
**PR:** ${{ github.event.pull_request.number || github.event.inputs.pr_number }}
**COMMIT:** ${{ github.event.pull_request.head.sha }}
## Context
This is the **Neon MCP Server** - a Model Context Protocol server bridging LLMs to Neon Postgres API.
The main codebase is in the `landing/` directory using Next.js App Router with Vercel serverless deployment.
Review this PR with understanding of:
- MCP tool/handler architecture in `landing/mcp-src/` (see CLAUDE.md)
- Next.js App Router API routes for OAuth and MCP transport
- TypeScript with bundler module resolution
- Tool registration pattern: definitions.ts → toolsSchema.ts → handlers/ → tools.ts
- Multi-call state management for migrations/tuning tools
## What's Already Automated (Don't Review)
- ❌ Lint errors → `bun run lint` (automated by pr.yml)
- ❌ Build failures → `bun run build` (automated by pr.yml)
- ❌ Formatting issues → Automated
## Focus Your Review On (Significant Issues Only)
1. **Architecture & Design**
- Does new tool follow the tool registration pattern?
- Is handler properly typed in NEON_HANDLERS?
- Are Zod schemas correctly defined in toolsSchema.ts?
2. **Security Vulnerabilities**
- SQL injection risks (tool handlers using raw SQL)
- Secrets exposure (API keys, tokens logged or returned)
- Input validation gaps (Zod schema completeness)
- Command injection in bash tool uses
3. **Logic Bugs**
- Error handling gaps (unhandled promise rejections)
- State management issues (branch ID tracking for multi-call tools)
- Edge cases not covered (null/undefined handling)
4. **Performance Issues**
- N+1 API call patterns
- Inefficient Neon API usage
- Missing pagination handling
- Unnecessary data fetching
5. **Testing Gaps**
- Missing Braintrust evaluations for new tools
- Uncovered edge cases in existing tests
- Integration test scenarios missing
6. **MCP-Specific Issues**
- Tool descriptions not clear for LLMs
- Missing analytics tracking (trackEvent calls)
- Error handling doesn't use ToolError pattern
- Missing Sentry error capture
## Review Instructions
### Step 1: Analyze the PR
Use `gh pr view` and `gh pr diff` to understand the changes.
### Step 2: Identify Significant Issues
- Read the full diff and changed files
- For each significant issue, note: file path, line number, severity, description
- Only flag issues a human reviewer would care about (not lint/format)
### Step 3: Post Inline Comments
For each significant issue (max 5 per file), post an inline comment using:
```bash
gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number || github.event.inputs.pr_number }}/comments -f body=$'COMMENT_BODY' -f path="relative/path/to/file.ts" -F line=42 -f side="RIGHT" -f commit_id="${{ github.event.pull_request.head.sha || github.sha }}"
```
**IMPORTANT:**
- Use a SINGLE LINE command (no backslashes or line continuations)
- For this PR, use: `gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number || github.event.inputs.pr_number }}/comments`
- Commit SHA: `${{ github.event.pull_request.head.sha || github.sha }}`
- Post comments for EVERY significant issue you find (not just a summary)
- Use $'...' (ANSI-C quoting) for body parameter so \n becomes actual newlines
**Inline Comment Format:**
- Use emoji severity: 🔴 Critical | 🟡 Important | 🔵 Consider
- Start with **[Category]** (Security/Logic/Performance/Architecture/Testing)
- Explain the issue clearly
- Provide actionable fix or suggestion
- Reference CLAUDE.md patterns when applicable
**Example:**
```bash
gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number || github.event.inputs.pr_number }}/comments -f body=$'🔴 **[Security]**: Potential SQL injection vulnerability.\n\n**Fix:** Use parameterized queries:\n```typescript\nconst result = await query(\'SELECT * FROM users WHERE name = $1\', [userName]);\n```' -f path="landing/mcp-src/tools/handlers/run-sql.ts" -F line=42 -f side="RIGHT" -f commit_id="${{ github.event.pull_request.head.sha || github.sha }}"
```
Note: The $'...' syntax is bash ANSI-C quoting which interprets \n as actual newlines. Use \' to escape single quotes within the body.
### Step 4: Post Summary Comment
After posting inline comments, create a summary with:
- Review statistics (files, lines, issues)
- Severity breakdown (🔴, 🟡, 🔵 counts)
- Key findings (2-3 most critical issues)
- What looks good (2-3 positive aspects)
- Note that lint/build are automated
Use `gh pr comment` to post the summary.
## Guidelines
- **Be selective**: Only comment on significant issues worth a human's attention
- **Be specific**: Reference exact lines, provide clear fixes
- **Be constructive**: Explain the "why" behind suggestions
- **Be project-aware**: Use CLAUDE.md patterns and terminology
- **Don't duplicate**: Skip issues automated tools will catch
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
claude_args: '--allowed-tools "Bash(gh:*)"'