8
n8n 中文网amn8n.com

使用AI验证GitHub配置并将问题记录到表格和Slack

高级

这是一个DevOps, AI Summarization领域的自动化工作流,包含 22 个节点。主要使用 Code, Merge, Slack, Github, GoogleSheets 等节点。 使用GPT-4o-mini验证GitHub配置并将问题记录到表格和Slack

前置要求
  • Slack Bot Token 或 Webhook URL
  • GitHub Personal Access Token
  • Google Sheets API 凭证
  • OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "NDAfOVpefnu0AO5l",
  "meta": {
    "instanceId": "8443f10082278c46aa5cf3acf8ff0f70061a2c58bce76efac814b16290845177",
    "templateCredsSetupCompleted": true
  },
  "name": "使用 AI 验证 GitHub 配置并将问题记录到表格和 Slack",
  "tags": [],
  "nodes": [
    {
      "id": "00b8e7a5-b837-42dc-af23-9a2d06336a56",
      "name": "工作流概览",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1600,
        -352
      ],
      "parameters": {
        "color": 4,
        "width": 420,
        "height": 520,
        "content": "## 🔍 GitHub 配置验证器"
      },
      "typeVersion": 1
    },
    {
      "id": "22574d71-89eb-4872-a6ec-17127c7c13ac",
      "name": "设置指南",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2000,
        -336
      ],
      "parameters": {
        "color": 2,
        "width": 380,
        "height": 540,
        "content": "## ⚙️ 设置说明"
      },
      "typeVersion": 1
    },
    {
      "id": "54dbfff3-2cfb-4e0f-92de-eeb8ad467ef4",
      "name": "触发器配置",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1152,
        -432
      ],
      "parameters": {
        "color": 2,
        "width": 320,
        "height": 332,
        "content": "## 🎯 GitHub Webhook 触发器"
      },
      "typeVersion": 1
    },
    {
      "id": "eabed35d-8708-4e30-9f50-de35746032b3",
      "name": "文件获取逻辑",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -976,
        176
      ],
      "parameters": {
        "color": 2,
        "width": 300,
        "height": 320,
        "content": "## 📂 文件获取"
      },
      "typeVersion": 1
    },
    {
      "id": "7a19688d-84bd-4c7c-98bd-6649a0192ed4",
      "name": "合并策略",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -512,
        -480
      ],
      "parameters": {
        "color": 2,
        "width": 280,
        "height": 360,
        "content": "## 🔀 数据合并"
      },
      "typeVersion": 1
    },
    {
      "id": "a446599d-12b9-4438-8795-e2b93b9a026d",
      "name": "AI 分析详情",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -160,
        -480
      ],
      "parameters": {
        "color": 2,
        "width": 300,
        "height": 372,
        "content": "## 🤖 AI 配置分析"
      },
      "typeVersion": 1
    },
    {
      "id": "93354c1a-1de0-44ab-808f-cf9ddbcc1b07",
      "name": "数据处理",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        208,
        -448
      ],
      "parameters": {
        "color": 2,
        "width": 300,
        "height": 344,
        "content": "## 📊 结果处理"
      },
      "typeVersion": 1
    },
    {
      "id": "ee3b404c-ee6c-44d7-9123-c90b351f8160",
      "name": "表格配置",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        64
      ],
      "parameters": {
        "color": 2,
        "width": 320,
        "height": 388,
        "content": "## 📝 Google Sheets 架构"
      },
      "typeVersion": 1
    },
    {
      "id": "133a9c1b-749f-4114-84ed-a23fd3e77d86",
      "name": "Slack 警报",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        672,
        -496
      ],
      "parameters": {
        "color": 2,
        "width": 300,
        "height": 408,
        "content": "## 💬 Slack 通知"
      },
      "typeVersion": 1
    },
    {
      "id": "edf48d61-2eff-4e52-91c8-1ff181c99a4c",
      "name": "GitHub 推送或 PR 事件",
      "type": "n8n-nodes-base.githubTrigger",
      "position": [
        -1088,
        -96
      ],
      "webhookId": "8269983f-8b5a-4f61-87a7-fb4e58e11b6c",
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $json.githubOwner }}"
        },
        "events": [
          "pull_request",
          "push"
        ],
        "options": {},
        "repository": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.githubRepo }}"
        },
        "authentication": "oAuth2"
      },
      "credentials": {
        "githubOAuth2Api": {
          "id": "Ih8web2ia8dlggr6",
          "name": "GitHub account vivek"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "88bcabe0-4557-4f16-bba2-8e0523853fa3",
      "name": "获取仓库配置",
      "type": "n8n-nodes-base.github",
      "position": [
        -864,
        -192
      ],
      "webhookId": "9ad4450b-f494-4026-9ac9-d78c90169881",
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $json.repository.owner.login }}"
        },
        "filePath": "config/app-config.json",
        "resource": "file",
        "operation": "get",
        "repository": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.repository.name }}"
        },
        "authentication": "oAuth2",
        "additionalParameters": {}
      },
      "credentials": {
        "githubOAuth2Api": {
          "id": "Ih8web2ia8dlggr6",
          "name": "GitHub account vivek"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "fe9f94a2-d9c9-4b51-832c-ae018daa821e",
      "name": "获取 FAQ 引用配置",
      "type": "n8n-nodes-base.github",
      "position": [
        -864,
        0
      ],
      "webhookId": "b63918a7-17bc-4934-9007-3c8aa0b7aee9",
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $json.repository.owner.login }}"
        },
        "filePath": "faq-config.json",
        "resource": "file",
        "operation": "get",
        "repository": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.repository.name }}"
        },
        "authentication": "oAuth2",
        "additionalParameters": {}
      },
      "credentials": {
        "githubOAuth2Api": {
          "id": "Ih8web2ia8dlggr6",
          "name": "GitHub account vivek"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "aaf24ba6-6338-4cd7-8451-b4add12fff46",
      "name": "解析仓库配置 JSON",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -640,
        -192
      ],
      "parameters": {
        "options": {},
        "operation": "fromJson"
      },
      "typeVersion": 1
    },
    {
      "id": "de433781-a62a-41e8-af75-6f659cc0bee6",
      "name": "解析 FAQ 配置 JSON",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -640,
        0
      ],
      "parameters": {
        "options": {},
        "operation": "fromJson"
      },
      "typeVersion": 1
    },
    {
      "id": "136b7b5e-c6c8-42db-ba9f-fea68d9e3db4",
      "name": "合并配置文件",
      "type": "n8n-nodes-base.merge",
      "position": [
        -416,
        -96
      ],
      "parameters": {
        "mode": "combine",
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "1e9f58bd-32a7-4652-a224-08a013ad656e",
      "name": "AI 配置比较代理",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -128,
        -96
      ],
      "parameters": {
        "text": "=You are comparing two configuration files:\n\n**Repository Config (Actual):**\n```json\n{{ JSON.stringify($json[0], null, 2) }}\n```\n\n**FAQ Reference Config (Expected):**\n```json\n{{ JSON.stringify($json[1], null, 2) }}\n```\n\n**Task:**\nCompare both configs and identify all discrepancies. For each issue, provide:\n- Unique ID\n- Config key path\n- Expected value (from FAQ)\n- Actual value (from repo)\n- Issue type (mismatch, missing, deprecated, type_error, security)\n- Severity (critical, high, medium, low)\n- Clear recommendation\n- Confidence score (0.0-1.0)\n\n**Important:**\n- Return ONLY valid JSON (no markdown, no extra text)\n- Use the exact schema provided\n- If no issues found, return empty issues array\n- Focus on actionable discrepancies",
        "options": {
          "systemMessage": "You are an expert DevOps configuration auditor and automation specialist.\n\n**Your expertise:**\n- Deep knowledge of config file best practices\n- Security-first mindset for credentials and secrets\n- Understanding of environment-specific variations\n- Ability to distinguish critical vs cosmetic differences\n\n**Analysis approach:**\n1. Compare key-by-key between repo config and FAQ reference\n2. Identify missing keys, mismatched values, type changes\n3. Assess security implications (exposed secrets, weak settings)\n4. Determine business impact and urgency\n5. Provide specific, actionable recommendations\n\n**Severity guidelines:**\n- `critical`: Breaking changes, security vulnerabilities, missing required fields\n- `high`: Important mismatches affecting functionality\n- `medium`: Minor inconsistencies, deprecated but working\n- `low`: Cosmetic differences, optional improvements\n\n**Output requirements:**\n- Strict JSON format only\n- No markdown formatting\n- No explanatory text outside JSON\n- Clear, concise recommendations"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "f1dc1aff-caf8-4a0a-8c64-44fc69af9a22",
      "name": "OpenAI GPT-4o-mini",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -192,
        128
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {
          "maxTokens": 4000,
          "temperature": 0.3
        }
      },
      "credentials": {
        "openAiApi": {
          "id": "5Kzt6hGSZ1JHZqWN",
          "name": "OpenAi account 2"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "460f00a4-afff-4d0d-a922-cf6a865a5cd0",
      "name": "JSON 输出架构",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        80,
        128
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"result\": \"success or issues_found\",\n  \"summary\": \"Brief overview of findings\",\n  \"issues\": [\n    {\n      \"id\": \"unique_issue_id\",\n      \"key\": \"config.path.to.field\",\n      \"repo_value\": \"actual value in repository\",\n      \"faq_value\": \"expected value from FAQ\",\n      \"type\": \"mismatch | missing | deprecated | type_error | security\",\n      \"severity\": \"critical | high | medium | low\",\n      \"recommendation\": \"Specific action to resolve\",\n      \"confidence\": 0.95\n    }\n  ],\n  \"metadata\": {\n    \"checked_at\": \"ISO timestamp\",\n    \"comparison_source\": \"faq-config.json\"\n  }\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "f50d6106-4931-46ce-b0ec-c816c1e25c8b",
      "name": "对话记忆",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        -64,
        128
      ],
      "parameters": {
        "sessionKey": "=\"config_validation_\" & $('GitHub Push or PR Event').item.json.repository.name",
        "sessionIdType": "customKey",
        "contextWindowLength": 3
      },
      "typeVersion": 1.3
    },
    {
      "id": "b40a6c22-c78e-43ba-90c6-2db71c74fe02",
      "name": "格式化问题以供记录",
      "type": "n8n-nodes-base.code",
      "position": [
        288,
        -96
      ],
      "parameters": {
        "jsCode": "// Extract and format AI comparison results for Google Sheets\nconst allItems = $input.all();\nlet issues = [];\n\ntry {\n  for (const item of allItems) {\n    const aiResponse = item.json;\n    \n    // Handle different output structures\n    let outputData;\n    if (aiResponse.output) {\n      outputData = [aiResponse.output];\n    } else if (Array.isArray(aiResponse)) {\n      outputData = aiResponse.map(entry => entry.output || entry);\n    } else {\n      outputData = [aiResponse];\n    }\n\n    // Process each output entry\n    for (const output of outputData) {\n      if (output.issues && Array.isArray(output.issues) && output.issues.length > 0) {\n        \n        // Map issues to Google Sheets format\n        const mappedIssues = output.issues.map(issue => ({\n          timestamp: new Date().toISOString(),\n          configKey: issue.key || 'N/A',\n          faqReference: issue.faq_value || 'N/A',\n          actualConfig: issue.repo_value || 'N/A',\n          issueType: issue.type || 'unknown',\n          severity: issue.severity || 'N/A',\n          suggestion: issue.recommendation || 'N/A',\n          confidence: issue.confidence ? issue.confidence.toFixed(2) : 'N/A',\n          issueId: issue.id || `issue_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n          summary: output.summary || 'No summary provided'\n        }));\n        \n        issues.push(...mappedIssues);\n      }\n    }\n  }\n\n  // Handle case when no issues found\n  if (issues.length === 0) {\n    issues = [{\n      timestamp: new Date().toISOString(),\n      configKey: 'No Issues',\n      faqReference: 'N/A',\n      actualConfig: 'N/A',\n      issueType: 'success',\n      severity: 'N/A',\n      suggestion: 'All configurations match FAQ reference',\n      confidence: '1.00',\n      issueId: `success_${Date.now()}`,\n      summary: '✅ No discrepancies found - configs are in sync'\n    }];\n  }\n\n} catch (error) {\n  // Error handling\n  console.error('Error processing AI output:', error);\n  issues = [{\n    timestamp: new Date().toISOString(),\n    configKey: 'Processing Error',\n    faqReference: 'Could not parse AI response',\n    actualConfig: error.message,\n    issueType: 'error',\n    severity: 'high',\n    suggestion: `Review AI output manually. Error: ${error.message}`,\n    confidence: 'N/A',\n    issueId: `error_${Date.now()}`,\n    summary: '⚠️ Processing error occurred during validation'\n  }];\n}\n\n// Return formatted data for Google Sheets\nreturn issues.map(issue => ({ json: issue }));"
      },
      "typeVersion": 2
    },
    {
      "id": "be1fa800-8b48-4d21-a953-da7e3fc34eeb",
      "name": "记录到Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        512,
        -96
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "configKey",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "configKey",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "faqReference",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "faqReference",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "actualConfig",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "actualConfig",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "issueType",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "issueType",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "severity",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "severity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "suggestion",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "suggestion",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "confidence",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "confidence",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "issueId",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "issueId",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "Config Discrepancies"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Workflow Overview').item.json.googleSheetId }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "kpPEOLCGn963qpoh",
          "name": "automations@techdome.ai"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "4df1bf84-2753-4472-aef7-4623439bfcf0",
      "name": "发送 Slack 警报",
      "type": "n8n-nodes-base.slack",
      "position": [
        736,
        -96
      ],
      "webhookId": "ef90cacf-14c2-48cc-905f-b06d2c649b8d",
      "parameters": {
        "text": "=⚠️ *Config Mismatch Detected!*\n\n*Repository:* {{ $('GitHub Push or PR Event').item.json.repository.full_name }}\n*Branch:* {{ $('GitHub Push or PR Event').item.json.ref }}\n*Commit:* {{ $('GitHub Push or PR Event').item.json.after.substring(0, 7) }}\n\n━━━━━━━━━━━━━━━━━━━━\n\n{{ $('Format Issues for Logging').all().slice(0, 3).map((item, idx) => {\n  const severity = item.json.severity;\n  const emoji = severity === 'critical' ? '🔴' : severity === 'high' ? '🟠' : severity === 'medium' ? '🟡' : '🟢';\n  return `${emoji} *Issue ${idx + 1}: ${item.json.configKey}*\\n• Type: ${item.json.issueType}\\n• Severity: ${item.json.severity}\\n• Expected: \\`${item.json.faqReference}\\`\\n• Actual: \\`${item.json.actualConfig}\\`\\n• Fix: ${item.json.suggestion}\\n`;\n}).join('\\n') }}\n\n*Total Issues:* {{ $('Format Issues for Logging').all().length }}\n\n📊 *Full Report:* <{{ $('Workflow Overview').item.json.sheetsReportUrl }}|View in Google Sheets>\n\n_Scanned: {{ new Date().toLocaleString('en-US', { timeZone: 'UTC' }) }} UTC_",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Workflow Overview').item.json.slackChannel }}"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "rNqvWj9TfChPVRYY",
          "name": "Slack account vivek"
        }
      },
      "typeVersion": 2.2
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "f61bd7be-e6be-425b-8929-bc5536255b8f",
  "connections": {
    "JSON Output Schema": {
      "ai_outputParser": [
        [
          {
            "node": "AI Config Comparison Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Merge Config Files": {
      "main": [
        [
          {
            "node": "AI Config Comparison Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI GPT-4o-mini": {
      "ai_languageModel": [
        [
          {
            "node": "AI Config Comparison Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Conversation Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Config Comparison Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Log to Google Sheets": {
      "main": [
        [
          {
            "node": "Send Slack Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse FAQ Config JSON": {
      "main": [
        [
          {
            "node": "Merge Config Files",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Parse Repo Config JSON": {
      "main": [
        [
          {
            "node": "Merge Config Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Repository Config": {
      "main": [
        [
          {
            "node": "Parse Repo Config JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GitHub Push or PR Event": {
      "main": [
        [
          {
            "node": "Fetch Repository Config",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch FAQ Reference Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Issues for Logging": {
      "main": [
        [
          {
            "node": "Log to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Config Comparison Agent": {
      "main": [
        [
          {
            "node": "Format Issues for Logging",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch FAQ Reference Config": {
      "main": [
        [
          {
            "node": "Parse FAQ Config JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

高级 - 开发运维, AI 摘要总结

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量22
分类2
节点类型12
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

作者
Rahul Joshi

Rahul Joshi

@rahul08

Rahul Joshi is a seasoned technology leader specializing in the n8n automation tool and AI-driven workflow automation. With deep expertise in building open-source workflow automation and self-hosted automation platforms, he helps organizations eliminate manual processes through intelligent n8n ai agent automation solutions.

外部链接
在 n8n.io 查看

分享此工作流