Hey
Describe the issue/error/question
I’m trying to use this WF to back up my WF on my Github repo
However I cannot export my n8n Workflows because the credentials don’t seem to work with my self hosted n8n.
However my API key does work on the Public API Playground and I am able to export my WF data that way.
I just cannot do it inside of n8n.
What is the error message (if any)?
Please share the workflow
Summary
{
“name”: “Backup n8n WFs to Github”,
“nodes”: [
{
“parameters”: {},
“id”: “76c454b3-ab17-4696-89f0-f4a8e3d9f87d”,
“name”: “On clicking ‘execute’”,
“type”: “n8n-nodes-base.manualTrigger”,
“position”: [
-1125,
595
],
“typeVersion”: 1
},
{
“parameters”: {
“resource”: “file”,
“operation”: “get”,
“owner”: “={{$node["Globals"].json["repo"]["owner"]}}”,
“repository”: “={{$node["Globals"].json["repo"]["name"]}}”,
“filePath”: “={{$node["Globals"].json["repo"]["path"]}}{{$json["name"]}}.json”,
“asBinaryProperty”: false,
“additionalParameters”: {}
},
“id”: “c558c2bc-3fcb-4afa-b70c-1f70ff1bac48”,
“name”: “GitHub”,
“type”: “n8n-nodes-base.github”,
“position”: [
-280,
560
],
“typeVersion”: 1,
“alwaysOutputData”: true,
“credentials”: {
“githubApi”: {
“id”: “11”,
“name”: “GitHub”
}
},
“continueOnFail”: true
},
{
“parameters”: {
“dataType”: “string”,
“value1”: “={{$json["github_status"]}}”,
“rules”: {
“rules”: [
{
“value2”: “same”
},
{
“value2”: “different”,
“output”: 1
},
{
“value2”: “new”,
“output”: 2
}
]
}
},
“id”: “b1bc4814-b44b-4aff-b403-d0729a09a0d4”,
“name”: “github_status”,
“type”: “n8n-nodes-base.switch”,
“position”: [
360,
700
],
“typeVersion”: 1
},
{
“parameters”: {},
“id”: “3a6ea956-eca2-4ac8-b528-735643ea37c8”,
“name”: “same”,
“type”: “n8n-nodes-base.noOp”,
“position”: [
600,
500
],
“typeVersion”: 1
},
{
“parameters”: {},
“id”: “b28a6425-6334-44e3-9c66-3bd80ffddf92”,
“name”: “different”,
“type”: “n8n-nodes-base.noOp”,
“position”: [
600,
700
],
“typeVersion”: 1
},
{
“parameters”: {},
“id”: “e5b6b860-9add-4a7f-9a69-04df8a614979”,
“name”: “new”,
“type”: “n8n-nodes-base.noOp”,
“position”: [
600,
880
],
“typeVersion”: 1
},
{
“parameters”: {
“resource”: “file”,
“operation”: “edit”,
“owner”: “={{$node["Globals"].json["repo"]["owner"]}}”,
“repository”: “={{$node["Globals"].json["repo"]["name"]}}”,
“filePath”: “={{$node["Globals"].json["repo"]["path"]}}{{$node["OneAtATime"].json["name"]}}.json”,
“fileContent”: “={{$node["isDiffOrNew"].json["n8n_data_stringy"]}}”,
“commitMessage”: “=[N8N Backup] {{$node["OneAtATime"].json["name"]}}.json ({{$json["github_status"]}})”
},
“id”: “9d4e3cb3-192a-411a-aaf3-683daf1bd766”,
“name”: “GitHub Edit”,
“type”: “n8n-nodes-base.github”,
“position”: [
780,
700
],
“typeVersion”: 1,
“credentials”: {
“githubApi”: {
“id”: “11”,
“name”: “GitHub”
}
}
},
{
“parameters”: {
“resource”: “file”,
“owner”: “={{$node["Globals"].json["repo"]["owner"]}}”,
“repository”: “={{$node["Globals"].json["repo"]["name"]}}”,
“filePath”: “={{$node["Globals"].json["repo"]["path"]}}{{$node["OneAtATime"].json["name"]}}.json”,
“fileContent”: “={{$node["isDiffOrNew"].json["n8n_data_stringy"]}}”,
“commitMessage”: “=[N8N Backup] {{$node["OneAtATime"].json["name"]}}.json ({{$json["github_status"]}})”
},
“id”: “ed11ff7e-0c18-4c6d-9f36-1a1c90271d4e”,
“name”: “GitHub Create”,
“type”: “n8n-nodes-base.github”,
“position”: [
780,
880
],
“typeVersion”: 1,
“credentials”: {
“githubApi”: {
“id”: “11”,
“name”: “GitHub”
}
}
},
{
“parameters”: {
“batchSize”: 1,
“options”: {}
},
“id”: “3e5be6e0-faec-4714-a259-f23635d461d5”,
“name”: “OneAtATime”,
“type”: “n8n-nodes-base.splitInBatches”,
“position”: [
-500,
720
],
“typeVersion”: 1
},
{
“parameters”: {
“values”: {
“string”: [
{
“name”: “repo.owner”,
“value”: “Javelo-Growth”
},
{
“name”: “repo.name”,
“value”: “n8n-backups”
},
{
“name”: “repo.path”,
“value”: “workflows/”
}
]
},
“options”: {}
},
“id”: “af38f530-944c-4384-80eb-64467c85c250”,
“name”: “Globals”,
“type”: “n8n-nodes-base.set”,
“position”: [
-940,
720
],
“typeVersion”: 1
},
{
“parameters”: {
“triggerTimes”: {
“item”: [
{
“mode”: “everyX”,
“value”: 12
}
]
}
},
“id”: “0b4aa07f-3b40-401d-982b-7db7909d8943”,
“name”: “Every 12 hours”,
“type”: “n8n-nodes-base.cron”,
“position”: [
-1125,
855
],
“typeVersion”: 1
},
{
“parameters”: {
“content”: “## Workflow Backups\nThis workflow will automatically backup your workflows to your Github account every 12 hours.\n\n### Setup\nOpen Globals and update the values below\nrepo.owner: This is your Github username\nrepo.name: This is the name of your repository\nrepo.path: This is the folder to use within the repository, If it doesn’t exist it will be created.\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”,
“height”: 464.79920462713443,
“width”: 389.78906250000017
},
“id”: “049198e1-3ee0-4961-912f-dcdbe143ec4b”,
“name”: “Note”,
“type”: “n8n-nodes-base.stickyNote”,
“position”: [
-1580,
500
],
“typeVersion”: 1
},
{
“parameters”: {
“content”: “## Single Item Loop\nWe process each workflow item one at a time, We first check Github to see if a file exists then we merge the Github Data and the API item so we can check if the values match in the function node isDiffOrNew
we then set a status of same
, different
or new
”,
“height”: 424.04333333333386,
“width”: 755.2349999999991
},
“id”: “c0d5bb2e-6d60-441a-b171-d954ff53cb51”,
“name”: “Note2”,
“type”: “n8n-nodes-base.stickyNote”,
“position”: [
-520,
440
],
“typeVersion”: 1
},
{
“parameters”: {
“content”: “## Save the data\nUsing the switch node we work out what to do based on the previous status, If it is the same we do nothing, If it is different we update the file in Github and if it is new we create a new file. After this is done we loop back to the Split in Batches node (OneAtAtTime) to start the process again.”,
“height”: 693.9283333333326,
“width”: 666.4416666666662
},
“id”: “4646e6d9-c26e-4194-8277-1b4a49301501”,
“name”: “Note3”,
“type”: “n8n-nodes-base.stickyNote”,
“position”: [
320,
380
],
“typeVersion”: 1
},
{
“parameters”: {
“filters”: {}
},
“id”: “9535463d-099c-44ef-b092-19607aa9cf9f”,
“name”: “n8n”,
“type”: “n8n-nodes-base.n8n”,
“position”: [
-740,
720
],
“typeVersion”: 1,
“credentials”: {
“n8nApi”: {
“id”: “16”,
“name”: “n8n account”
}
}
},
{
“parameters”: {
“jsCode”: “// File Returned with Content\nif (Object.keys($input.all()[0].json).includes("content")) {\n // Get JSON Objects\n var origWorkflow = JSON.parse(Buffer.from($input.all()[0].json.content, ‘base64’));\n var n8nWorkflow = $input.all()[1].json;\n \n // Order JSON Objects\n var orderedOriginal = {}\n var orderedActual = {}\n \n Object.keys(origWorkflow).sort().forEach(function(key) {\n orderedOriginal[key] = origWorkflow[key];\n });\n \n Object.keys(n8nWorkflow).sort().forEach(function(key) {\n orderedActual[key] = n8nWorkflow[key];\n });\n\n // Determine Difference\n if ( JSON.stringify(orderedOriginal) === JSON.stringify(orderedActual) ) {\n $input.all()[0].json.github_status = "same";\n $input.all()[0].json.content_decoded = orderedOriginal;\n } else {\n $input.all()[0].json.github_status = "different";\n $input.all()[0].json.content_decoded = orderedOriginal;\n $input.all()[0].json.n8n_data_stringy = JSON.stringify(orderedActual, null, 2);\n }\n// No File Returned / New Workflow\n} else {\n // Order JSON Object\n var n8nWorkflow = ($input.all()[1].json);\n var orderedActual = {}\n Object.keys(n8nWorkflow).sort().forEach(function(key) {\n orderedActual[key] = n8nWorkflow[key];\n });\n \n // Proper Formatting\n $input.all()[0].json.github_status = "new";\n $input.all()[0].json.n8n_data_stringy = JSON.stringify(orderedActual, null, 2);\n}\n\n// Return Items\nreturn $input.all();”
},
“id”: “35d1c786-9764-4c59-9143-e1fc69badcb5”,
“name”: “isDiffOrNew”,
“type”: “n8n-nodes-base.code”,
“position”: [
120,
700
],
“typeVersion”: 1
},
{
“parameters”: {},
“id”: “f7e8f785-0aa8-4994-9c69-db1fc929c4ea”,
“name”: “Merge”,
“type”: “n8n-nodes-base.merge”,
“position”: [
-60,
700
],
“typeVersion”: 2
}
],
“pinData”: {},
“connections”: {
“n8n”: {
“main”: [
[
{
“node”: “OneAtATime”,
“type”: “main”,
“index”: 0
}
]
]
},
“new”: {
“main”: [
[
{
“node”: “GitHub Create”,
“type”: “main”,
“index”: 0
}
]
]
},
“same”: {
“main”: [
[
{
“node”: “OneAtATime”,
“type”: “main”,
“index”: 0
}
]
]
},
“Merge”: {
“main”: [
[
{
“node”: “isDiffOrNew”,
“type”: “main”,
“index”: 0
}
]
]
},
“GitHub”: {
“main”: [
[
{
“node”: “Merge”,
“type”: “main”,
“index”: 0
}
]
]
},
“Globals”: {
“main”: [
[
{
“node”: “n8n”,
“type”: “main”,
“index”: 0
}
]
]
},
“different”: {
“main”: [
[
{
“node”: “GitHub Edit”,
“type”: “main”,
“index”: 0
}
]
]
},
“OneAtATime”: {
“main”: [
[
{
“node”: “GitHub”,
“type”: “main”,
“index”: 0
},
{
“node”: “Merge”,
“type”: “main”,
“index”: 1
}
]
]
},
“GitHub Edit”: {
“main”: [
[
{
“node”: “OneAtATime”,
“type”: “main”,
“index”: 0
}
]
]
},
“isDiffOrNew”: {
“main”: [
[
{
“node”: “github_status”,
“type”: “main”,
“index”: 0
}
]
]
},
“GitHub Create”: {
“main”: [
[
{
“node”: “OneAtATime”,
“type”: “main”,
“index”: 0
}
]
]
},
“github_status”: {
“main”: [
[
{
“node”: “same”,
“type”: “main”,
“index”: 0
}
],
[
{
“node”: “different”,
“type”: “main”,
“index”: 0
}
],
[
{
“node”: “new”,
“type”: “main”,
“index”: 0
}
]
]
},
“Every 12 hours”: {
“main”: [
[
{
“node”: “Globals”,
“type”: “main”,
“index”: 0
}
]
]
},
“On clicking ‘execute’”: {
“main”: [
[
{
“node”: “Globals”,
“type”: “main”,
“index”: 0
}
]
]
}
},
“active”: false,
“settings”: {},
“versionId”: “d8222ac1-2496-4724-834a-66a9b22502d5”,
“id”: 28,
“meta”: {
“instanceId”: “377bfe01e179cd2fef6b779f65cf03d1a502288906de51e0fcad84dfc65d11c6”
},
“tags”: []
}
Information on your n8n setup
- n8n version: : Version 0.209.4
- Database you’re using (default: SQLite): : Heroku Postgres
- Running n8n with the execution process [own(default), main]: : default
- Running n8n via [Docker, npm, n8n.cloud, desktop app]: : npm / Heroku
Happy to provide more details if someone can lend me a hand
Have a great day