Credentials: ~/.openclaw/credentials/gitlab.json
{
"token": "glpat-xxx",
"host": "https://gitlab.com",
"ignore_patterns": ["*.min.js", "*.lock", "forms/*.json"]
}
Required API scopes:
api — required for posting inline comments
read_api — sufficient for analysis only (no comment posting)
Always run token check first to know upfront whether comments can be posted:
python scripts/gitlab_client.py check-token <mr_url>
Output includes "can_write": true/false. If false, skip step 6 and inform the user that the token needs the api scope to post comments. Do NOT proceed to analysis and then fail at step 6.
python scripts/gitlab_client.py fetch-mr <mr_url>
python scripts/gitlab_client.py fetch-diff <mr_url>
fetch-diff returns a JSON array. Each entry contains new_path, old_path, diff (unified diff text), and boolean flags new_file, deleted_file, renamed_file.
> Fallback: if the /diffs endpoint returns HTTP 500 (some self-hosted GitLab instances), the script automatically retries via /changes. No manual intervention needed.
Use ignore_matcher.py to exclude files before analysis:
from ignore_matcher import filter_diffs
reviewable = filter_diffs(all_diffs) # merges defaults + credentials ignore_patterns
Default ignore patterns (always applied, even without credentials file):
.min.js, .min.css, .lock, package-lock.json, pnpm-lock.yaml, forms/.json
Binary extensions (.png, .jar, .class, .map, etc.) are always skipped.
references/review-guidelines.md for all review rules, severity definitions, and comment format.
Focus areas:
Group findings by severity:
## Code Review — <MR title> (<source_branch> → <target_branch>)
### Critical
- `UserService.java:42` — Transaction wraps HTTP call; holds DB lock during network I/O.
### Major
- `OrderRepository.java:87` — N+1: `findRolesByUserId` called inside loop. Use batch query.
### Minor
- `PaymentDto.java:15` — Field name `val` is not descriptive.
### Decision: Needs changes
Decision options: Pass / Needs changes / Reject
Only execute this step if check-token (step 1) returned "can_write": true.
Write comments to a temp JSON file, then post via post_comments.py.
Never use python -c with inline comment bodies — backticks and special characters break shell escaping.
# 1. Write all findings to a JSON file
cat > /tmp/mr_comments.json << 'EOF'
[
{
"file_path": "src/main/UserService.java",
"line": 42,
"body": "[CRITICAL] Transaction wraps HTTP call...\n\nSuggestion:\n```java\n// fix\n```"
}
]
EOF
# 2. Post via script
python scripts/post_comments.py <mr_url> /tmp/mr_comments.json
How to determine the correct line number from a diff hunk:
@@ -375,6 +375,8 @@ ← new file starts at line 375
unchanged line → 375
unchanged line → 376
unchanged line → 377
+ added line → 378 ← use this number
+ added line → 379
Count from the +A value in @@ -X,Y +A,B @@ for new-file lines.
Each comment body format (from references/review-guidelines.md §8):
[SEVERITY] <one-line issue>
<2-4 sentence explanation referencing the diff.>
Suggestion:
Constraints:
insufficient_scope, the script stops immediately and prints a fix instruction. Do not retry.
references/review-guidelines.md
共 2 个版本