* Add inline comment automation script - Add glab-add-inline-comment.sh for posting inline MR comments - Posts comments at specific file:line locations via GitLab API - Auto-extracts token and fetches MR metadata - Validates inline placement (DiffNote type) - Add comprehensive documentation (README-inline-comments.md) - Update scripts/README.md with new script listing Closes #26 * Rename script: glab-add-inline-comment.sh → add-inline-comment.sh Drop glab- prefix per review feedback. - Rename scripts/glab-add-inline-comment.sh to scripts/add-inline-comment.sh - Update all references in documentation (README.md, README-inline-comments.md) - Update usage examples and command names --------- Co-authored-by: Steven (Bot) <steven@winkintel.com>
7.9 KiB
GitLab Inline Comment Automation
Overview
The add-inline-comment.sh script enables posting inline code review comments to GitLab merge requests at specific file lines. This is more effective than general MR comments because developers can see feedback directly in context without hunting through code.
Why Use Inline Comments?
Problem: GitLab's native glab mr note command only creates general MR comments. When reviewing code, you often want to comment on specific lines, but there's no built-in glab command for this.
Solution: This script uses the GitLab Discussions API to post inline comments with proper position data (file path, line number, and commit SHAs).
Benefits:
- 📍 Contextualized feedback - Comments appear at exact line locations
- ⏱️ Saves time - No manual clicking in GitLab UI
- 🤖 Enables automation - Can be integrated into review workflows
- ✅ Better UX - Developers see feedback in context
Installation
# The script is already in the gitlab-cli-skills repo
cd /path/to/gitlab-cli-skills/scripts
chmod +x add-inline-comment.sh
# Optional: Add to PATH for global access
ln -s $(pwd)/add-inline-comment.sh ~/.local/bin/add-inline-comment
Requirements
- glab CLI - Configured and authenticated (
glab auth login) - jq - For JSON parsing (
apt install jqorbrew install jq) - curl - For API calls (usually pre-installed)
Usage
add-inline-comment.sh <repo> <mr_iid> <file_path> <line_number> <comment_text>
Parameters
| Parameter | Description | Example |
|---|---|---|
repo |
Repository path | owner/repo |
mr_iid |
Merge request IID (numeric) | 42 |
file_path |
File path relative to repo root | src/main.js |
line_number |
Line number in NEW version | 100 |
comment_text |
Comment (supports markdown) | Bug: Add null check |
Examples
Simple comment:
add-inline-comment.sh \
"owner/repo" \
"42" \
"src/components/Button.tsx" \
"25" \
"Consider using a more descriptive variable name here"
Bug report with markdown:
add-inline-comment.sh \
"owner/repo" \
"42" \
"src/utils/validator.js" \
"10" \
"**Bug**: This regex doesn't handle edge case when input is \`null\`. Add: \`if (!input) return false;\`"
Multiple comments (batch review):
#!/bin/bash
REPO="owner/repo"
MR_IID="42"
add-inline-comment.sh "$REPO" "$MR_IID" "src/api.js" 15 "Add error handling"
add-inline-comment.sh "$REPO" "$MR_IID" "src/api.js" 22 "Use async/await instead of .then()"
add-inline-comment.sh "$REPO" "$MR_IID" "src/types.ts" 8 "Missing JSDoc comment"
How It Works
- Extracts GitLab token from
~/.config/glab-cli/config.yml - Fetches MR metadata via
glab apito get:- Project ID
- Base SHA (target branch commit)
- Head SHA (source branch commit)
- Start SHA (merge base commit)
- Builds JSON payload with position data:
{ "body": "Comment text", "position": { "base_sha": "abc123...", "head_sha": "def456...", "start_sha": "abc123...", "position_type": "text", "new_path": "src/file.js", "new_line": 42 } } - Posts to GitLab API via
curl(usingglab apidoesn't work for nested JSON) - Validates response - Checks that note type is
DiffNote(inline) notDiscussionNote(general)
Output
Success Output
✅ Success!
Discussion ID: abc123...
Note ID: 3106970438
Note Type: DiffNote
Inline: true
✅ Inline comment posted successfully at src/main.js:42
URL: https://gitlab.com/owner/repo/-/merge_requests/42#note_3106970438
The script also outputs the full JSON response for programmatic use.
Error Output
❌ Error: HTTP 400
{
"message": "400 Bad request - Position is invalid"
}
Common errors:
- 400 Bad Request - Line number doesn't exist in diff
- 401 Unauthorized - Token invalid or expired
- 404 Not Found - MR or repo doesn't exist
Troubleshooting
"Could not extract GitLab token"
Cause: glab CLI not authenticated or config file missing.
Fix:
glab auth login
glab auth status # Verify authentication
"Position is invalid"
Cause: Line number doesn't exist in the file diff.
Fix:
- Verify the line number exists in the NEW version of the file
- Check that the file was actually changed in this MR
- Use
glab mr diff <iid>to see what lines are in the diff
Comment appears as general, not inline
Cause: This shouldn't happen if the script succeeded, but if it does:
- File path might be incorrect (must be relative to repo root)
- Line number might be outside the diff range
Debug:
# Check the diff to see available lines
glab mr diff 42 --repo owner/repo | grep -A5 -B5 "src/file.js"
Integration with Code Review Workflows
Example: Automated Review Script
#!/bin/bash
# review-mr.sh - Automated code review helper
REPO="$1"
MR_IID="$2"
# Fetch MR diff
DIFF=$(glab mr diff "$MR_IID" --repo "$REPO")
# Check for common issues
if echo "$DIFF" | grep -q "console.log"; then
# Find line number of console.log
LINE=$(echo "$DIFF" | grep -n "console.log" | head -1 | cut -d: -f1)
FILE=$(echo "$DIFF" | grep -B20 "console.log" | grep "^+++" | head -1 | cut -d/ -f2-)
add-inline-comment.sh "$REPO" "$MR_IID" "$FILE" "$LINE" \
"⚠️ Remove console.log before merging"
fi
# Check for TODO comments
if echo "$DIFF" | grep -q "TODO"; then
# ... similar logic
fi
Example: Review from Analysis Tool
#!/bin/bash
# Run ESLint and post inline comments for each issue
REPO="owner/repo"
MR_IID="42"
# Run linter and parse output
eslint src/ --format json | jq -r '.[] | "\(.filePath):\(.messages[].line) \(.messages[].message)"' | \
while IFS=: read -r file line message; do
# Remove absolute path prefix
rel_path="${file#/absolute/path/to/repo/}"
add-inline-comment.sh "$REPO" "$MR_IID" "$rel_path" "$line" "ESLint: $message"
done
Limitations
- Line must exist in diff - Can only comment on lines that were added or changed in the MR
- File path must be exact - Must match the path relative to repo root exactly
- New file lines only - Line number refers to the NEW version (after changes)
- GitLab.com only - Script uses
https://gitlab.com/api/v4/(modify for self-hosted)
API Reference
This script uses the GitLab Discussions API.
Endpoint:
POST /projects/:id/merge_requests/:merge_request_iid/discussions
Key fields:
body- Comment text (markdown supported)position.base_sha- Target branch commitposition.head_sha- Source branch commitposition.new_path- File pathposition.new_line- Line number
Development
Testing
Test on a personal repo before using on production MRs:
# Create test MR
glab mr create --title "Test MR" --repo owner/test-repo
# Post test comment
./add-inline-comment.sh \
"owner/test-repo" \
"1" \
"README.md" \
"1" \
"TEST: This is a test inline comment"
# Verify in GitLab UI
# Delete test comment and MR when done
Contributing
Improvements welcome! This script is part of gitlab-cli-skills.
Ideas for enhancement:
- Support for self-hosted GitLab instances (configurable API URL)
- Batch mode (read comments from file or stdin)
- Support for line ranges (multi-line comments)
- Integration with existing
glab-mrreview workflow
Related Skills
- glab-mr - Main MR management skill
- Code review workflows - Documented in
glab-mr/SKILL.md - CI automation - Can be triggered from CI pipelines
License
Same as gitlab-cli-skills: MIT License
Version: 1.0.0 (2026-02-23)
Tested on: GitLab.com with glab CLI v1.48.0