knowledge-genome-orchestrator/deploy/n8n/genome-ingest.json

419 lines
No EOL
12 KiB
JSON

{
"name": "Genome: ingest",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "forgejo-push",
"options": {}
},
"id": "eb4abf4a-d26d-4aea-85a2-fc356b81385f",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
1920,
1728
],
"webhookId": "cf215f5d31e04dd2"
},
{
"parameters": {
"jsCode": "// Bell filter: proceed ONLY on develop pushes that actually touch raw/. Returning [] stops the\n// flow (no node needed). Performance: never wake vm101 for wiki-only pushes (e.g. an ingest PR\n// merged back to develop). pending-raw remains the source of truth.\nconst b = $json.body || $json;\nconst ref = b.ref || '';\nconst genome = (b.repository && b.repository.name) || '';\nif (ref !== 'refs/heads/develop') return [];\nif (!/^[a-z0-9][a-z0-9-]{0,63}$/.test(genome)) return [];\nconst commits = b.commits || [];\nconst touched = [];\nfor (const c of commits) {\n for (const p of (c.added || [])) touched.push(p);\n for (const p of (c.modified || [])) touched.push(p);\n for (const p of (c.removed || [])) touched.push(p);\n}\nif (!touched.some(p => p.startsWith('raw/'))) return [];\nreturn [{ json: { genome } }];"
},
"id": "190d44ea-4f6f-4cff-91aa-3e65ef44cb21",
"name": "Gate push",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2144,
1728
]
},
{
"parameters": {
"workflowId": {
"__rl": true,
"value": "zbtRXWsLt56nEIfz",
"mode": "list",
"cachedResultUrl": "/workflow/zbtRXWsLt56nEIfz",
"cachedResultName": "Power Manager"
},
"workflowInputs": {
"mappingMode": "defineBelow",
"value": {
"mode": "ensure-on"
},
"matchingColumns": [
"mode"
],
"schema": [
{
"id": "mode",
"displayName": "mode",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string",
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": true
},
"options": {}
},
"id": "40af578c-eac4-47ac-9c30-5596eceaf9df",
"name": "Power Manager - ensure-on",
"type": "n8n-nodes-base.executeWorkflow",
"typeVersion": 1.3,
"position": [
2352,
1728
]
},
{
"parameters": {
"authentication": "privateKey",
"command": "=ssh vm101 'pi pending-raw {{ $('Gate push').first().json.genome }}'"
},
"id": "f8861a50-aaf1-46fb-95a9-b9b200d4d6ae",
"name": "SSH: pending-raw",
"type": "n8n-nodes-base.ssh",
"typeVersion": 1,
"position": [
2576,
1728
],
"credentials": {
"sshPrivateKey": {
"id": "GJQjKzte7Hjdfz89",
"name": "n8n container -> n8n-runner@nexus"
}
}
},
{
"parameters": {
"jsCode": "// Parse pending-raw -> one item per raw, carrying everything run-one-ingest needs. Unsafe\n// filenames (spaces / odd chars) are NOT ingested -> a 'badname' item -> ntfy.\nconst out = ($input.first().json.stdout || '').toString().trim();\nlet d;\ntry { d = JSON.parse(out); }\ncatch (e) { return [{ json: { _kind: 'error', reason: 'pending-raw non parsabile', raw: out } }]; }\nif (!d.files || d.files.length === 0) return [];\nconst why = {};\nfor (const it of (d.detail || [])) why[it.path] = it.reason;\nconst SAFE = /^[A-Za-z0-9._\\\\/-]+$/;\nconst items = [];\nfor (const raw of d.files) {\n if (SAFE.test(raw)) items.push({ json: { _kind: 'ingest', genome: d.genome, raw,\n mode: 'ingest', feedback_b64: '', reason: why[raw] || 'new', prevPr: '' } });\n else items.push({ json: { _kind: 'badname', genome: d.genome, raw,\n hint: raw.replace(/[^A-Za-z0-9._\\\\/-]+/g, '-').toLowerCase() } });\n}\nreturn items;"
},
"id": "e1f1e251-1565-4092-b8e7-b97c9c0bb18d",
"name": "Split raw files",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2800,
1728
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "cbacf5d98d594ba5",
"leftValue": "={{ $json._kind }}",
"rightValue": "ingest",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "3339ce75-3ec9-4ed0-8faa-2433e9616c43",
"name": "Nome valido?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
3024,
1728
]
},
{
"parameters": {
"workflowId": {
"__rl": true,
"value": "VIi2ovb5gJxNJLbg",
"mode": "list",
"cachedResultUrl": "/workflow/VIi2ovb5gJxNJLbg",
"cachedResultName": "Genome: run-one-ingest"
},
"workflowInputs": {
"mappingMode": "defineBelow",
"value": {
"genome": "={{ $json.genome }}",
"raw": "={{ $json.raw }}",
"mode": "ingest",
"feedback_b64": "",
"reason": "={{ $json.reason }}",
"prevPr": ""
},
"matchingColumns": [],
"schema": [
{
"id": "genome",
"displayName": "genome",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string",
"removed": false
},
{
"id": "raw",
"displayName": "raw",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string",
"removed": false
},
{
"id": "mode",
"displayName": "mode",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string",
"removed": false
},
{
"id": "feedback_b64",
"displayName": "feedback_b64",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string",
"removed": false
},
{
"id": "reason",
"displayName": "reason",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string",
"removed": false
},
{
"id": "prevPr",
"displayName": "prevPr",
"required": false,
"defaultMatch": false,
"display": true,
"canBeUsedToMatch": true,
"type": "string",
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": true
},
"options": {
"waitForSubWorkflow": false
}
},
"id": "fda796f5-588b-4502-a653-5d27c3f72ac6",
"name": "Run one ingest",
"type": "n8n-nodes-base.executeWorkflow",
"typeVersion": 1.3,
"position": [
3232,
1616
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const d = $json;\nreturn { topic: 'genome-ingest', title: `${d.genome} \\u00b7 file da rinominare`,\n priority: 'high', tags: 'warning', click: '', actions: '',\n body: `Il file \\`${d.raw}\\` ha spazi o caratteri non ammessi e **non** \\u00e8 stato ingerito.\\nRinominalo in: \\`${d.hint}\\`` };"
},
"id": "6820f3fb-97bb-45bf-8e7f-00eb68d7f313",
"name": "Build ntfy badname",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
3232,
1840
]
},
{
"parameters": {
"method": "POST",
"url": "=http://ntfy/{{ $json.topic }}",
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Title",
"value": "={{ $json.title }}"
},
{
"name": "Priority",
"value": "={{ $json.priority }}"
},
{
"name": "Tags",
"value": "={{ $json.tags }}"
},
{
"name": "Click",
"value": "={{ $json.click }}"
},
{
"name": "Actions",
"value": "={{ $json.actions }}"
},
{
"name": "Markdown",
"value": "yes"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "Raw / Text",
"body": "={{ $json.body }}",
"options": {
"timeout": 15000
}
},
"id": "55cc42b2-3170-4884-bb5d-58e3af97bfea",
"name": "ntfy: send",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
3456,
1840
],
"credentials": {
"httpHeaderAuth": {
"id": "TBPXSWOF63k9mvm8",
"name": "ntfy-token"
},
"httpBearerAuth": {
"id": "nCv4CUN7Ef086Ewj",
"name": "Bearer Auth account"
}
}
}
],
"pinData": {},
"connections": {
"Webhook": {
"main": [
[
{
"node": "Gate push",
"type": "main",
"index": 0
}
]
]
},
"Gate push": {
"main": [
[
{
"node": "Power Manager - ensure-on",
"type": "main",
"index": 0
}
]
]
},
"Power Manager - ensure-on": {
"main": [
[
{
"node": "SSH: pending-raw",
"type": "main",
"index": 0
}
]
]
},
"SSH: pending-raw": {
"main": [
[
{
"node": "Split raw files",
"type": "main",
"index": 0
}
]
]
},
"Split raw files": {
"main": [
[
{
"node": "Nome valido?",
"type": "main",
"index": 0
}
]
]
},
"Nome valido?": {
"main": [
[
{
"node": "Run one ingest",
"type": "main",
"index": 0
}
],
[
{
"node": "Build ntfy badname",
"type": "main",
"index": 0
}
]
]
},
"Build ntfy badname": {
"main": [
[
{
"node": "ntfy: send",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate",
"timeSavedMode": "fixed",
"errorWorkflow": "7Vws3gCX3QnjM3oD",
"callerPolicy": "workflowsFromSameOwner",
"availableInMCP": false
},
"versionId": "d58601e7-b752-4c9f-9438-d91be663c82e",
"meta": {
"instanceId": "96b2f0ec76a4400bbd481c617b24b3b87024cc7a913efacccaf9fc85722e7417"
},
"id": "mUJUuQxcDiiPWcUE",
"tags": []
}