gitlab-mr-review
Original:🇺🇸 English
Translated
Review a GitLab Merge Request and provide findings, and post structured review comments with issue explanation plus pseudo code fixes. Use this skill when asked to review a Gitlab Merge request.
6installs
Added on
NPX Install
npx skill4agent add ibuildingsnl/reusable-ai-prompts gitlab-mr-reviewTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →GitLab MR Review Workflow Skill
Purpose
The purpose of this skill is to provide constructive and comprehensive feedback on code changes. The primary goals are:
- Quality Assurance: Identify bugs, potential logic errors, and edge cases.
- Maintainability: Ensure code is readable, modular, and consistent with the existing architecture.
- Security: Detect common security vulnerabilities and privacy risks. Validate against OWASP Top 10 where applicable.
- Education: Provide explanations and context for suggested changes to help the author grow.
This workflow is read-first and non-invasive:
- Do not modify repository files.
- Analyze MR content and discussions.
- Post comments only when explicitly requested.
Inputs Required
- MR identifiers: Either an MR URL or
{project_id, merge_request_iid} - Desired action (to be confirmed in Step 6 report):
- Option 1: Report only (show findings, no GitLab action).
- Option 2: Discuss, (re)validate or update/delete a specific finding by ID.
- Option 3: Post + Approve (comments + approval).
- Option 4: Post + Request Changes (signal that changes are required).
Required Tools
Before starting, verify the following tools are available. If any tool is unavailable, stop and ask the user to install the Gitlab MCP (https://github.com/zereight/gitlab-mcp/tree/main) server.
| Tool | Purpose | Step |
|---|---|---|
| Fetch MR metadata (title, branches, diff refs) | Step 2 |
| Retrieve existing review threads | Step 2 |
| Retrieve diff between branches | Step 4 |
| Explore codebase conventions | Step 1 |
| Execute git worktree commands | Step 3, 7-F |
| Create inline review comments | Step 7-A |
| Verify draft notes created | Step 7-A |
| Correct missing draft notes | Step 7-A |
| Publish all drafts at once | Step 7-A |
| Approve the MR | Step 7-B |
| Request changes via GraphQL mutation | Step 7-C |
| Add current user as reviewer (if needed) | Step 7-C |
Prohibited: Do not use raw or CLI commands for API interactions.
curlgitWorkflow
Follow these steps in order. Do not skip a step.
Step 1 — Gather Codebase Context
Quickly identify the project's conventions and architecture:
- Search for key structural files (framework config, , linting configs).
README - Read project-level instructions (,
.github/copilot-instructions.md,AGENTS.mddevelopment docs).CLAUD.md - Document: language, framework, architectural patterns, naming conventions, test strategy.
- Store these observations as your review baseline for code analysis.
Fallback if conventions are unclear: Infer standards from the detected language/framework:
- PHP: PSR-12, PSR-4 (autoloading).
- Python: PEP 8, type hints (PEP 484).
- JavaScript/TypeScript: ESLint, Google/Airbnb style guides.
- Go: , idiomatic Go patterns.
gofmt - If still unclear, note this assumption in the final report and apply general best practices (SOLID, DRY, KISS).
Step 2 — Fetch GitLab MR Details
Retrieve all MR metadata needed for the review.
- Call with
mcp_gitlab_get_merge_request.{project_id, merge_request_iid}- Extract: title, description, source/target branches, author, labels, milestone, diff refs (,
base_sha,start_sha).head_sha - Note diff refs: These are required in Step 7-A for inline comment positioning.
- Extract: title, description, source/target branches, author, labels, milestone, diff refs (
- Call to load existing review threads.
mcp_gitlab_mr_discussions- Note all open and resolved threads to avoid posting duplicate feedback.
- Note the MR description for stated intent, linked issues, and breaking-change flags.
Step 3 — Checkout MR Branch
Create an isolated, read-only worktree for file access:
bash
# Sanity check: prune orphaned worktrees from previous runs
git worktree prune
# Fetch the source branch to ensure it exists locally
git fetch origin {source_branch}:{source_branch} 2>/dev/null || true
# Create isolated worktree in detached state
REPO_ROOT=$(git rev-parse --show-toplevel)
WORKTREE_PATH="${REPO_ROOT}/.tmp/mr-review-{merge_request_iid}"
git worktree add --detach "${WORKTREE_PATH}" {source_branch}
# Lock worktree to prevent accidental modifications
git worktree lock "${WORKTREE_PATH}"Store for Steps 4–5. Read-only enforced — the worktree is locked to prevent file modifications.
worktree_path = "${REPO_ROOT}/.tmp/mr-review-{merge_request_iid}"Step 4 — Retrieve and Parse the Diff
- Call using the source and target branches.
mcp_gitlab_get_branch_diffs - Build a file-change inventory: list each changed file with its change type (added / modified / deleted).
- Prioritise files for review:
- High priority: core business logic, security-sensitive code, public APIs, data models.
- Lower priority: generated files, lock files, migration snapshots, test fixtures.
- Constraint: If the diff exceeds 20 files, focus on high-priority files first and note skipped files in the report.
- Option to user: If >20 files are detected, ask the user whether they want a full review despite the scope; flag this in the report if high-priority files are skipped.
Step 5 — Analyze & Classify Findings
Analyse each prioritised file against the review baseline. For each changed section, check:
- Correctness — logic errors, edge cases, incorrect conditionals.
- Maintainability — architecture adherence, DRY, SOLID, readability, clarity.
- Security — OWASP Top 10, injection risks, exposed secrets, PII.
- Consistency — coding standards, naming conventions, codebase patterns (from Step 1 baseline).
- Scope / Description alignment (if MR description is available) — validate that the actual diff matches the stated intent in the MR description:
- Identify any changed files or logic that are not mentioned in the description (scope creep or unintended changes).
- Identify any requirements stated in the description that appear to be missing from the diff.
- Flag discrepancies as 🟡 Request for Change findings with an explanation of what was expected vs. what was found.
- If the MR description is empty or absent, skip this check and note its absence in the report.
Determine exact line numbers using the worktree ( from ):
read_file{worktree_path}/{file_path}- For added/modified lines: extract from the diff API hunk.
new_line - For deleted lines: extract from the diff API hunk.
old_line
Record each issue:
- File path and exact line number(s).
- Short description.
- Risk/impact.
- Suggested fix (pseudo code).
Classify by severity:
Use the following guidance table to categorize findings:
| Severity | Category | Examples | Action |
|---|---|---|---|
| 🔵 Optional | Style, naming, minor formatting | Whitespace inconsistency, code comments, doc formatting | Can be addressed in a follow-up or ignored |
| 🟡 Request for Change | Logic errors, architectural issues, configuration gaps | Incorrect conditionals, missing error handling, data consistency issues, missing translations, naming convention, typos in labels, unused imports, performance concerns, architectural inconsistency, breaking changes, API contract violations | Must be addressed before merge |
| 🔴 Request for Change | Security vulnerabilities, severe bugs | SQL injection, XSS vulnerability, exposed secrets/credentials, authentication bypass, buffer overflow, data loss risk, race conditions, privilege escalation | Must be addressed before merge |
Note on Critical findings: When a finding is a security vulnerability or severe bug, prefix the title with 🔴 (e.g., 🔴 Request for Change — SQL injection vulnerability) Always flag critical findings explicitly to the user before approval.
Before compiling the report: Every finding must use the Comment Template structure
- READ FIRST: "Comment Template" section below
- Title with severity and short topic
- Relevant lines — file path and line number(s)
- Issue — what is problematic
- Why it matters — risk/maintenance impact
- Suggested fix (code and or configuration example)
Do not invent alternative formats or omit any field.
Compile report grouped by severity with totals.
Step 6 — Present Findings to the User
Present the full findings report to the user before taking any action.
The report must include:
- MR title, source → target branch, author.
- Finding totals per severity.
- Each finding formatted exactly using the Comment Template structure defined above. Prefix each finding with a sequential number (e.g., ) for easy reference in the chat.
**Finding #1**
Pause here and await user confirmation. Ask the user to choose one of the following actions:
What would you like me to do next?
- Report only — no GitLab action, findings are shown above.
- Discuss / Refine — discuss, (re)validate or update/delete a specific finding by ID.
- Post + Approve — publish all findings and approve the MR.
- Post + Request Changes — publish all findings on the MR (signals changes are required).
Do not call any posting, approval, or state-change tool until the user selects one of the options above.
Step 7 — Execute Chosen Action (Only When Confirmed)
Based on the user's choice from Step 6, follow the matching sub-procedure below.
7-A: Post Comments (options 3 and 4)
Post all findings as inline draft notes, then publish them in a single batch.
-
Create draft notes — for each finding, call:
mcp_gitlab_create_draft_note- Provide ,
project_id.merge_request_iid - Set to the rendered Comment Template output from Step 7. Important: Strip the sequential finding number before posting; numbers are for the report only.
body - Provide a object (inline diff comment):
position- for code diffs (use
position_type: "text"only if diff positioning fails)."file" - ,
base_sha,head_shafrom Step 2 diff refs.start_sha - File path: Use for added/modified files; use
new_pathfor deleted files.old_path - Line numbers from diff API: Use (for added/modified lines) or
new_line(for deleted lines) as extracted and validated in Step 5. These MUST correspond to actual hunk boundaries fromold_line.mcp_gitlab_get_branch_diffs
- Save each returned for verification.
draft_note_id
- Provide
-
Positioning Fallbacks (if inline positioning fails):
- Hunk mismatch or stale diff: If the diff positioning is rejected by the API, the diff may be stale or the repository state has changed.
- Retry with on the relevant file path.
position_type: "file" - Include exact file path and line references inside the comment body using the Comment Template structure.
- Retry with
- Renamed or moved files: For files that have been renamed/moved in the MR:
- Use for new sections; use
new_pathfor removed sections.old_path - If GitLab rejects the position, fallback to file-level comment.
- Use
- GitLab API error (e.g., , invalid position object):
line_code can't be blank- Log the error and file path.
- Retry with on the relevant file path.
position_type: "file" - Include exact file path and line references inside the comment body using the Comment Template structure.
- Hunk mismatch or stale diff: If the diff positioning is rejected by the API, the diff may be stale or the repository state has changed.
-
Proceed to draft verification
-
Proceed to draft verification — verify all draft notes were created successfully.
-
Verify drafts — callwith
mcp_gitlab_list_draft_notes.{project_id, merge_request_iid}- Confirm the number of draft notes matches the number of findings.
- Correct any missing notes using before publishing.
mcp_gitlab_update_draft_note
-
Publish — callwith
mcp_gitlab_bulk_publish_draft_notes.{project_id, merge_request_iid}- All drafts become visible on the MR simultaneously.
7-B: Approve (option 3 only)
After all draft notes are published (7-A complete):
- Call with
mcp_gitlab_approve_merge_request.{project_id, merge_request_iid} - Confirm approval was recorded (check response for approval state).
- Only approve when no 🔴 critical findings were posted. If critical security or severe bug findings exist, warn the user and ask to confirm they still want to approve despite the issues.
7-C: Request Changes (option 4 only)
After all draft notes are published (7-A complete):
-
Validate reviewer assignment — Before attempting the Request Changes mutation:
- Retrieve the current MR state using with
mcp_gitlab_get_merge_request.{project_id, merge_request_iid} - Extract the array from the response.
reviewers - Check if the current user (typically identified by GitLab session context) is listed in the reviewers.
- If the current user is NOT a reviewer: Call to add yourself as a reviewer:
mcp_gitlab_update_merge_requestParameters: - project_id: the project identifier - merge_request_iid: the MR IID - reviewer_ids: array containing the ID of the current user (retrieve from GitLab user context) - Confirm the update was successful before proceeding to step 2.
- Retrieve the current MR state using
-
Submit a formal "Request Changes" review using the GitLab GraphQL mutation:
mergeRequestRequestChangesgraphqlmutation RequestChanges($projectPath: ID!, $iid: String!) { mergeRequestRequestChanges(input: { projectPath: $projectPath, iid: $iid }) { mergeRequest { iid title reviewers { nodes { username mergeRequestInteraction { reviewState } } } } errors } }Callwith the query above and variables:mcp_gitlab_execute_graphql- : the full project path (e.g.
projectPath) — derived from the project identifier used in Step 2."group/project" - : the merge request IID as a string.
iid
-
Verify the response:
- Confirm is empty.
errors - Check that the current user's in the response is
reviewState.REQUESTED_CHANGES - If the mutation returns errors (e.g., GitLab API issue), inform the user with the error details — the published inline comments still communicate the required changes.
- Confirm
-
Post an Overall Summary Comment on the MR:
- You must explicitly post a general comment/note on the MR containing a high-level summary of the key findings.
7-D: Report Only (option 1)
If the user chose "Report only" (no GitLab action):
- Skip Steps 7-A, 7-B, and 7-C.
- Proceed directly to 7-F cleanup (worktree removal below).
- Summary to user: Provide the findings report and note that no draft notes were posted.
7-E: Discuss / Refine Finding (option 2)
If the user chose "Discuss / Refine":
- Ask the user which Finding ID they want to discuss or refine.
- Discuss the specifics with the user. Update the finding text, severity, or suggested fix based on the consensus.
- Remove or keep the finding based on the discussion.
- Return directly to Step 6: Summarize the updated findings and present the action options again. Do not proceed to Clean Up yet.
7-F: Clean Up
After all actions are complete (or if option 1 was chosen):
-
Remove the git worktree with verification:bash
REPO_ROOT=$(git rev-parse --show-toplevel) WORKTREE_PATH="${REPO_ROOT}/.tmp/mr-review-{merge_request_iid}" # Unlock before removal git worktree unlock "${WORKTREE_PATH}" 2>/dev/null || true # Attempt removal with error handling if git worktree remove "${WORKTREE_PATH}"; then echo "Worktree cleaned up successfully." else echo "WARNING: Failed to remove worktree at ${WORKTREE_PATH}" echo "Run 'git worktree prune' manually to clean orphaned entries." fi -
Report back to the user:
- For Report only (option 1): Confirm findings were presented; no actions taken.
- For Posted comments/approval/request-changes: Draft note IDs that were published, approval state (if applicable), MR state change (if applicable) and include summary with key findings.
- If any fallback path was used, explain why in one sentence.
- If worktree cleanup failed, notify the user to run manually.
git worktree prune
Comment Template Example
Refer to the Comment Template structure defined in Step 5. Here is a concrete example (in the chat report, prefix this with ):
**Finding #N**text
🟡 Request for Change — avoid repeated magic string
Relevant lines
- path/file.twig around line 108
- path/partial.twig around line 99
Issue
- Repeated literal condition in multiple files.
Why this matters
- Rename risk and inconsistent behavior.
Suggested fix (example)
{# parent #}
set boolean once
pass boolean to include
{# child #}
branch on booleanOutput Style for User
- Keep summary concise.
- State exactly what was posted (thread IDs/note IDs when available).
- If a fallback path was used, explain why in one sentence.
Guardrails
- Post comments only when user selects option 3 or 4 at the end of Step 6 (do not post for option 1).
- Only approve (option 3) if no 🔴 critical findings — otherwise ask user re-confirmation.
- Option 4 (request changes) relies on published review comments; no additional MR state change is required.
- Never merge, alter code, or use alternate providers (GitHub, Jira, etc.).
- Keep findings tied to concrete diff evidence from the branch worktree.
- If the workflow is interrupted (user cancels, agent crashes), manually run to clean orphaned entries and recover disk space.
git worktree prune
Completion Checklist
- Step 1: Codebase context gathered, conventions documented
- Step 2: MR metadata fetched (title, branches, diffs refs, author), discussions loaded
- Step 3: Worktree created at
.tmp/mr-review-{merge_request_iid} - Step 4: Diff parsed, files prioritised, high/low priority files identified
- Step 5: Code analysed, findings classified by severity, description alignment validated (if available), Comment Template fields populated
- Step 6: Report presented to user, action confirmed (options 1–4 selected)
- Step 7: Appropriate sub-procedure executed (7-A/B/C/D/E/F), worktree removed, summary reported