n8n 2.x disables n8n-nodes-base.executeCommand by default (nodes.exclude), so the first workflow shape could not activate: 'Unrecognized node type'. Replace the Execute Command node with the SSH node, which is enabled, and keep the restricted trigger key: the server forced command runs exactly scripts/morning-brief.sh. - deploy/n8n-morning-brief.json: schedule + optional manual trigger -> SSH node -> Code check that makes a non-zero exit red (FR-12). - deploy/import-n8n-morning-brief.sh: builds the sshPrivateKey credential from the key (id schoolScanKey, mode-0600 temp, removed after import), imports, publishes, restarts once, and confirms activation in the n8n log. - scripts/morning-brief.sh: default IMAGE 0.6.1-phase8 so the scheduled job uses the deployed image. - docs/phase-7a-n8n-schedule.md, deploy/DEPLOYMENT.md: document the design and the throwaway-n8n rehearsal (activation + success + failure path).
120 lines
3.5 KiB
JSON
120 lines
3.5 KiB
JSON
{
|
|
"id": "schoolMorningBrf",
|
|
"name": "Compass / NHS — 6:00am morning brief",
|
|
"nodes": [
|
|
{
|
|
"parameters": {
|
|
"rule": {
|
|
"interval": [
|
|
{
|
|
"field": "cronExpression",
|
|
"expression": "0 6 * * *"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"id": "c1a0a0a0-0000-4000-8000-000000000001",
|
|
"name": "6:00am every day",
|
|
"type": "n8n-nodes-base.scheduleTrigger",
|
|
"typeVersion": 1.3,
|
|
"position": [200, 360]
|
|
},
|
|
{
|
|
"parameters": {},
|
|
"id": "c1a0a0a0-0000-4000-8000-000000000002",
|
|
"name": "Run now (manual)",
|
|
"type": "n8n-nodes-base.manualTrigger",
|
|
"typeVersion": 1,
|
|
"position": [200, 180],
|
|
"notes": "Optional: run the brief by hand from the n8n UI, or with `docker exec n8n n8n execute --id=schoolMorningBrf`. The schedule fires on its own; this trigger only does something when you press it."
|
|
},
|
|
{
|
|
"parameters": {
|
|
"authentication": "privateKey",
|
|
"resource": "command",
|
|
"operation": "execute",
|
|
"command": "cd /home/sam/paseo/projects/compass_teams_nhs && ./scripts/morning-brief.sh",
|
|
"cwd": "/"
|
|
},
|
|
"id": "c1a0a0a0-0000-4000-8000-000000000003",
|
|
"name": "Run the morning brief on the host",
|
|
"type": "n8n-nodes-base.ssh",
|
|
"typeVersion": 1,
|
|
"position": [480, 360],
|
|
"notes": "The scan needs node + patchright on .13, so it runs outside this container. The credential is the restricted trigger key: the server's forced command runs exactly scripts/morning-brief.sh, whatever command is sent.",
|
|
"credentials": {
|
|
"sshPrivateKey": {
|
|
"id": "schoolScanKey",
|
|
"name": "school-scan restricted key"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForAllItems",
|
|
"language": "javaScript",
|
|
"jsCode": "for (const item of $input.all()) {\n if (item.json.code !== 0) {\n throw new Error('morning-brief.sh failed with exit ' + item.json.code + ': ' + (item.json.stderr || ''));\n }\n}\nreturn $input.all();"
|
|
},
|
|
"id": "c1a0a0a0-0000-4000-8000-000000000004",
|
|
"name": "Red execution when the brief fails",
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [720, 360],
|
|
"notes": "The SSH node reports the remote exit code but does not fail on it. This node turns a non-zero exit (a failed scan or a failed send) into a red execution, so the schedule can never look green when the brief failed (FR-12)."
|
|
}
|
|
],
|
|
"connections": {
|
|
"6:00am every day": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Run the morning brief on the host",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Run now (manual)": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Run the morning brief on the host",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Run the morning brief on the host": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Red execution when the brief fails",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
},
|
|
"settings": {
|
|
"executionOrder": "v1",
|
|
"timezone": "Australia/Melbourne",
|
|
"saveManualExecutions": true,
|
|
"callerPolicy": "workflowsFromSameOwner"
|
|
},
|
|
"staticData": null,
|
|
"meta": {
|
|
"templateCredsSetupCompleted": true,
|
|
"instanceId": "compass-teams-nhs"
|
|
},
|
|
"pinData": {},
|
|
"tags": [
|
|
{
|
|
"name": "school"
|
|
}
|
|
],
|
|
"active": false
|
|
}
|