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 →
{
"name": "jump-section: Comment Fix Pipeline",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "comment-fix",
"responseMode": "onReceived",
"responseData": "noData",
"options": {
"rawBody": true
}
},
"id": "webhook-trigger",
"name": "Webhook: PR Comment Event",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1.1,
"position": [
240,
300
]
},
{
"parameters": {
"jsCode": "// GitHub Actions(slash-fix.yml)\uac00 \uacc4\uc0b0\ud55c X-Hub-Signature-256\uc744 \uac80\uc99d\ud55c\ub2e4.\n// rawBody \uc635\uc158\uc73c\ub85c \ubc1b\uc740 \uc6d0\ubcf8 \ubc14\uc774\ud2b8\ub85c HMAC\uc744 \uacc4\uc0b0\ud574\uc57c GitHub\uc774 \ubcf4\ub0b8 \uc11c\uba85\uacfc \uc815\ud655\ud788 \uc77c\uce58\ud55c\ub2e4\n// (\ud30c\uc2f1 \ud6c4 \uc7ac\uc9c1\ub82c\ud654\ub41c JSON\uc740 \ubc14\uc774\ud2b8\uac00 \ub2ec\ub77c\uc838 \uc11c\uba85\uc774 \uae68\uc9c8 \uc218 \uc788\uc74c).\n// $binary \ud544\ub4dc \uc704\uce58\ub294 n8n \ubc84\uc804\uc5d0 \ub530\ub77c \ub2e4\ub97c \uc218 \uc788\uc73c\ub2c8 \uc124\uce58\ub41c \ubc84\uc804\uc73c\ub85c \uc7ac\ud655\uc778\ud560 \uac83.\nconst crypto = require('crypto');\nconst secret = $env.GITHUB_WEBHOOK_SECRET;\n\nconst item = $input.first();\nconst rawBuffer = await this.helpers.getBinaryDataBuffer(0, 'data');\nconst rawBody = rawBuffer.toString('utf8');\nconst signatureHeader = (item.json.headers && item.json.headers['x-hub-signature-256']) || '';\n\nconst expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');\n\nconst sigBuf = Buffer.from(signatureHeader);\nconst expBuf = Buffer.from(expected);\nconst valid = sigBuf.length === expBuf.length && crypto.timingSafeEqual(sigBuf, expBuf);\n\nif (!valid) {\n // \uc11c\uba85 \ubd88\uc77c\uce58 - \ud750\ub984\uc744 \uc911\ub2e8\ud55c\ub2e4 (\ube48 \ubc30\uc5f4\uc744 \ubc18\ud658\ud558\uba74 \uc774\ud6c4 \ub178\ub4dc\uac00 \uc2e4\ud589\ub418\uc9c0 \uc54a\uc74c)\n return [];\n}\n\nreturn [{ json: JSON.parse(rawBody) }];"
},
"id": "verify-github-signature",
"name": "GitHub \uc11c\uba85 \uac80\uc99d",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
460,
300
]
},
{
"parameters": {
"conditions": {
"conditions": [
{
"id": "action-check",
"leftValue": "={{ $json.action }}",
"rightValue": "created",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
}
},
"id": "check-action",
"name": "IF: action=created",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
680,
300
]
},
{
"parameters": {
"jsCode": "const body = $input.first().json;\nconst comment = body.comment;\nconst repo = body.repository;\n\nconst commentBody = (comment.body || '').trim();\nlet command = null;\n\nif (commentBody === '/fix-build') command = 'fix-build';\nelse if (commentBody === '/fix-lint') command = 'fix-lint';\nelse if (commentBody === '/fix' && comment.in_reply_to_id) command = 'fix';\n\nif (!command) return [];\n\nlet prNumber, prTitle, prUrl, headBranch, headSha;\n\nif (body.pull_request) {\n // pull_request_review_comment \uc774\ubca4\ud2b8\n const pr = body.pull_request;\n prNumber = pr.number;\n prTitle = pr.title;\n prUrl = pr.html_url;\n headBranch = pr.head.ref;\n headSha = pr.head.sha;\n} else if (body.issue && body.issue.pull_request) {\n // issue_comment \uc774\ubca4\ud2b8 (\uc77c\ubc18 PR \ucf54\uba58\ud2b8)\n prNumber = body.issue.number;\n prTitle = body.issue.title;\n prUrl = body.issue.html_url;\n\n // headBranch/headSha\ub294 API\ub85c \uc870\ud68c (whitelist-guard\uc5d0\uc11c \ubcf4\ud638 \ube0c\ub79c\uce58 \uc5ec\ubd80\ub97c \ud310\ub2e8\ud558\ub294 \ub370 \ud544\uc694)\n const token = $env.GITHUB_TOKEN;\n const prData = await new Promise((resolve, reject) => {\n const https = require('https');\n const req = https.request({\n hostname: 'api.github.com',\n path: `/repos/${repo.owner.login}/${repo.name}/pulls/${prNumber}`,\n method: 'GET',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Accept': 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n 'User-Agent': 'n8n-jump-section'\n }\n }, (res) => {\n let data = '';\n res.on('data', chunk => data += chunk);\n res.on('end', () => {\n if (res.statusCode >= 400) { reject(new Error(`HTTP ${res.statusCode}: ${data}`)); return; }\n try { resolve(JSON.parse(data)); } catch (e) { reject(new Error('Invalid JSON: ' + data.slice(0, 200))); }\n });\n });\n req.setTimeout(15000, () => { req.destroy(); reject(new Error('Request timeout')); });\n req.on('error', reject);\n req.end();\n });\n\n headBranch = prData.head.ref;\n headSha = prData.head.sha;\n} else {\n return [];\n}\n\nreturn [{\n json: {\n command,\n prNumber,\n prTitle,\n prUrl,\n headBranch,\n headSha,\n repoOwner: repo.owner.login,\n repoName: repo.name,\n commentId: comment.id,\n filePath: comment.path || null,\n inReplyToId: comment.in_reply_to_id || null\n }\n}];"
},
"id": "detect-command",
"name": "\ucee4\ub9e8\ub4dc \uac10\uc9c0",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
900,
300
]
},
{
"parameters": {
"conditions": {
"combinator": "and",
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "is-protected",
"leftValue": "={{ $json.headBranch }}",
"rightValue": "^(main|master|develop|release/.*)$",
"operator": {
"type": "string",
"operation": "regex"
}
}
]
}
},
"id": "whitelist-guard",
"name": "IF: \ubcf4\ud638 \ube0c\ub79c\uce58?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1120,
300
]
},
{
"parameters": {
"jsCode": "// Generic V2 \uc11c\uba85: HMAC-SHA256(\"<timestamp>.<body>\"), X-Webhook-Signature-V2 + X-Webhook-Timestamp \ud5e4\ub354\n// (Hermes \uacf5\uc2dd \ubb38\uc11c \uad8c\uc7a5 \ubc29\uc2dd - 300\ucd08 \uc774\ub0b4 \ud0c0\uc784\uc2a4\ud0ec\ud504\ub9cc \ud5c8\uc6a9\ud574 \uc7ac\uc804\uc1a1 \uacf5\uaca9\uc744 \ub9c9\ub294\ub2e4)\nconst crypto = require('crypto');\nconst secret = $env.HERMES_WEBHOOK_SECRET;\nconst ctx = $input.first().json;\n\n// \ud654\uc774\ud2b8\ub9ac\uc2a4\ud2b8\ub41c \ud544\ub4dc\ub9cc \uba85\uc2dc\uc801\uc73c\ub85c \uad6c\uc131\ud574 \ubcf4\ub0b8\ub2e4 (\uc6d0\ubcf8 GitHub \uc774\ubca4\ud2b8\ub97c \ud1b5\uc9f8\ub85c \uc804\ub2ec\ud558\uc9c0 \uc54a\uc74c)\nconst payload = {\n correlation_id: `cf-${ctx.repoName}-${ctx.prNumber}-${ctx.commentId}-${Date.now()}`,\n command: ctx.command,\n repo: { owner: ctx.repoOwner, name: ctx.repoName },\n pr: { number: ctx.prNumber, title: ctx.prTitle, url: ctx.prUrl },\n branch: { head_ref: ctx.headBranch, head_sha: ctx.headSha },\n comment: { id: ctx.commentId, path: ctx.filePath, in_reply_to_id: ctx.inReplyToId },\n callback: { url: $env.HERMES_CALLBACK_URL }\n};\n\nconst body = JSON.stringify(payload);\nconst timestamp = Math.floor(Date.now() / 1000).toString();\nconst signature = crypto.createHmac('sha256', secret).update(`${timestamp}.${body}`).digest('hex');\n\nreturn [{\n json: {\n url: `${$env.HERMES_BASE_URL}/webhooks/${ctx.command}`,\n timestamp,\n signature,\n body\n }\n}];"
},
"id": "sign-hermes-request",
"name": "Hermes \uc694\uccad \uc11c\uba85 (HMAC-V2)",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1340,
460
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $json.url }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "X-Webhook-Timestamp",
"value": "={{ $json.timestamp }}"
},
{
"name": "X-Webhook-Signature-V2",
"value": "={{ $json.signature }}"
}
]
},
"sendBody": true,
"specifyBody": "raw",
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ $json.body }}",
"options": {}
},
"id": "call-hermes",
"name": "Hermes: \uc6f9\ud6c5 \ud638\ucd9c",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1560,
460
]
}
],
"connections": {
"Webhook: PR Comment Event": {
"main": [
[
{
"node": "GitHub \uc11c\uba85 \uac80\uc99d",
"type": "main",
"index": 0
}
]
]
},
"GitHub \uc11c\uba85 \uac80\uc99d": {
"main": [
[
{
"node": "IF: action=created",
"type": "main",
"index": 0
}
]
]
},
"IF: action=created": {
"main": [
[
{
"node": "\ucee4\ub9e8\ub4dc \uac10\uc9c0",
"type": "main",
"index": 0
}
],
[]
]
},
"\ucee4\ub9e8\ub4dc \uac10\uc9c0": {
"main": [
[
{
"node": "IF: \ubcf4\ud638 \ube0c\ub79c\uce58?",
"type": "main",
"index": 0
}
]
]
},
"IF: \ubcf4\ud638 \ube0c\ub79c\uce58?": {
"main": [
[],
[
{
"node": "Hermes \uc694\uccad \uc11c\uba85 (HMAC-V2)",
"type": "main",
"index": 0
}
]
]
},
"Hermes \uc694\uccad \uc11c\uba85 (HMAC-V2)": {
"main": [
[
{
"node": "Hermes: \uc6f9\ud6c5 \ud638\ucd9c",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"tags": [
{
"name": "jump-section"
},
{
"name": "comment-fix"
},
{
"name": "hermes"
}
]
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
How this works
This workflow automates the resolution of common code issues in pull requests by detecting specific commands in comments and applying targeted fixes, saving developers hours of manual debugging and ensuring cleaner code merges. It is ideal for teams using GitHub or similar platforms who want to streamline their review process without interrupting their flow. The key step involves a webhook trigger that captures new PR comments, followed by conditional checks to identify fix requests, culminating in an HTTP request to a service like Gemini for generating precise code corrections based on the project's context.
Use this pipeline when your repository frequently encounters repeatable errors such as build failures or linting violations that can be addressed via AI-assisted patches, particularly in collaborative environments with multiple contributors. Avoid it for complex, context-heavy bugs requiring human oversight or in non-code repositories. Common variations include adapting the command detection for different issue types or integrating with additional tools like Slack for fix notifications.
About this workflow
jump-section: Comment Fix Pipeline. Uses httpRequest. Webhook trigger; 24 nodes.
Source: https://github.com/bae080311/jump-section/blob/c566471882fa8b8f0e4d00704693b7c92d62c519/.n8n/workflows/comment-fix-pipeline.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Portfolio Orchestrator. Uses httpRequest. Webhook trigger; 59 nodes.
GitHub Issues Router (Linear / Jira / ClickUp). Uses stickyNote, httpRequest, respondToWebhook. Webhook trigger; 23 nodes.
Form to CRM Lead Router (Pipedrive / HubSpot / Salesforce). Uses stickyNote, httpRequest, respondToWebhook. Webhook trigger; 22 nodes.
Calendly to CRM Sync (Pipedrive / HubSpot / Salesforce). Uses stickyNote, httpRequest, respondToWebhook. Webhook trigger; 22 nodes.
Reputation Engine — Technical SEO Implementer. Uses httpRequest. Webhook trigger; 22 nodes.