316 lines
7.6 KiB
JSON
316 lines
7.6 KiB
JSON
{
|
|
"name": "Auto-Backup Verifier",
|
|
"nodes": [
|
|
{
|
|
"parameters": {
|
|
"rule": {
|
|
"interval": [
|
|
{
|
|
"field": "cronExpression",
|
|
"expression": "20 2 * * *"
|
|
}
|
|
]
|
|
},
|
|
"timezone": "Australia/Perth"
|
|
},
|
|
"id": "cron-trigger",
|
|
"name": "Daily 02:20 AWST",
|
|
"type": "n8n-nodes-base.scheduleTrigger",
|
|
"typeVersion": 1.2,
|
|
"position": [
|
|
200,
|
|
300
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"assignments": {
|
|
"assignments": [
|
|
{
|
|
"name": "repoOwner",
|
|
"type": "string",
|
|
"value": "Anthony"
|
|
},
|
|
{
|
|
"name": "repoName",
|
|
"type": "string",
|
|
"value": "openclaw-backups"
|
|
},
|
|
{
|
|
"name": "branch",
|
|
"type": "string",
|
|
"value": "main"
|
|
},
|
|
{
|
|
"name": "requiredPaths",
|
|
"type": "string",
|
|
"value": "AGENTS.md,MEMORY.md,TOOLS.md,state-backup/openclaw.json,state-backup/cron/jobs.json,state-backup/devices/paired.json"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"id": "set-context",
|
|
"name": "Set Context",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 3.4,
|
|
"position": [
|
|
420,
|
|
300
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"url": "=http://gitea.kangaroo-eel.ts.net:3000/api/v1/repos/{{$json.repoOwner}}/{{$json.repoName}}/branches/{{$json.branch}}",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"options": {
|
|
"timeout": 10000
|
|
}
|
|
},
|
|
"id": "get-branch",
|
|
"name": "Get Branch Head",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.2,
|
|
"position": [
|
|
660,
|
|
300
|
|
],
|
|
"retryOnFail": true,
|
|
"maxTries": 3,
|
|
"waitBetweenTries": 2000
|
|
},
|
|
{
|
|
"parameters": {
|
|
"url": "=http://gitea.kangaroo-eel.ts.net:3000/api/v1/repos/{{$node[\"Set Context\"].json.repoOwner}}/{{$node[\"Set Context\"].json.repoName}}/git/trees/{{$json.commit.id}}?recursive=1",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"options": {
|
|
"timeout": 10000
|
|
}
|
|
},
|
|
"id": "get-tree",
|
|
"name": "Get Repo Tree",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.2,
|
|
"position": [
|
|
900,
|
|
300
|
|
],
|
|
"retryOnFail": true,
|
|
"maxTries": 3,
|
|
"waitBetweenTries": 2000
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "const required = $node['Set Context'].json.requiredPaths.split(',').map(s => s.trim());\nconst tree = $json.tree || [];\nconst existing = new Set(tree.map(t => t.path));\nconst missing = required.filter(p => !existing.has(p));\nreturn [{ json: {\n status: missing.length ? 'failed' : 'ok',\n missing,\n checked: required.length,\n headSha: ($node['Get Branch Head'].json.commit || {}).id || '',\n repo: `${$node['Set Context'].json.repoOwner}/${$node['Set Context'].json.repoName}`\n}}];"
|
|
},
|
|
"id": "validate",
|
|
"name": "Validate Required Files",
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1140,
|
|
300
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"string": [
|
|
{
|
|
"value1": "={{$json.status}}",
|
|
"operation": "equals",
|
|
"value2": "ok"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"id": "if-ok",
|
|
"name": "Backup OK?",
|
|
"type": "n8n-nodes-base.if",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1360,
|
|
300
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"url": "={{$env.NTFY_URL || 'https://ntfy.sh'}}/{{ $env.NTFY_TOPIC || 'anthony-krilly-9f3k2' }}",
|
|
"sendBody": true,
|
|
"contentType": "json",
|
|
"bodyParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "title",
|
|
"value": "\u2705 Backup Verified"
|
|
},
|
|
{
|
|
"name": "message",
|
|
"value": "={{`Repo ${$json.repo} verified. SHA: ${$json.headSha.slice(0,7)}. Checked ${$json.checked} required files.`}}"
|
|
},
|
|
{
|
|
"name": "priority",
|
|
"value": "2"
|
|
}
|
|
]
|
|
},
|
|
"options": {
|
|
"timeout": 10000
|
|
}
|
|
},
|
|
"id": "notify-ok",
|
|
"name": "ntfy Success",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.2,
|
|
"position": [
|
|
1600,
|
|
200
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"url": "={{$env.NTFY_URL || 'https://ntfy.sh'}}/{{ $env.NTFY_TOPIC || 'anthony-krilly-9f3k2' }}",
|
|
"sendBody": true,
|
|
"contentType": "json",
|
|
"bodyParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "title",
|
|
"value": "\ud83d\udea8 Backup Verification Failed"
|
|
},
|
|
{
|
|
"name": "message",
|
|
"value": "={{`Repo ${$json.repo} failed verification. Missing: ${$json.missing.join(', ')}. SHA: ${$json.headSha.slice(0,7)}`}}"
|
|
},
|
|
{
|
|
"name": "priority",
|
|
"value": "9"
|
|
}
|
|
]
|
|
},
|
|
"options": {
|
|
"timeout": 10000
|
|
}
|
|
},
|
|
"id": "notify-fail-gotify",
|
|
"name": "ntfy Failure",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.2,
|
|
"position": [
|
|
1600,
|
|
360
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"chatId": "1793951355",
|
|
"text": "={{`\ud83e\udd80 Backup verifier failed\nRepo: ${$json.repo}\nMissing: ${$json.missing.join(', ')}\nSHA: ${$json.headSha.slice(0,7)}`}}",
|
|
"additionalFields": {}
|
|
},
|
|
"id": "notify-fail-telegram",
|
|
"name": "Telegram Failure",
|
|
"type": "n8n-nodes-base.telegram",
|
|
"typeVersion": 1.2,
|
|
"position": [
|
|
1810,
|
|
360
|
|
],
|
|
"credentials": {
|
|
"telegramApi": {
|
|
"name": "Telegram account"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
"connections": {
|
|
"Daily 02:20 AWST": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Set Context",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Set Context": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Get Branch Head",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Get Branch Head": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Get Repo Tree",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Get Repo Tree": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Validate Required Files",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Validate Required Files": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Backup OK?",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Backup OK?": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "ntfy Success",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "ntfy Failure",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"ntfy Failure": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Telegram Failure",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
},
|
|
"settings": {
|
|
"executionOrder": "v1"
|
|
},
|
|
"active": false
|
|
} |