{"id":"uoBZx3eMvLMxlHCS","meta":{"instanceId":"workflow-efb19129","versionId":"1.0.0","createdAt":"2025-09-29T07:07:45.132628","updatedAt":"2025-09-29T07:07:45.132685","owner":"n8n-user","license":"MIT","category":"automation","status":"active","priority":"high","environment":"production"},"name":"[OPS] Restore workflows from GitHub to n8n","nodes":[{"id":"540d147a-8185-4f3e-b2f4-522a19eb6b10","name":"On clicking 'execute'","type":"n8n-nodes-base.manualTrigger","position":[-700,780],"parameters":{},"typeVersion":1,"notes":"This manualTrigger node performs automated tasks as part of the workflow."},{"id":"7040674c-57b4-453d-acd4-69cbeff64180","name":"Globals","type":"n8n-nodes-base.set","position":[-500,680],"parameters":{"values":{"string":[{"name":"repo.owner","value":"n8n-io"},{"name":"repo.name","value":"n8n-backups"},{"name":"repo.path","value":"workflows/"}]},"options":{}},"typeVersion":1,"notes":"This set node performs automated tasks as part of the workflow."},{"id":"2b3a2856-4024-4fb0-b068-6bace0e6592c","name":"Note","type":"n8n-nodes-base.stickyNote","position":[-1140,600],"parameters":{"color":2,"width":389.78906250000017,"height":464.79920462713443,"content":"## Workflow - Restore Backups\nThis workflow will restore backed-up workflows from Github. \nIt is launch by testing the workflow\n\n### Setup\nOpen Globals and update the values below\n**repo.owner:** This is your Github username\n**repo.name:** This is the name of your repository\n**repo.path:** This is the folder where your workflows are saved, within the repository.\n\nIf your username was `n8n-io` and your repository was called `n8n-backups` and you wanted the workflows to go into a `workflows` folder you would set:\n\nrepo.owner - n8n-io\nrepo.name - n8n-backups\nrepo.path - workflows"},"typeVersion":1,"notes":"This stickyNote node performs automated tasks as part of the workflow."},{"id":"ba2d3355-df53-43e2-a4b2-2e031b71d687","name":"Workflow name already exists","type":"n8n-nodes-base.noOp","position":[1180,880],"parameters":{},"typeVersion":1,"notes":"This noOp node performs automated tasks as part of the workflow."},{"id":"f012be7a-fb56-4a92-b2e5-e5ec316624e8","name":"If workflow already exists","type":"n8n-nodes-base.if","position":[860,760],"parameters":{"options":{},"conditions":{"options":{"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"063d51c7-0b7a-48a4-82b3-76b370fc4265","operator":{"type":"string","operation":"exists","singleValue":true},"leftValue":"={{ $('Merge Github and n8n workflows - Keep only non existing workflows based on the name').item.json.name }}","rightValue":""}]}},"typeVersion":2,"notes":"This if node performs automated tasks as part of the workflow."},{"id":"d1d698f2-0ccf-4865-9ecd-9e10e725d12d","name":"Set n8n existing workflows names","type":"n8n-nodes-base.set","position":[320,880],"parameters":{"options":{},"assignments":{"assignments":[{"id":"6be8c184-8fb7-47a9-ad42-d0dc3db1eea4","name":"name","type":"string","value":"={{ $json.name }}"}]}},"typeVersion":3.3,"notes":"This set node performs automated tasks as part of the workflow."},{"id":"d9c58650-ca2d-47c8-a887-59407fa70e1d","name":"GitHub - get all files","type":"n8n-nodes-base.github","position":[-280,540],"parameters":{"owner":{"__rl":true,"mode":"name","value":"={{$node[\"Globals\"].json[\"repo\"][\"owner\"]}}"},"filePath":"={{$node[\"Globals\"].json[\"repo\"][\"path\"]}}","resource":"file","operation":"list","repository":{"__rl":true,"mode":"name","value":"={{$node[\"Globals\"].json[\"repo\"][\"name\"]}}"}},"credentials":{"githubApi":{"id":"vL0n4BqAk6e4zDd7","name":"GitHub account"}},"typeVersion":1,"notes":"This github node performs automated tasks as part of the workflow."},{"id":"7bff36b1-d526-402b-bff8-7ce2af050e2d","name":"n8n - get all workflows","type":"n8n-nodes-base.n8n","position":[-500,880],"parameters":{"filters":{}},"credentials":{"n8nApi":{"id":"RzT15uIVuSWu3ioX","name":"n8n account"}},"typeVersion":1,"notes":"This n8n node performs automated tasks as part of the workflow."},{"id":"277f6400-409a-4ba0-8ad7-1241768b669a","name":"GitHub - get each file","type":"n8n-nodes-base.github","position":[140,660],"parameters":{"owner":{"__rl":true,"mode":"name","value":"={{ $json.repo.owner }}"},"filePath":"={{ $json.path }}","resource":"file","operation":"get","repository":{"__rl":true,"mode":"name","value":"={{ $json.repo.name }}"},"asBinaryProperty":false,"additionalParameters":{}},"credentials":{"githubApi":{"id":"vL0n4BqAk6e4zDd7","name":"GitHub account"}},"typeVersion":1,"notes":"This github node performs automated tasks as part of the workflow."},{"id":"b59f5e23-729a-41fb-be4b-1aebc573393b","name":"Set name and content","type":"n8n-nodes-base.set","position":[340,660],"parameters":{"options":{},"assignments":{"assignments":[{"id":"714b0cfd-9f06-4e2f-b73d-30ef39dc40e3","name":"content","type":"string","value":"={{ $json.content.base64Decode() }}"},{"id":"6f48ed58-d55a-4ee4-8cf2-373941aaa341","name":"name","type":"string","value":"={{ $json.name.replace(\".json\", \"\") }}"}]}},"typeVersion":3.3,"notes":"This set node performs automated tasks as part of the workflow."},{"id":"6f642a8c-9997-42b2-b9d7-3c1f02e0e26a","name":"n8n - create workflow","type":"n8n-nodes-base.n8n","position":[1180,660],"parameters":{"operation":"create","workflowObject":"={{ $('Set name and content').item.json.content }}"},"credentials":{"n8nApi":{"id":"RzT15uIVuSWu3ioX","name":"n8n account"}},"typeVersion":1,"notes":"This n8n node performs automated tasks as part of the workflow."},{"id":"b4ce8bdb-8c76-4c10-bf48-3664ec2f924b","name":"Note1","type":"n8n-nodes-base.stickyNote","position":[-360,340],"parameters":{"color":2,"width":861.4145066375679,"height":478.9952882299376,"content":"## Get all Github files\n1. List all the files from your repository\n2. Get each file as a JSON. \n3. The content, retrieved as base64, is converted in the \"Set Name and Content\" node\n\n\nThe \"Set Name and Content\" node creates a list of workflows with name and content, in order to compare it with the existing n8n workflows in the workspace."},"typeVersion":1,"notes":"This stickyNote node performs automated tasks as part of the workflow."},{"id":"5ff560b9-8c43-401c-869f-2b4a2e13cacc","name":"Merge globals and files","type":"n8n-nodes-base.merge","position":[-60,660],"parameters":{"mode":"combine","options":{},"combinationMode":"multiplex"},"typeVersion":2.1,"notes":"This merge node performs automated tasks as part of the workflow."},{"id":"008d21d9-007b-44da-8d1a-bd334ba54d61","name":"Merge Github and n8n workflows - Keep only non existing workflows based on the name","type":"n8n-nodes-base.merge","position":[640,760],"parameters":{"mode":"combine","options":{},"joinMode":"keepNonMatches","mergeByFields":{"values":[{"field1":"name","field2":"name"}]},"outputDataFrom":"input1"},"typeVersion":2.1,"alwaysOutputData":true,"notes":"This merge node performs automated tasks as part of the workflow."},{"id":"c7ffe214-1d7b-4f4f-87c1-36d9cb8e43a9","name":"Note2","type":"n8n-nodes-base.stickyNote","position":[560,940],"parameters":{"color":2,"width":260.44696745223945,"height":196.65095879641083,"content":"## Merge Github and n8n workflows\n\nHere, we only keep the workflows from Github that doesn't already exist in n8n workspace, based on the name"},"typeVersion":1,"notes":"This stickyNote node performs automated tasks as part of the workflow."},{"id":"3d84fd1c-c49b-4db0-951a-e38d50dae47b","name":"Note3","type":"n8n-nodes-base.stickyNote","position":[1360,720],"parameters":{"color":2,"width":344.0461264465236,"height":237.66186698228626,"content":"## Create n8n workflow\n\nCreate the n8n workflow using:\n- Content saved in Github\n- Name of the file in Github\n\n\nIf the workflow name already exist in n8n, then the workflow is not created - to avoid duplicates."},"typeVersion":1,"notes":"This stickyNote node performs automated tasks as part of the workflow."},{"id":"144a0b2e-d7b2-443d-91a5-96c09ef16b8e","name":"Note4","type":"n8n-nodes-base.stickyNote","position":[-280,980],"parameters":{"color":2,"width":378.7476641422645,"height":182.45487519360773,"content":"## Get existing n8n workflows\n\n1. Get all workflows\n2. Prepare a list of workflows in order to compare it with the workflows saved in the Github repo."},"typeVersion":1,"notes":"This stickyNote node performs automated tasks as part of the workflow."},{"id":"error-50e6ea2f","name":"Error Handler","type":"n8n-nodes-base.stopAndError","typeVersion":1,"position":[1000,400],"parameters":{"message":"Workflow execution error","options":{}}}],"active":false,"settings":{"executionOrder":"v1","saveManualExecutions":true,"callerPolicy":"workflowsFromSameOwner","errorWorkflow":null,"timezone":"UTC","executionTimeout":3600,"maxExecutions":1000,"retryOnFail":true,"retryCount":3,"retryDelay":1000},"versionId":"b7a0e558-1c40-4ff8-aaed-b6e3a8ab6b8c","connections":{},"description":"Automated workflow: [OPS] Restore workflows from GitHub to n8n. This workflow integrates 8 different services: stickyNote, n8n, merge, set, manualTrigger. It contains 17 nodes and follows best practices for error handling and security.","notes":"Excellent quality workflow: [OPS] Restore workflows from GitHub to n8n. This workflow has been optimized for production use with comprehensive error handling, security, and documentation."}