ChatGPTSoftwareCode reviewAI score · PendingAI-assisted edit · no obvious prompt-injection riskn8n.io

GitLab MR Automated Code Review & AI Risk Assessment

GitLab merge request trigger → extract code diff → Claude/GPT risk analysis → structured report → email & MR comment notification

ExperiencedStepsWorkflowPromptTip
Who
DevOps and engineering teams using n8n who want to automate merge request review
You get
When an MR is created or updated, automatically fetch code changes, have AI assess risk level, identify issues, provide fix recommendations and test cases, then notify dev and QA teams via email and GitLab MR comment
You need
n8n · http-request · code · ai-agent · structured-output · anthropic · gmail

Constraints

Requires an accessible n8n instance (self-hosted or Cloud), GitLab API credentials (gitlabApi), Anthropic API key (anthropicApi) or OpenAI API key, and Gmail OAuth2 credentials (gmailOAuth2). The template hardcodes example projects and placeholder emails; after import you must replace with actual project paths, repository names, notification email lists, and valid API tokens.

What they did

This n8n template was developed by Quantana and published to the official n8n template library. The workflow listens for GitLab merge request creation and update events, pulls the code diff via the GitLab API, sends it to an AI Agent calling Claude (or GPT) for structured analysis, and outputs risk level, issue list, fix recommendations, code snippets, diff comparison table, and QA test cases. Finally it sends an HTML email to dev/QA teams and posts the report as a comment on the GitLab MR.

How it went

The template author states this workflow enables: automated code review, pre-merge security and compliance risk identification, integration with existing GitLab CI/CD workflows, and improved dev/QA collaboration. Actual effectiveness depends on the AI model's code comprehension and adherence to the HTML formatting requirements in the prompt.

Worth knowing

1. The template workflow.json contains multiple hardcoded placeholders (YOUR_TOKEN_HERE, REPLACE_WITH_GMAIL_OAUTH_ID, REPLACE_WITH_GITLAB_CRED_ID, example emails [email protected], and example project names) that must all be replaced after import or the workflow will fail. 2. The AI Agent node is configured for claude-3-5-haiku-20241022, which differs from the GPT-4o mentioned in the template title; to use GPT-4o you must manually switch the model node and parameters. 3. The email node uses Gmail OAuth2, requiring prior Google Cloud app authorization. 4. This site has not tested this workflow; we recommend validating the full pipeline with a test MR before production use.

