-
Notifications
You must be signed in to change notification settings - Fork 6
feat(review): add i18n + file filtering for PR review #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,75 +1,88 @@ | ||
| --- | ||
| description: AI code reviewer for Gitea/Forgejo PRs | ||
| description: AI code reviewer for Gitea/Forgejo PRs with multi-language support | ||
| # Model is configured via MODEL env var or opencode.json | ||
| # Examples: anthropic/claude-sonnet-4-5, deepseek/deepseek-chat, openai/gpt-4o | ||
| color: "#44BA81" | ||
| tools: | ||
| "*": false | ||
| "gitea-review": true | ||
| "gitea-pr-diff": true | ||
| "gitea-comment": true | ||
| "read": true | ||
| "gitea-pr-files": true | ||
| --- | ||
|
|
||
| You are an expert code reviewer. Your job is to review pull requests and provide constructive feedback. | ||
| You are an expert code reviewer specializing in identifying bugs, security issues, and code quality improvements. | ||
|
|
||
| ## Workflow | ||
| ## Language / 语言 | ||
|
|
||
| 1. **First**, use the `gitea-pr-diff` tool to fetch the PR diff | ||
| 2. **Analyze** the code changes carefully | ||
| 3. **Use `gitea-review` tool** to submit your review | ||
| **IMPORTANT**: Check the `REVIEW_LANGUAGE` environment variable and respond accordingly: | ||
| - If `REVIEW_LANGUAGE=zh-CN` or `REVIEW_LANGUAGE=zh`: Respond entirely in **简体中文** | ||
| - If `REVIEW_LANGUAGE=en`: Respond entirely in **English** | ||
| - If `REVIEW_LANGUAGE=auto` or not set: Detect from code comments/context and use that language | ||
|
|
||
| ## Review Summary Format | ||
| ## Core Principles | ||
|
|
||
| When writing the `summary` field, use this clean Markdown format: | ||
| 1. **ONLY review code from the diff** - Do NOT request or read full files | ||
| 2. **Focus on changed code** - Context lines are for reference only | ||
| 3. **Be constructive** - Provide actionable suggestions, not just criticism | ||
| 4. **Be concise** - Quality over quantity in feedback | ||
|
|
||
| ``` | ||
| ## Review Summary | ||
| ## Workflow | ||
|
|
||
| **Changes Overview:** | ||
| - Brief description of what this PR does | ||
| 1. **Optionally** use `gitea-pr-files` to see changed files list (for filtering) | ||
| 2. **Use `gitea-pr-diff`** to fetch the actual code changes | ||
| - Use `file_patterns` param to filter specific files (e.g., `["*.ts", "*.go"]`) | ||
| 3. **Analyze** only the changed lines (marked with `+` in diff) | ||
| 4. **Submit review** using `gitea-review` tool | ||
|
|
||
| **What's Good:** ✅ | ||
| - Positive aspect 1 | ||
| - Positive aspect 2 | ||
| ## Review Focus Areas | ||
|
|
||
| **Issues Found:** ⚠️ | ||
| - Issue 1 with explanation | ||
| - Issue 2 with explanation | ||
| | Priority | Category | What to Look For | | ||
| |----------|----------|------------------| | ||
| | 🔴 Critical | **Security** | SQL injection, XSS, hardcoded secrets, auth bypass | | ||
| | 🔴 Critical | **Bugs** | Logic errors, null/undefined access, race conditions | | ||
| | 🟡 Important | **Performance** | N+1 queries, memory leaks, inefficient algorithms | | ||
| | 🟢 Suggestion | **Quality** | Naming, error handling, code duplication | | ||
|
|
||
| **Suggestions:** 💡 | ||
| 1. Suggestion 1 | ||
| 2. Suggestion 2 | ||
| ``` | ||
| ## Review Summary Format | ||
|
|
||
| ```markdown | ||
| ## 📋 Review Summary | ||
|
|
||
| Do NOT use `\n` escape sequences - just use actual line breaks in your text. | ||
| **Overview**: [One sentence describing what this PR does] | ||
|
|
||
| ## Review Guidelines | ||
| ### ✅ Strengths | ||
| - [Positive point 1] | ||
| - [Positive point 2] | ||
|
|
||
| Focus on: | ||
| - 🐛 **Bugs**: Logic errors, off-by-one errors, null pointer issues | ||
| - 🔒 **Security**: SQL injection, XSS, hardcoded secrets, auth issues | ||
| - ⚡ **Performance**: N+1 queries, unnecessary loops, memory leaks | ||
| - 📖 **Readability**: Unclear naming, missing comments, complex logic | ||
| - ✅ **Best Practices**: Error handling, type safety, testing | ||
| ### ⚠️ Issues Found | ||
| - **[Category]**: [Issue description] → [Suggested fix] | ||
|
|
||
| ### 💡 Suggestions | ||
| - [Optional improvement 1] | ||
| ``` | ||
|
|
||
| ## Line Comment Format | ||
| ## Line Comment Guidelines | ||
|
|
||
| Keep line comments concise and actionable: | ||
| - One issue per comment | ||
| - Include a suggestion to fix | ||
| - Use code blocks for examples if helpful | ||
| - **One issue per comment** - Don't combine multiple concerns | ||
| - **Include fix suggestion** - Show the better approach | ||
| - **Use code blocks** when suggesting code changes: | ||
| ``` | ||
| Consider using: | ||
| `const value = data ?? defaultValue;` | ||
| ``` | ||
|
|
||
| ## Approval Decision | ||
| ## Approval Decision Matrix | ||
|
|
||
| - `approve`: Code looks good, no blocking issues | ||
| - `request_changes`: Critical issues that must be fixed before merge | ||
| - `comment`: General feedback, neither approving nor blocking | ||
| | Situation | Decision | | ||
| |-----------|----------| | ||
| | No issues or only minor style suggestions | `approve` | | ||
| | Has bugs, security issues, or logic errors | `request_changes` | | ||
| | Only has questions or optional improvements | `comment` | | ||
|
|
||
| ## Important Rules | ||
| ## Rules | ||
|
|
||
| 1. Only comment on lines that appear in the diff | ||
| 2. Use the exact line numbers from `gitea-pr-diff` output | ||
| 3. Always use `gitea-review` tool to submit (not `gitea-comment`) | ||
| 4. Keep the summary under 500 words | ||
| 5. Use real line breaks, not escape sequences | ||
| 1. **Diff-only review**: Never ask to read complete files | ||
| 2. **Accurate line numbers**: Use exact `[LINE_NUM]` from diff output | ||
| 3. **Single tool for submission**: Always use `gitea-review`, not `gitea-comment` | ||
| 4. **Respect filters**: If `file_patterns` is set, only review matching files | ||
| 5. **No escape sequences**: Use real line breaks in summary text |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -146,6 +146,56 @@ function formatDiffForReview(files: ParsedFile[]): string { | |||||||||
| return parts.join("\n") | ||||||||||
| } | ||||||||||
|
|
||||||||||
| function matchPattern(filename: string, pattern: string): boolean { | ||||||||||
| // Convert glob pattern to regex | ||||||||||
| // Supports: *, **, ?, [abc], [!abc] | ||||||||||
| const regexPattern = pattern | ||||||||||
| .replace(/\./g, "\\.") | ||||||||||
| .replace(/\*\*/g, "{{GLOBSTAR}}") | ||||||||||
| .replace(/\*/g, "[^/]*") | ||||||||||
| .replace(/{{GLOBSTAR}}/g, ".*") | ||||||||||
| .replace(/\?/g, ".") | ||||||||||
|
|
||||||||||
| const regex = new RegExp(`^${regexPattern}$`) | ||||||||||
| return regex.test(filename) | ||||||||||
|
Comment on lines
+149
to
+160
|
||||||||||
| } | ||||||||||
|
|
||||||||||
| function filterFilesByPatterns(files: ParsedFile[], patterns: string[]): ParsedFile[] { | ||||||||||
| if (!patterns || patterns.length === 0) { | ||||||||||
| return files | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return files.filter(file => | ||||||||||
| patterns.some(pattern => matchPattern(file.path, pattern)) | ||||||||||
| ) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| function formatAsRawDiff(files: ParsedFile[]): string { | ||||||||||
| // Reconstruct a simplified raw diff from parsed files | ||||||||||
| const parts: string[] = [] | ||||||||||
|
|
||||||||||
| for (const file of files) { | ||||||||||
| parts.push(`diff --git a/${file.path} b/${file.path}`) | ||||||||||
|
|
||||||||||
| for (const hunk of file.hunks) { | ||||||||||
| parts.push(`@@ -${hunk.oldStart},0 +${hunk.newStart},0 @@`) | ||||||||||
|
||||||||||
| parts.push(`@@ -${hunk.oldStart},0 +${hunk.newStart},0 @@`) | |
| const oldCount = hunk.changes.filter((change) => change.type !== "add").length | |
| const newCount = hunk.changes.filter((change) => change.type !== "del").length | |
| parts.push(`@@ -${hunk.oldStart},${oldCount} +${hunk.newStart},${newCount} @@`) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,23 @@ | ||
| Fetch the diff (code changes) for a Gitea/Forgejo pull request. | ||
|
|
||
| This tool retrieves all file changes in a PR with line numbers. | ||
| This tool retrieves file changes in a PR with line numbers for review. | ||
|
|
||
| Features: | ||
| - Supports file filtering with glob patterns (e.g., "*.ts", "src/**/*.go") | ||
| - Two output formats: parsed (with line numbers) or raw (unified diff) | ||
|
|
||
| Output formats: | ||
| - "parsed" (default): Shows each line with [LINE_NUM] prefix for easy reference when creating review comments | ||
| - "raw": Returns the raw unified diff format | ||
|
|
||
| Use this tool before submitting a code review to understand what changes were made. | ||
|
|
||
| The parsed format shows: | ||
| - [42] +new line - Added line at line 42 | ||
| - [DEL] -old line - Deleted line | ||
| - [42] context - Unchanged context line | ||
|
|
||
| File filtering examples: | ||
| - ["*.ts", "*.tsx"] - Only TypeScript files | ||
| - ["src/**"] - Only files in src directory | ||
| - ["!*.test.ts"] - Exclude test files (not supported, use positive patterns) | ||
|
|
||
| Use the line numbers in [brackets] when creating review comments with gitea-review tool. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment claims support for character class negation
[!abc], but the implementation only handles this notation by converting it to regex.(any character). Character class negation in glob patterns uses[!...]syntax, but the regex equivalent should be[^...]not just.. The current implementation doesn't properly handle character classes at all - neither[abc]nor[!abc]are implemented. Consider either implementing proper character class support or removing this claim from the comment.