Skip to content

Commit 5b03cba

Browse files
authored
AI Code-review (#4542)
1 parent fcbab6e commit 5b03cba

1 file changed

Lines changed: 97 additions & 0 deletions

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
name: Claude Code Review
2+
3+
concurrency:
4+
group: ${{ github.workflow }}-${{ github.ref }}
5+
cancel-in-progress: true
6+
7+
on:
8+
pull_request:
9+
types: [opened, synchronize]
10+
11+
jobs:
12+
code-review:
13+
runs-on: ubuntu-latest
14+
timeout-minutes: 30
15+
permissions:
16+
contents: write
17+
pull-requests: write
18+
issues: write
19+
id-token: write
20+
actions: read
21+
steps:
22+
- name: Checkout repository
23+
uses: actions/checkout@v4
24+
with:
25+
fetch-depth: 1
26+
- name: Dismiss old Claude bot comments
27+
env:
28+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
run: |
30+
# Get PR comments from claude[bot] and hide them as outdated
31+
REPO="${{ github.repository }}"
32+
PR_NUMBER="${{ github.event.pull_request.number }}"
33+
34+
# Get review comments (PR review comments)
35+
gh api "repos/$REPO/issues/$PR_NUMBER/comments" --jq '.[] | select(.user.login == "claude[bot]") | .node_id' | while read -r comment_node_id; do
36+
if [ -n "$comment_node_id" ]; then
37+
echo "Hiding review comment: $comment_node_id"
38+
gh api graphql -f query='
39+
mutation($id: ID!) {
40+
minimizeComment(input: {subjectId: $id, classifier: OUTDATED}) {
41+
minimizedComment {
42+
isMinimized
43+
}
44+
}
45+
}' -f id="$comment_node_id"
46+
fi
47+
done
48+
- name: Review code
49+
uses: anthropics/claude-code-action@v1
50+
with:
51+
claude_code_oauth_token: ${{ secrets.CLAUDE_OAUTH_TOKEN }}
52+
prompt: |
53+
REPO: ${{ github.repository }}
54+
PR NUMBER: ${{ github.event.pull_request.number }}
55+
56+
Review this pull request and provide feedback.
57+
Post your feedback as a PR comment using `gh pr comment`.
58+
59+
When reviewing code, leave a general summary of the changes at the top of your comment and then evaluate the following areas:
60+
61+
### Architecture & Design
62+
63+
- Separation of concerns: Does the code properly separate layers (views, services, models, serializers)? Watch for business logic leaking into views or serializers.
64+
- Single responsibility: Do classes and functions have one clear purpose, or are they doing too much?
65+
- Code patterns: Are there opportunities to use established patterns (e.g., service objects, query objects, mixins) that would improve readability?
66+
- Dependencies: Does the code introduce tight coupling between modules that should be independent?
67+
- Abstraction level: Is code at the right level of abstraction? Avoid both over-engineering and under-abstraction.
68+
69+
### Testing & Coverage
70+
71+
- Critical path coverage: Are the main success and failure paths tested?
72+
- Edge cases: Are boundary conditions and error scenarios covered?
73+
- Multi-tenant security: Every query involving user data MUST be scoped to the current tenant/business. Look for:
74+
- Missing `.filter(business=...)` or similar tenant scoping
75+
- Direct object lookups without ownership verification (e.g., `Model.objects.get(id=id)` without checking the user has access)
76+
- Bulk operations that could affect other tenants' data
77+
- Test isolation: Are they independent of execution order?
78+
- Mocking boundaries: Are external services and I/O properly mocked?
79+
80+
### Error Handling
81+
82+
- Explicit error handling: Are exceptions caught and handled appropriately, or do they bubble up unexpectedly?
83+
- User-facing errors: Do error messages make sense to users without leaking internal details?
84+
- Transactional integrity: Are database operations wrapped in transactions where needed to prevent partial updates?
85+
- Graceful degradation: Does the code fail gracefully when external services are unavailable?
86+
87+
### Performance
88+
89+
- N+1 queries: Look for loops that trigger database queries. Use `select_related()` and `prefetch_related()`.
90+
- Missing indexes: Will new query patterns require database indexes?
91+
- Pagination: Are list endpoints paginated to prevent loading unbounded data?
92+
- Caching opportunities: Could frequently-accessed, rarely-changed data benefit from caching?
93+
- Bulk operations: Are there loops doing individual saves that could use `bulk_create()` or `bulk_update()`?
94+
95+
Use the repository's CLAUDE.md for guidance on style and conventions.
96+
Be constructive, helpful, concise and to the point in your feedback.
97+
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'

0 commit comments

Comments
 (0)