Steps

  1. Configure GitLab Trigger

    Add a GitLab Trigger node in n8n, connect GitLab API credentials, select the merge_requests event, and specify the repository (owner/repository) to monitor. After saving, n8n will auto-generate and register the webhook.

  2. Extract MR Code Diff

    Add an HTTP Request node (Extract Diff) configured to call the GitLab API: GET /api/v4/projects/{project}/merge_requests/{iid}/changes. Use expressions to dynamically pull the project path and MR IID from trigger data, and provide the GitLab API Token in the Header.

  3. Verify Changes Are Non-Empty

    Add an If node (If Some Change) that checks whether the changes array length from the diff response is greater than 0. If empty, terminate the workflow to avoid analyzing no-op MRs.

  4. AI Analysis & Structured Output

    Configure the AI Agent node, connecting an Anthropic Chat Model (or alternative). The node uses define mode with a complete tool schema requiring the AI to return JSON: RiskLevel, Summary, Recommendations, Issues, URL, DiffTable, TestCases. Pass the diff content and MR URL as user messages. Downstream, connect Auto-fixing Output Parser and Structured Output Parser to enforce output format compliance.

    Execution prompt · Source text。n8n AI Agent node Parameters > Text (define mode), as the complete tool-calling configuration and message content

    ={
      "model": "claude-3-5-haiku-20241022",
      "max_tokens": 1000,
      "temperature": 0.7,
      "tools": [
        {
          "name": "record_summary",
          "description": "Record a structured summary of a git diff using well-defined JSON.",
          "input_schema": {
            "type": "object",
            "properties": {
              "RiskLevel": {
                "type": "string",
                "description": "Overall risk assessment of the changes: High/Medium/Low."
              },
              "Summary": {
                "type": "string",
                "description": "One-line summary of the git diff analysis"
              },
              "Recommendations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "Recommendation": {
                      "type": "string",
                      "description": "Specific recommendation in HTML format."
                    },
                    "CodeSnippet": {
                      "type": "string",
                      "description": "Relevant code full snippet formatted in HTML."
                    }
                  },
                  "required": ["Recommendation", "CodeSnippet"]
                }
              },
              "Issues": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "File": {
                      "type": "string",
                      "description": "HTML-formatted name of the file where the issue exists."
                    },
                    "PotentialIssue": {
                      "type": "string",
                      "description": "HTML-formatted description of the issue."
                    },
                    "Severity": {
                      "type": "string",
                      "description": "Severity of the issue: High/Medium/Low in HTML."
                    }
                  },
                  "required": ["File", "PotentialIssue", "Severity"]
                }
              },
              "URL": {
                "type": "string",
                "description": "Link to the repository in HTML."
              },
              "DiffTable": {
                "type": "object",
                "properties": {
                  "FileName": {
                    "type": "string",
                    "description": "HTML-formatted name of the file."
                  },
                  "Changes": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "Line": {
                          "type": "string",
                          "description": "HTML-formatted line number."
                        },
                        "Before": {
                          "type": "string",
                          "description": "Code before the change formatted in HTML."
                        },
                        "After": {
                          "type": "string",
                          "description": "Code after the change formatted in HTML."
                        }
                      },
                      "required": ["Line", "Before", "After"]
                    }
                  }
                }
              },
              "TestCases": {
                "type": "array",
                "description": "List of test cases the QA team must check.",
                "items": {
                  "type": "object",
                  "properties": {
                    "TestFor": {
                      "type": "string",
                      "description": "Description of the functionality or area to test."
                    },
                    "Steps": {
                      "type": "string",
                      "description": "HTML-formatted steps to test the functionality."
                    },
                    "ExpectedOutcome": {
                      "type": "string",
                      "description": "HTML-formatted description of the expected result of the test."
                    }
                  },
                  "required": ["TestFor", "Steps", "ExpectedOutcome"]
                }
              }
            },
            "required": ["RiskLevel", "Summary", "Recommendations", "Issues", "URL", "DiffTable", "TestCases"]
          }
        }
      ],
      "tool_choice": {
        "type": "tool",
        "name": "record_summary"
      },
      "messages": [
        {
          "role": "user",
          "content": [
            {
              "type": "text",
              "text": "Analyze the following git diff, highlight potential issues, provide recommendations with code snippets (using HTML formatting for all values), and include the URL. Ensure proper risk evaluation. Mark issues that may break the build or reveal a security risk as High':"
            },
            {
              "type": "text",
              "text": "{{ $json.changes.map(change => JSON.stringify(change.diff).slice(1, -1).replace(/[\r]/g, '')).join(' ') }}"
            },
            {
              "type": "text",
              "text": "URL: {{ $json.web_url }}"
            },
            {
              "type": "text",
              "text": "Provide a table of test cases for the QA team under the 'TestCases' field."
            }
          ]
        }
      ]
    }
  5. Generate Notification List

    Add a Code node (Distribution List Generator) that uses JavaScript to map project names to dev/qa email lists, merges with a global list and the committer email, deduplicates, and outputs a comma-separated string. You must replace the example project names and placeholder emails with actual team configuration.

  6. Send Email & MR Comment

    Configure two nodes in parallel: 1) Gmail node (Send to DL) receiving the emails output from Distribution List Generator, sending an HTML-formatted report email with subject containing risk level and project name; 2) HTTP Request node (Comment Back on MR) POSTing to the GitLab MR notes API, rendering AI output as Markdown table comments. Both require replacing credentials and project path expressions.

Prompt you can copy

Setup guidance · Editorial suggestion。Setup assistant starter word for post-import configuration checklist and testing guidance

This block is the prompt. Ads are never placed here.

This is an official n8n template. After importing, check in this order:
1. Replace the owner/repository in GitLab Trigger with your actual repository;
2. Enter a valid GitLab API Token in the Headers of Extract Diff and Comment Back on MR (not placeholders);
3. Configure Anthropic API credentials (or switch to OpenAI);
4. Replace the project-to-email mapping in Distribution List Generator with actual team addresses;
5. Configure Gmail OAuth2 credentials and update email subject variables;
6. Create a test MR to verify triggering, analysis, email delivery, and comment posting.

The AI Agent node uses define mode; the prompt is a complete JSON parameter (tool schema + messages) to be pasted directly inside the n8n node, not sent as chat messages.

Source

GitLab merge request review & risk analysis with Claude/GPT AI · vishalquantana · n8n.io · 2025-05-12

Comments & feedback

Tried this method? Share results, problems or improvements. Comments appear after moderation. Please avoid sensitive information.

Loading…

    Related