{ "updatedAt": "2026-05-07T00:49:43.226Z", "createdAt": "2026-05-07T00:49:43.226Z", "id": "CFYWbBRx9RPf4HjS", "name": "Git Commit \u2192 AI Summary \u2192 Gotify v1.0", "description": null, "active": true, "isArchived": false, "nodes": [ { "parameters": { "httpMethod": "POST", "path": "git/push", "options": {} }, "id": "fe377ac9-adcf-427d-a096-679f5469f8d8", "name": "Git Push Webhook", "type": "n8n-nodes-base.webhook", "typeVersion": 2, "position": [ 0, 0 ], "webhookId": "d1d31942-6fe8-48a2-aab7-7eefaf800420" }, { "parameters": { "jsCode": "const data = $input.first().json;\nconst body = data.body || data;\n\n// Works with Gitea, Forgejo, GitHub, and GitLab webhook payloads\nconst repo = body.repository?.full_name || body.repository?.name || body.project?.path_with_namespace || 'unknown-repo';\nconst branch = (body.ref || '').replace('refs/heads/', '');\nconst pusher = body.pusher?.name || body.pusher?.login || body.user_name || body.sender?.login || 'unknown';\n\n// Extract commits\nconst commits = (body.commits || []).map(c => ({\n id: (c.id || c.sha || '').substring(0, 7),\n message: (c.message || '').split('\\n')[0],\n author: c.author?.name || c.author?.username || 'unknown',\n added: (c.added || []).length,\n modified: (c.modified || []).length,\n removed: (c.removed || []).length\n}));\n\nconst commitSummary = commits.map(c =>\n `${c.id}: ${c.message} (by ${c.author}) [+${c.added} ~${c.modified} -${c.removed}]`\n).join('\\n');\n\nreturn [{\n json: {\n repo,\n branch,\n pusher,\n commitCount: commits.length,\n commitSummary,\n compareUrl: body.compare_url || body.compare || ''\n }\n}];" }, "id": "8dda4f14-9563-490f-89b3-aef80f64ba0b", "name": "Parse Git Payload", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 224, 0 ] }, { "parameters": { "method": "POST", "url": "http://10.5.30.6:4000/v1/chat/completions", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Content-Type", "value": "application/json" }, { "name": "Authorization", "value": "={{'Bearer ' + $env.LITELLM_API_KEY}}" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"model\": \"light\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are a git commit summarizer. Given a list of commits pushed to a repo, write a 1-2 sentence summary of what changed. Be concise and technical. Focus on the purpose of the changes, not just listing files.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Repository: {{ $json.repo }}\\nBranch: {{ $json.branch }}\\nPushed by: {{ $json.pusher }}\\n\\nCommits ({{ $json.commitCount }}):\\n{{ $json.commitSummary }}\"\n }\n ],\n \"max_tokens\": 150,\n \"temperature\": 0.2\n}", "options": {} }, "id": "c6b2b71b-2612-4ef7-8561-8adccbfa9be8", "name": "AI Summarize Commits", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 448, 0 ] }, { "parameters": { "jsCode": "const response = $input.first().json;\nconst gitData = $('Parse Git Payload').first().json;\nconst summary = response.choices?.[0]?.message?.content || 'Could not summarize';\n\nconst title = `\ud83d\udd00 ${gitData.repo}:${gitData.branch} (${gitData.commitCount} commit${gitData.commitCount !== 1 ? 's' : ''})`;\n\nreturn [{\n json: {\n title,\n message: `${summary}\\n\\nPushed by: ${gitData.pusher}`,\n priority: 3\n }\n}];" }, "id": "94f5c120-0ae6-4a23-9556-d4f564f9f967", "name": "Format Notification", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 672, 0 ] }, { "parameters": { "message": "={{ $json.message }}", "additionalFields": { "priority": "={{ $json.priority }}", "title": "={{ $json.title }}" }, "options": { "contentType": "text/plain" } }, "id": "4f731683-574c-4a39-84fe-025280193ba1", "name": "Push to Gotify", "type": "n8n-nodes-base.gotify", "typeVersion": 1, "position": [ 880, 0 ], "credentials": { "gotifyApi": { "id": "SETUP_REQUIRED", "name": "Git Commits" } } } ], "connections": { "Git Push Webhook": { "main": [ [ { "node": "Parse Git Payload", "type": "main", "index": 0 } ] ] }, "Parse Git Payload": { "main": [ [ { "node": "AI Summarize Commits", "type": "main", "index": 0 } ] ] }, "AI Summarize Commits": { "main": [ [ { "node": "Format Notification", "type": "main", "index": 0 } ] ] }, "Format Notification": { "main": [ [ { "node": "Push to Gotify", "type": "main", "index": 0 } ] ] } }, "settings": { "executionOrder": "v1", "binaryMode": "separate" }, "staticData": null, "meta": null, "pinData": {}, "versionId": "61fca126-b5dd-4425-b0ee-c621d3ed58af", "activeVersionId": "61fca126-b5dd-4425-b0ee-c621d3ed58af", "versionCounter": 12, "triggerCount": 1, "tags": [ { "updatedAt": "2026-05-07T00:49:41.640Z", "createdAt": "2026-05-07T00:49:41.640Z", "id": "36CVfQVO41QQyOmh", "name": "notifications" }, { "updatedAt": "2026-05-07T00:49:41.638Z", "createdAt": "2026-05-07T00:49:41.638Z", "id": "2oumYE52ygvhrieZ", "name": "git" }, { "updatedAt": "2026-05-06T22:38:51.678Z", "createdAt": "2026-05-06T22:38:51.678Z", "id": "S9FxzVfHLsHmyzyt", "name": "ai" } ], "shared": [ { "updatedAt": "2026-05-07T00:49:43.226Z", "createdAt": "2026-05-07T00:49:43.226Z", "role": "workflow:owner", "workflowId": "CFYWbBRx9RPf4HjS", "projectId": "dxCRnBdX5uJizCGa", "project": { "updatedAt": "2026-05-06T01:10:37.484Z", "createdAt": "2026-05-06T01:08:07.721Z", "id": "dxCRnBdX5uJizCGa", "name": "Wilfred Fizzlepoof ", "type": "personal", "icon": null, "description": null, "creatorId": "47b2227f-2fc2-4a08-bd35-ea157b92df0d" } } ], "versionMetadata": { "name": "Version 61fca126", "description": "" } }