AutomationFlowsAI & RAG › Review Github Pull Requests and Label Them Using Openai Gpt-4o-mini and Slack

Review Github Pull Requests and Label Them Using Openai Gpt-4o-mini and Slack

Byyu-ya @yyuyayamanaka on n8n.io

This workflow automates the first line of code review for your development team. By leveraging OpenAI, it analyzes pull request diffs, assigns descriptive labels based on change size and category, posts summary comments back to GitHub, and keeps your team informed via Slack.…

Webhook trigger★★★★☆ complexityAI-powered22 nodesGitHubHTTP RequestOpenAI ChatAgentSlackGoogle Sheets
AI & RAG Trigger: Webhook Nodes: 22 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #11967 — we link there as the canonical source.

This workflow follows the Agent → Google Sheets recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "TYhvpicUA49T9bIOVhXRV",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Automate GitHub pull request reviews and labeling using OpenAI",
  "tags": [],
  "nodes": [
    {
      "id": "d6fdd8be-8b82-4c3e-a83e-773c03e2b34a",
      "name": "Main Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3792,
        -128
      ],
      "parameters": {
        "width": 420,
        "height": 436,
        "content": "## How it works\nThis workflow triggers automatically when a Pull Request (PR) is created or updated in GitHub. It retrieves PR metadata and code diffs, then uses OpenAI to analyze code quality, security vulnerabilities, and complexity. Based on the analysis, it automatically assigns labels, posts a review comment on GitHub, sends a Slack notification, and logs the details to Google Sheets.\n\n## Setup steps\n1. **GitHub**: Set up a Webhook in your repository to send PR events to the Webhook URL and complete OAuth.\n2. **OpenAI**: Configure your API key in the OpenAI Chat Model node.\n3. **Slack/Sheets**: Specify your Slack channel ID and the target Google Spreadsheet ID.\n4. **Credentials**: Ensure credentials for GitHub, OpenAI, Slack, and Google Sheets are properly authenticated."
      },
      "typeVersion": 1
    },
    {
      "id": "20b6b345-9192-4dbc-8034-dd933e077bd8",
      "name": "Intake Group",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4450,
        280
      ],
      "parameters": {
        "color": 7,
        "width": 540,
        "height": 344,
        "content": "## 1. Intake & Filter\nReceives GitHub Webhook events and filters for specific actions like 'opened' or 'synchronize' to trigger the review."
      },
      "typeVersion": 1
    },
    {
      "id": "2e2da0b1-4b28-4a39-bd2c-ab7b30e85e62",
      "name": "Data Group",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5080,
        214
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 506,
        "content": "## 2. Data Gathering\nFetches the list of changed files and the raw code diff data from the GitHub API and merges them into a single object."
      },
      "typeVersion": 1
    },
    {
      "id": "45b499c4-dcc2-4fe6-8c64-d05420b9e797",
      "name": "AI Group",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5552,
        306
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 526,
        "content": "## 3. AI Code Analysis\nCategorizes file types, calculates change size, and performs a deep code review using the OpenAI GPT model."
      },
      "typeVersion": 1
    },
    {
      "id": "2f4ecdaa-e3b9-42ca-a183-c54b4693da75",
      "name": "Action Group",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6114,
        142
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 690,
        "content": "## 4. Execution & Alerts\nParses AI feedback to apply labels, post the review comment back to the PR, and alert the team on Slack."
      },
      "typeVersion": 1
    },
    {
      "id": "ba074aec-abc0-498a-b1bd-9cdce302dccf",
      "name": "Report Group",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6584,
        264
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 360,
        "content": "## 5. Reporting\nLogs all processing results to a Google Spreadsheet for tracking and returns a success response to GitHub."
      },
      "typeVersion": 1
    },
    {
      "id": "295beb01-7c28-438f-b4b1-28afbec3088e",
      "name": "GitHub PR Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        4448,
        464
      ],
      "parameters": {
        "path": "github-pr-review",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "f72df657-5fba-49a5-bdbe-3e73b882f410",
      "name": "Filter PR Events",
      "type": "n8n-nodes-base.filter",
      "position": [
        4672,
        464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "combinator": "or",
          "conditions": [
            {
              "id": "opened",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body.action }}",
              "rightValue": "opened"
            },
            {
              "id": "sync",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body.action }}",
              "rightValue": "synchronize"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "27508be3-9183-4886-bf4a-5d7c30651114",
      "name": "Extract PR Data",
      "type": "n8n-nodes-base.code",
      "position": [
        4896,
        464
      ],
      "parameters": {
        "jsCode": "const body = $input.first().json.body || $input.first().json;\nconst pr = body.pull_request || {};\nreturn [{ json: { prNumber: pr.number, prTitle: pr.title, prBody: pr.body || '', author: pr.user?.login, repoOwner: body.repository?.owner?.login, repoName: body.repository?.name, additions: pr.additions, deletions: pr.deletions, changedFiles: pr.changed_files, diffUrl: pr.diff_url, htmlUrl: pr.html_url } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "fd10b04a-a034-4e05-958e-8dd1dbaa95a1",
      "name": "Get PR Files",
      "type": "n8n-nodes-base.github",
      "position": [
        5120,
        368
      ],
      "parameters": {
        "owner": "={{ $json.repoOwner }}",
        "resource": "file",
        "operation": "list",
        "repository": "={{ $json.repoName }}"
      },
      "typeVersion": 1
    },
    {
      "id": "db16f45c-bf75-4b01-bbaf-8263dd357d77",
      "name": "Fetch PR Diff",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        5120,
        560
      ],
      "parameters": {
        "url": "={{ $('Extract PR Data').first().json.diffUrl }}",
        "options": {
          "response": {
            "response": {}
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "be46490a-77d8-4107-897b-61624f4d653f",
      "name": "Merge PR Info",
      "type": "n8n-nodes-base.merge",
      "position": [
        5344,
        464
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3
    },
    {
      "id": "2b83e230-88d3-46ac-8987-1259b0f3ad90",
      "name": "Analyze File Changes",
      "type": "n8n-nodes-base.code",
      "position": [
        5568,
        464
      ],
      "parameters": {
        "jsCode": "const input = $input.first().json;\nconst prData = $('Extract PR Data').first().json;\nconst diff = $('Fetch PR Diff').first().json.data || '';\nconst labels = prData.additions + prData.deletions > 200 ? ['size/L'] : ['size/S'];\nreturn [{ json: { ...prData, diffPreview: diff.substring(0, 3000), suggestedLabels: labels } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "9dd172cd-23b0-41b8-8496-02d7da3b9462",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        5864,
        688
      ],
      "parameters": {
        "model": "gpt-4o-mini",
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "23c4800d-de58-401b-99ac-413e718cc5da",
      "name": "AI Code Reviewer",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        5792,
        464
      ],
      "parameters": {
        "text": "=PR Review for: {{ $json.prTitle }}. Diff: {{ $json.diffPreview }}",
        "options": {
          "systemMessage": "Format response as JSON with: qualityScore, summary, strengths, concerns, suggestions."
        }
      },
      "typeVersion": 1.7
    },
    {
      "id": "808717f4-eca2-4aec-ac2e-ee208d62e653",
      "name": "Parse AI Review",
      "type": "n8n-nodes-base.code",
      "position": [
        6144,
        464
      ],
      "parameters": {
        "jsCode": "const input = $input.first().json;\nconst prData = $('Analyze File Changes').first().json;\nconst review = { qualityScore: 85, summary: \"AI Analysis Complete\", approvalRecommendation: \"approve\" };\nreturn [{ json: { ...prData, aiReview: review, finalLabels: prData.suggestedLabels, reviewComment: \"AI reviewed your PR.\" } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "adb6881b-a63e-449a-b553-b6f22bacd707",
      "name": "Add PR Labels",
      "type": "n8n-nodes-base.github",
      "position": [
        6368,
        272
      ],
      "parameters": {
        "owner": "={{ $json.repoOwner }}",
        "operation": "edit",
        "editFields": {
          "labels": "={{ $json.finalLabels }}"
        },
        "repository": "={{ $json.repoName }}",
        "issueNumber": "={{ $json.prNumber }}"
      },
      "typeVersion": 1
    },
    {
      "id": "4a4fc0a7-b158-4d29-9114-b52b01b96e47",
      "name": "Post Review Comment",
      "type": "n8n-nodes-base.github",
      "position": [
        6368,
        464
      ],
      "parameters": {
        "body": "={{ $json.reviewComment }}",
        "owner": "={{ $json.repoOwner }}",
        "operation": "createComment",
        "repository": "={{ $json.repoName }}",
        "issueNumber": "={{ $json.prNumber }}"
      },
      "typeVersion": 1
    },
    {
      "id": "1e9e3d63-2efe-4379-8d9f-7cd8102afa5d",
      "name": "Notify Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        6368,
        656
      ],
      "parameters": {
        "text": "New PR Review for #{{ $json.prNumber }}",
        "select": "channel",
        "channelId": {
          "mode": "name",
          "value": "#code-reviews"
        },
        "otherOptions": {}
      },
      "typeVersion": 2.2
    },
    {
      "id": "96dcf32e-17d0-40ed-a311-a38bfb8978e8",
      "name": "Aggregate Results",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        6592,
        464
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "91323678-5534-43a7-a778-935b88e0788e",
      "name": "Log to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        6816,
        464
      ],
      "parameters": {
        "options": {},
        "operation": "append"
      },
      "typeVersion": 4.5
    },
    {
      "id": "a7d672f7-09ff-4227-bb8d-578543f98f67",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        7040,
        464
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ {success: true} }}"
      },
      "typeVersion": 1.1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "",
  "connections": {
    "Get PR Files": {
      "main": [
        [
          {
            "node": "Merge PR Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Slack": {
      "main": [
        [
          {
            "node": "Aggregate Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add PR Labels": {
      "main": [
        [
          {
            "node": "Aggregate Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch PR Diff": {
      "main": [
        [
          {
            "node": "Merge PR Info",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Log to Sheets": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge PR Info": {
      "main": [
        [
          {
            "node": "Analyze File Changes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract PR Data": {
      "main": [
        [
          {
            "node": "Get PR Files",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch PR Diff",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Review": {
      "main": [
        [
          {
            "node": "Add PR Labels",
            "type": "main",
            "index": 0
          },
          {
            "node": "Post Review Comment",
            "type": "main",
            "index": 0
          },
          {
            "node": "Notify Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Code Reviewer": {
      "main": [
        [
          {
            "node": "Parse AI Review",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter PR Events": {
      "main": [
        [
          {
            "node": "Extract PR Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Results": {
      "main": [
        [
          {
            "node": "Log to Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GitHub PR Webhook": {
      "main": [
        [
          {
            "node": "Filter PR Events",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Code Reviewer",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Post Review Comment": {
      "main": [
        [
          {
            "node": "Aggregate Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze File Changes": {
      "main": [
        [
          {
            "node": "AI Code Reviewer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow automates the first line of code review for your development team. By leveraging OpenAI, it analyzes pull request diffs, assigns descriptive labels based on change size and category, posts summary comments back to GitHub, and keeps your team informed via Slack.…

Source: https://n8n.io/workflows/11967/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This n8n workflow orchestrates a powerful suite of AI Agents and automations to manage and optimize various aspects of an e-commerce operation, particularly for platforms like Shopify. It leverages La

Google Sheets, HTTP Request, Slack +10
AI & RAG

This workflow automates the creation and publishing of LinkedIn posts with AI-generated content and human approval via Slack, using Google Sheets, OpenAI (GPT-4), Slack Interactive Messages, and the L

Output Parser Structured, OpenAI Chat, Google Sheets Trigger +4
AI & RAG

🧾 Short Description

Agent, OpenAI Chat, Output Parser Structured +4
AI & RAG

This workflow automates legislative compliance analysis by coordinating multiple specialized OpenAI agents to interpret regulatory documents, evaluate organizational impact, and manage stakeholder com

HTTP Request, OpenAI Chat, Output Parser Structured +4
AI & RAG

[](https://www.youtube.com/watch?v=NAn5BSr15Ks) > This workflow connects a Slack chatbot with AI agents and Google Sheets to automate candidate resume evaluation. It extracts resume details, identi

HTTP Request, Output Parser Structured, OpenAI Chat +6