n8n Workflow

Chatgpt Automatic Code Review In Gitlab Mr

This n8n workflow automates tasks and integrates with various services. Chatgpt Automatic Code Review In Gitlab Mr - ready to import and run in your n8n instance.

n8n workflow.json

About This Script

This n8n workflow automates tasks and integrates with various services. Chatgpt Automatic Code Review In Gitlab Mr - ready to import and run in your n8n instance.
Features:
  • Receives webhook events
  • Makes HTTP requests to external APIs
  • Conditional logic and branching
Source Code
{
    "nodes": [
        {
            "name": "Sticky Note",
            "type": "n8n-nodes-base.stickyNote",
            "position": [
                880,
                540
            ],
            "parameters": {
                "content": "Configuration note: update with your credentials or endpoint.",
                "color": "#FFF59D"
            },
            "typeVersion": 1,
            "id": "369ad956-f827-4f6a-a501-45b4ebd1747b"
        },
        {
            "name": "Sticky Note2",
            "type": "n8n-nodes-base.stickyNote",
            "position": [
                -380,
                580
            ],
            "parameters": {
                "content": "Configuration note: update with your credentials or endpoint.",
                "color": "#FFF59D"
            },
            "typeVersion": 1,
            "id": "7026d81f-dcba-4f38-856b-306c87e802cb"
        },
        {
            "name": "Sticky Note3",
            "type": "n8n-nodes-base.stickyNote",
            "position": [
                -120,
                560
            ],
            "parameters": {
                "content": "Configuration note: update with your credentials or endpoint.",
                "color": "#FFF59D"
            },
            "typeVersion": 1,
            "id": "cf9b27ac-73df-4be1-bb9c-835710bcb344"
        },
        {
            "name": "Webhook",
            "type": "n8n-nodes-base.webhook",
            "position": [
                -540,
                760
            ],
            "webhookId": "6cfd2f23-6f45-47d4-9fe0-8f6f1c05829a",
            "parameters": {
                "path": "e21095c0-1876-4cd9-9e92-a2eac737f03e",
                "options": [],
                "httpMethod": "POST"
            },
            "typeVersion": 1.1,
            "id": "6b642442-d1f5-4fb7-8c4b-7af260637327"
        },
        {
            "name": "Code",
            "type": "n8n-nodes-base.code",
            "position": [
                720,
                540
            ],
            "parameters": {
                "mode": "runOnceForEachItem",
                "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nvar diff = $input.item.json.gitDiff\n\nlet lines = diff.trimEnd().split('\\n');\n\nlet originalCode = '';\nlet newCode = '';\n\nlines.forEach(line => {\n  console.log(line)\n    if (line.startsWith('-')) {\n        originalCode += line + \"\\n\";\n    } else if (line.startsWith('+')) {\n        newCode += line + \"\\n\";\n    } else {\n        originalCode += line + \"\\n\";\n        newCode += line + \"\\n\";\n    }\n});\n\nreturn {\n  originalCode:originalCode,\n  newCode:newCode\n};\n\n"
            },
            "typeVersion": 2,
            "id": "6e86af06-ad31-4683-9d41-b9a9a4769aab"
        },
        {
            "name": "Split Out1",
            "type": "n8n-nodes-base.splitOut",
            "position": [
                140,
                740
            ],
            "parameters": {
                "options": [],
                "fieldToSplitOut": "changes"
            },
            "typeVersion": 1,
            "id": "50257995-3203-4137-a832-705924dcbd0a"
        },
        {
            "name": "OpenAI Chat Model1",
            "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
            "position": [
                900,
                860
            ],
            "parameters": {
                "options": {
                    "baseURL": ""
                }
            },
            "typeVersion": 1,
            "id": "3f9a672c-0f71-4d16-a97a-f3a286f77cd1"
        },
        {
            "name": "Get Changes1",
            "type": "n8n-nodes-base.httpRequest",
            "position": [
                -60,
                740
            ],
            "parameters": {
                "url": "=https://gitlab.com/api/v4/projects/{{ $json[\"body\"][\"project_id\"] }}/merge_requests/{{ $json[\"body\"][\"merge_request\"][\"iid\"] }}/changes",
                "options": [],
                "sendHeaders": true,
                "headerParameters": {
                    "parameters": [
                        {
                            "name": "PRIVATE-TOKEN"
                        }
                    ]
                }
            },
            "typeVersion": 4.1,
            "id": "c2c87323-ddb0-407b-8c4a-6c6eecf9813f"
        },
        {
            "name": "Skip File Change1",
            "type": "n8n-nodes-base.if",
            "position": [
                340,
                740
            ],
            "parameters": {
                "options": [],
                "conditions": {
                    "options": {
                        "leftValue": "",
                        "caseSensitive": true,
                        "typeValidation": "strict"
                    },
                    "combinator": "and",
                    "conditions": [
                        {
                            "operator": {
                                "type": "boolean",
                                "operation": "false",
                                "singleValue": true
                            },
                            "leftValue": "={{ $json.renamed_file }}",
                            "rightValue": ""
                        },
                        {
                            "operator": {
                                "type": "boolean",
                                "operation": "false",
                                "singleValue": true
                            },
                            "leftValue": "={{ $json.deleted_file }}",
                            "rightValue": ""
                        },
                        {
                            "operator": {
                                "type": "string",
                                "operation": "startsWith"
                            },
                            "leftValue": "={{ $json.diff }}",
                            "rightValue": "@@"
                        }
                    ]
                }
            },
            "typeVersion": 2,
            "id": "322e916e-6be7-4497-bc16-f27dd44b3ff3"
        },
        {
            "name": "Parse Last Diff Line1",
            "type": "n8n-nodes-base.code",
            "position": [
                540,
                540
            ],
            "parameters": {
                "mode": "runOnceForEachItem",
                "jsCode": "const parseLastDiff = (gitDiff) => {\n  gitDiff = gitDiff.replace(/\\n\\\\ No newline at end of file/, '')\n  \n  const diffList = gitDiff.trimEnd().split('\\n').reverse();\n  const lastLineFirstChar = diffList?.[0]?.[0];\n  const lastDiff =\n    diffList.find((item) => {\n      return /^@@ \\-\\d+,\\d+ \\+\\d+,\\d+ @@/g.test(item);\n    }) || '';\n\n  const [lastOldLineCount, lastNewLineCount] = lastDiff\n    .replace(/@@ \\-(\\d+),(\\d+) \\+(\\d+),(\\d+) @@.*/g, ($0, $1, $2, $3, $4) => {\n      return `${+$1 + +$2},${+$3 + +$4}`;\n    })\n    .split(',');\n  \n  if (!/^\\d+$/.test(lastOldLineCount) || !/^\\d+$/.test(lastNewLineCount)) {\n    return {\n      lastOldLine: -1,\n      lastNewLine: -1,\n      gitDiff,\n    };\n  }\n\n\n  const lastOldLine = lastLineFirstChar === '+' ? null : (parseInt(lastOldLineCount) || 0) - 1;\n  const lastNewLine = lastLineFirstChar === '-' ? null : (parseInt(lastNewLineCount) || 0) - 1;\n\n  return {\n    lastOldLine,\n    lastNewLine,\n    gitDiff,\n  };\n};\n\nreturn parseLastDiff($input.item.json.diff)\n"
            },
            "typeVersion": 2,
            "id": "0fca1318-9d05-47c8-83db-4464f45df43f"
        },
        {
            "name": "Post Discussions1",
            "type": "n8n-nodes-base.httpRequest",
            "position": [
                1280,
                720
            ],
            "parameters": {
                "url": "=https://gitlab.com/api/v4/projects/{{ $('Webhook').item.json[\"body\"][\"project_id\"] }}/merge_requests/{{ $('Webhook').item.json[\"body\"][\"merge_request\"][\"iid\"] }}/discussions",
                "method": "POST",
                "options": [],
                "sendBody": true,
                "contentType": "multipart-form-data",
                "sendHeaders": true,
                "bodyParameters": {
                    "parameters": [
                        {
                            "name": "body",
                            "value": "={{ $('Basic LLM Chain1').item.json[\"text\"] }}"
                        },
                        {
                            "name": "position[position_type]",
                            "value": "text"
                        },
                        {
                            "name": "position[old_path]",
                            "value": "={{ $('Split Out1').item.json.old_path }}"
                        },
                        {
                            "name": "position[new_path]",
                            "value": "={{ $('Split Out1').item.json.new_path }}"
                        },
                        {
                            "name": "position[start_sha]",
                            "value": "={{ $('Get Changes1').item.json.diff_refs.start_sha }}"
                        },
                        {
                            "name": "position[head_sha]",
                            "value": "={{ $('Get Changes1').item.json.diff_refs.head_sha }}"
                        },
                        {
                            "name": "position[base_sha]",
                            "value": "={{ $('Get Changes1').item.json.diff_refs.base_sha }}"
                        },
                        {
                            "name": "position[new_line]",
                            "value": "={{ $('Parse Last Diff Line1').item.json.lastNewLine || ''  }}"
                        },
                        {
                            "name": "position[old_line]",
                            "value": "={{ $('Parse Last Diff Line1').item.json.lastOldLine || '' }}"
                        }
                    ]
                },
                "headerParameters": {
                    "parameters": [
                        {
                            "name": "PRIVATE-TOKEN"
                        }
                    ]
                }
            },
            "typeVersion": 4.1,
            "id": "b0e5f468-c626-422a-907b-adbb2f9196ab"
        },
        {
            "name": "Need Review1",
            "type": "n8n-nodes-base.if",
            "position": [
                -320,
                760
            ],
            "parameters": {
                "options": [],
                "conditions": {
                    "options": {
                        "leftValue": "",
                        "caseSensitive": true,
                        "typeValidation": "strict"
                    },
                    "combinator": "and",
                    "conditions": [
                        {
                            "operator": {
                                "name": "filter.operator.equals",
                                "type": "string",
                                "operation": "equals"
                            },
                            "leftValue": "={{ $json.body.object_attributes.note }}",
                            "rightValue": "+0"
                        }
                    ]
                }
            },
            "typeVersion": 2,
            "id": "da50a5d5-9e15-4b10-887b-e952ac775afb"
        },
        {
            "name": "Basic LLM Chain1",
            "type": "@n8n/n8n-nodes-langchain.chainLlm",
            "position": [
                880,
                720
            ],
            "parameters": {
                "prompt": "=File path\uff1a{{ $('Skip File Change1').item.json.new_path }}\n\n```Original code\n {{ $json.originalCode }}\n```\nchange to\n```New code\n {{ $json.newCode }}\n```\nPlease review the code changes in this section:",
                "messages": {
                    "messageValues": [
                        {
                            "message": "# Overview:\n You are a senior programming expert Bot, responsible for reviewing code changes and providing review recommendations.\n At the beginning of the suggestion, it is necessary to clearly make a decision to \"reject\" or \"accept\" the code change, and rate the change in the format \"Change Score: Actual Score\", with a score range of 0-100 points.\n Then, point out the existing problems in concise language and a stern tone.\n If you feel it is necessary, you can directly provide the modified content.\n Your review proposal must use rigorous Markdown format."
                        }
                    ]
                }
            },
            "typeVersion": 1.2,
            "id": "fe5aa3d5-7b27-467f-8828-7a0c6211290a"
        },
        {
            "name": "Sticky Note4",
            "type": "n8n-nodes-base.stickyNote",
            "position": [
                1200,
                540
            ],
            "parameters": {
                "content": "Configuration note: update with your credentials or endpoint.",
                "color": "#FFF59D"
            },
            "typeVersion": 1,
            "id": "80fdb39b-3947-4c15-96f1-97ff254cb79b"
        }
    ],
    "connections": {
        "Code": {
            "main": [
                [
                    {
                        "node": "Basic LLM Chain1",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Webhook": {
            "main": [
                [
                    {
                        "node": "Need Review1",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Split Out1": {
            "main": [
                [
                    {
                        "node": "Skip File Change1",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Get Changes1": {
            "main": [
                [
                    {
                        "node": "Split Out1",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Need Review1": {
            "main": [
                [
                    {
                        "node": "Get Changes1",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Basic LLM Chain1": {
            "main": [
                [
                    {
                        "node": "Post Discussions1",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Skip File Change1": {
            "main": [
                [
                    {
                        "node": "Parse Last Diff Line1",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "OpenAI Chat Model1": {
            "ai_languageModel": [
                [
                    {
                        "node": "Basic LLM Chain1",
                        "type": "ai_languageModel",
                        "index": 0
                    }
                ]
            ]
        },
        "Parse Last Diff Line1": {
            "main": [
                [
                    {
                        "node": "Code",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        }
    },
    "n8n_version": "1.5.0"
}
Requirements
n8n instance, API credentials for connected services
Tags
#n8n #automation #workflow
Quick Actions
More in n8n Workflows