server-desktop-01/scripts/build-n8n-workflows.rb

248 lines
7.6 KiB
Ruby
Raw Normal View History

#!/usr/bin/env ruby
# frozen_string_literal: true
#
# Generates importable n8n workflow JSON from component pieces.
# Run: ruby scripts/build-n8n-workflows.rb
# Output: scripts/n8n-workflow-receiver.json
# scripts/n8n-workflow-reporter.json
#
# Before running:
# 1. Complete Task 7 and verify DATATABLE_TYPE / DATATABLE_TYPE_VERSION below.
# 2. After Task 10 (credentials set up), replace REPLACE_WITH_*_CREDENTIAL_ID
# in the generated JSON and re-run to regenerate clean files before import.
require 'json'
require 'securerandom'
SCRIPTS_DIR = File.dirname(__FILE__)
# Verify against the exported scratch-workflow JSON from Task 7.
DATATABLE_TYPE = 'n8n-nodes-base.dataTable'
DATATABLE_TYPE_VERSION = 1
evaluate_sources_js = File.read(File.join(SCRIPTS_DIR, 'n8n-evaluate-sources.js'))
build_email_js = File.read(File.join(SCRIPTS_DIR, 'n8n-build-email.js'))
# ── Workflow 1: Receiver ──────────────────────────────────────────────────────
receiver = {
name: 'Backup Monitor — Receiver',
nodes: [
{
parameters: {
httpMethod: 'POST',
path: 'backup-notify',
authentication: 'headerAuth',
responseMode: 'responseNode',
options: {}
},
id: SecureRandom.uuid,
name: 'Webhook',
type: 'n8n-nodes-base.webhook',
typeVersion: 2,
position: [240, 300],
webhookId: SecureRandom.uuid,
credentials: {
httpHeaderAuth: {
id: 'REPLACE_WITH_BACKUP_CREDENTIAL_ID',
name: 'backup-monitor-token'
}
}
},
{
parameters: {
resource: 'row',
operation: 'insert',
dataTableId: {
'__rl' => true,
mode: 'list',
value: 'REPLACE_WITH_DATATABLE_ID',
cachedResultName: 'backup_runs'
},
columns: {
mappingMode: 'defineBelow',
value: {
timestamp: '={{ $json.body.timestamp }}',
machine: '={{ $json.body.machine }}',
destination: '={{ $json.body.destination }}',
status: '={{ $json.body.status }}',
bytes_transferred: '={{ $json.body.bytes_transferred }}',
snapshot_id: '={{ $json.body.snapshot_id }}',
log_path: '={{ $json.body.log_path }}',
notes: '={{ $json.body.notes }}'
}
}
},
id: SecureRandom.uuid,
name: 'Insert to backup_runs',
type: DATATABLE_TYPE,
typeVersion: DATATABLE_TYPE_VERSION,
position: [520, 300]
},
{
parameters: {
respondWith: 'json',
responseBody: '={{ JSON.stringify({ ok: true }) }}',
options: { responseCode: 200 }
},
id: SecureRandom.uuid,
name: 'Respond 200',
type: 'n8n-nodes-base.respondToWebhook',
typeVersion: 1.1,
position: [800, 300]
}
],
connections: {
'Webhook' => { main: [[{ node: 'Insert to backup_runs', type: 'main', index: 0 }]] },
'Insert to backup_runs' => { main: [[{ node: 'Respond 200', type: 'main', index: 0 }]] }
},
active: false,
settings: { executionOrder: 'v1' },
pinData: {},
meta: { templateCredsSetupCompleted: true },
tags: []
}
# ── Workflow 2: Reporter ──────────────────────────────────────────────────────
reporter = {
name: 'Backup Monitor — Reporter',
nodes: [
{
parameters: {
rule: {
interval: [
{
field: 'weeks',
weeksInterval: 1,
triggerAtDay: [5],
triggerAtHour: 8,
triggerAtMinute: 0
}
]
}
},
id: SecureRandom.uuid,
name: 'Every Friday 8 AM',
type: 'n8n-nodes-base.scheduleTrigger',
typeVersion: 1.2,
position: [240, 300]
},
{
parameters: {
mode: 'manual',
includeOtherFields: false,
assignments: {
assignments: [
{
id: SecureRandom.uuid,
name: 'sources',
value: '={{ [{"machine":"desktop","destination":"synology"},{"machine":"desktop","destination":"backblaze-b2"},{"machine":"vps-ovh-prod-01","destination":"local"}] }}',
type: 'arrayValue'
}
]
},
options: {}
},
id: SecureRandom.uuid,
name: 'Set sources',
type: 'n8n-nodes-base.set',
typeVersion: 3.4,
position: [460, 300]
},
{
parameters: {
resource: 'row',
operation: 'getMany',
dataTableId: {
'__rl' => true,
mode: 'list',
value: 'REPLACE_WITH_DATATABLE_ID',
cachedResultName: 'backup_runs'
},
filters: {
conditions: [
{
keyName: 'timestamp',
condition: 'gt',
keyValue: '={{ $now.minus({days: 7}).toISO() }}'
}
]
},
options: {}
},
id: SecureRandom.uuid,
name: 'Get backup_runs (last 7d)',
type: DATATABLE_TYPE,
typeVersion: DATATABLE_TYPE_VERSION,
position: [680, 300]
},
{
parameters: {
mode: 'runOnceForAllItems',
language: 'javaScript',
jsCode: evaluate_sources_js
},
id: SecureRandom.uuid,
name: 'Evaluate Sources',
type: 'n8n-nodes-base.code',
typeVersion: 2,
position: [900, 300]
},
{
parameters: {
mode: 'runOnceForAllItems',
language: 'javaScript',
jsCode: build_email_js
},
id: SecureRandom.uuid,
name: 'Build Email',
type: 'n8n-nodes-base.code',
typeVersion: 2,
position: [1120, 300]
},
{
parameters: {
method: 'POST',
url: 'https://app.mailpace.com/api/v1/send',
authentication: 'genericCredentialType',
genericAuthType: 'httpHeaderAuth',
sendBody: true,
specifyBody: 'json',
jsonBody: '={{ { from: "REPLACE_WITH_MAILPACE_FROM_ADDRESS", to: "jaredmswanson@gmail.com", subject: $json.subject, text_body: $json.body } }}',
options: {}
},
id: SecureRandom.uuid,
name: 'Send via MailPace',
type: 'n8n-nodes-base.httpRequest',
typeVersion: 4.2,
position: [1340, 300],
credentials: {
httpHeaderAuth: {
id: 'REPLACE_WITH_MAILPACE_CREDENTIAL_ID',
name: 'mailpace-token'
}
}
}
],
connections: {
'Every Friday 8 AM' => { main: [[{ node: 'Set sources', type: 'main', index: 0 }]] },
'Set sources' => { main: [[{ node: 'Get backup_runs (last 7d)', type: 'main', index: 0 }]] },
'Get backup_runs (last 7d)' => { main: [[{ node: 'Evaluate Sources', type: 'main', index: 0 }]] },
'Evaluate Sources' => { main: [[{ node: 'Build Email', type: 'main', index: 0 }]] },
'Build Email' => { main: [[{ node: 'Send via MailPace', type: 'main', index: 0 }]] }
},
active: false,
settings: { executionOrder: 'v1' },
pinData: {},
meta: { templateCredsSetupCompleted: true },
tags: []
}
File.write(File.join(SCRIPTS_DIR, 'n8n-workflow-receiver.json'), JSON.pretty_generate(receiver))
File.write(File.join(SCRIPTS_DIR, 'n8n-workflow-reporter.json'), JSON.pretty_generate(reporter))
puts 'Generated:'
puts " #{SCRIPTS_DIR}/n8n-workflow-receiver.json"
puts " #{SCRIPTS_DIR}/n8n-workflow-reporter.json"