{ "name": "Extension Sync: Daily Drift Check", "nodes": [ { "parameters": { "rule": { "interval": [ { "triggerAtHour": 7 } ] } }, "id": "schedule-trigger", "name": "Daily 07:00", "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.2, "position": [0, 0] }, { "parameters": { "method": "POST", "url": "https://platform.dev.marcus-law.co.il/sync", "sendBody": true, "bodyParameters": { "parameters": [] }, "options": { "timeout": 120000 } }, "id": "call-sync-api", "name": "Call Platform Sync", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [220, 0] }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" }, "conditions": [ { "id": "drift-check", "leftValue": "={{ $json.total_drifts }}", "rightValue": 0, "operator": { "type": "number", "operation": "gt" } } ], "combinator": "and" }, "options": {} }, "id": "check-drifts", "name": "Has Drifts?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [440, 0] }, { "parameters": { "jsCode": "// Build Mattermost message from sync results\nconst syncResult = $input.first().json;\nconst results = syncResult.results || [];\n\nlet lines = [\n `### :warning: Extension Drift Report`,\n `**${syncResult.customers_checked}** customers checked | **${syncResult.total_drifts}** drifts found`,\n ''\n];\n\nfor (const r of results) {\n if (r.status === 'error') {\n lines.push(`#### :x: ${r.customer}`);\n lines.push(`> ${r.message}`);\n lines.push('');\n continue;\n }\n if (!r.drifts || r.drifts.length === 0) continue;\n\n lines.push(`#### :mag: ${r.customer} (${r.drift_count} drifts)`);\n lines.push(`| Extension | Type | Platform | Server |`);\n lines.push(`|-----------|------|----------|--------|`);\n\n for (const d of r.drifts) {\n const type = {\n 'version_mismatch': ':arrows_counterclockwise: Version mismatch',\n 'missing_on_server': ':red_circle: Missing on server',\n 'extra_on_server': ':large_blue_circle: Extra on server'\n }[d.type] || d.type;\n lines.push(`| ${d.extension} | ${type} | ${d.platform || '-'} | ${d.server || '-'} |`);\n }\n\n if (r.updated > 0) {\n lines.push(`> :white_check_mark: Updated ${r.updated} records in platform DB`);\n }\n lines.push('');\n}\n\nreturn [{ json: { message: lines.join('\\n') } }];" }, "id": "format-drift-message", "name": "Format Drift Report", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [660, -100] }, { "parameters": { "jsCode": "// Build success summary\nconst syncResult = $input.first().json;\n\nconst message = [\n `### :white_check_mark: Extension Sync — All Clear`,\n `**${syncResult.customers_checked}** customers checked, no drifts found.`,\n '',\n `| Customer | Server | Platform |`,\n `|----------|--------|----------|`\n];\n\nfor (const r of (syncResult.results || [])) {\n if (r.status === 'error') {\n message.push(`| ${r.customer} | :x: Error | - |`);\n } else {\n message.push(`| ${r.customer} | ${r.server_count} exts | ${r.platform_count} tracked |`);\n }\n}\n\nreturn [{ json: { message: message.join('\\n') } }];" }, "id": "format-ok-message", "name": "Format OK Summary", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [660, 100] }, { "parameters": { "method": "POST", "url": "https://mattermost.dev.marcus-law.co.il/api/v4/posts", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ JSON.stringify({ channel_id: '5x1mzsm7djdz7ydqkde93dkq4e', message: $json.message }) }}", "options": {} }, "id": "mattermost-drift", "name": "Mattermost (Drift)", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [880, -100], "credentials": { "httpHeaderAuth": { "id": "mattermost-token", "name": "Mattermost Token" } } }, { "parameters": { "method": "POST", "url": "https://mattermost.dev.marcus-law.co.il/api/v4/posts", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ JSON.stringify({ channel_id: '5x1mzsm7djdz7ydqkde93dkq4e', message: $json.message }) }}", "options": {} }, "id": "mattermost-ok", "name": "Mattermost (OK)", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [880, 100], "credentials": { "httpHeaderAuth": { "id": "mattermost-token", "name": "Mattermost Token" } } } ], "connections": { "Daily 07:00": { "main": [ [{ "node": "Call Platform Sync", "type": "main", "index": 0 }] ] }, "Call Platform Sync": { "main": [ [{ "node": "Has Drifts?", "type": "main", "index": 0 }] ] }, "Has Drifts?": { "main": [ [{ "node": "Format Drift Report", "type": "main", "index": 0 }], [{ "node": "Format OK Summary", "type": "main", "index": 0 }] ] }, "Format Drift Report": { "main": [ [{ "node": "Mattermost (Drift)", "type": "main", "index": 0 }] ] }, "Format OK Summary": { "main": [ [{ "node": "Mattermost (OK)", "type": "main", "index": 0 }] ] } }, "settings": { "executionOrder": "v1" }, "tags": [ { "name": "extension-platform" }, { "name": "daily" } ] }