Workflow-Backup in ein Git-Repository auf Gitea
Experte
Dies ist ein Other-Bereich Automatisierungsworkflow mit 20 Nodes. Hauptsächlich werden If, N8n, Set, Code, HttpRequest und andere Nodes verwendet. Backup von Arbeitsabläufen in ein git-Repository auf Gitea
Voraussetzungen
- •Möglicherweise sind Ziel-API-Anmeldedaten erforderlich
Verwendete Nodes (20)
Kategorie
Workflow-Vorschau
Visualisierung der Node-Verbindungen, mit Zoom und Pan
Workflow exportieren
Kopieren Sie die folgende JSON-Konfiguration und importieren Sie sie in n8n
{
"id": "Ef2uEM6H19K2DGUO",
"meta": {
"templateId": "2532",
"templateCredsSetupCompleted": true
},
"name": "Backup workflows to git repository on Gitea",
"tags": [
{
"id": "UWNX4AzSneYNvTQI",
"name": "Gitea",
"createdAt": "2025-01-28T23:10:06.823Z",
"updatedAt": "2025-01-28T23:10:06.823Z"
},
{
"id": "4b7Bs9T0Cagsg5tT",
"name": "Git",
"createdAt": "2025-01-28T23:10:26.545Z",
"updatedAt": "2025-01-28T23:10:26.545Z"
},
{
"id": "HiN3ehC2KkAp5kVs",
"name": "Backup",
"createdAt": "2025-01-28T23:10:38.878Z",
"updatedAt": "2025-01-28T23:10:38.878Z"
}
],
"nodes": [
{
"id": "639582ef-f13e-4844-bd10-647718079121",
"name": "Globals",
"type": "n8n-nodes-base.set",
"position": [
600,
240
],
"parameters": {
"values": {
"string": [
{
"name": "repo.url",
"value": "https://git.vdm.dev"
},
{
"name": "repo.name",
"value": "workflows"
},
{
"name": "repo.owner",
"value": "n8n"
}
]
},
"options": {}
},
"typeVersion": 1
},
{
"id": "9df89713-220e-43b9-b234-b8f5612629cf",
"name": "n8n",
"type": "n8n-nodes-base.n8n",
"position": [
840,
240
],
"parameters": {
"filters": {},
"requestOptions": {}
},
"credentials": {
"n8nApi": {
"id": "ZjfxOLTTHX2CzbKa",
"name": "Main N8N Account"
}
},
"typeVersion": 1
},
{
"id": "4b2d375c-a339-404c-babd-555bd2fc4091",
"name": "Zeitplan-Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
380,
240
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 45
}
]
}
},
"typeVersion": 1.2
},
{
"id": "ea026e96-0db1-41fd-b003-2f2bf4662696",
"name": "Haftnotiz",
"type": "n8n-nodes-base.stickyNote",
"position": [
2620,
300
],
"parameters": {
"height": 80,
"content": "Workflow changes committed to the repository"
},
"typeVersion": 1
},
{
"id": "9c402daa-6d03-485d-b8a0-58f1b65d396d",
"name": "Haftnotiz1",
"type": "n8n-nodes-base.stickyNote",
"position": [
2260,
180
],
"parameters": {
"height": 80,
"content": "Check if there are any changes in the workflow"
},
"typeVersion": 1
},
{
"id": "1d9216d9-bf8d-4945-8a58-22fb1ffc9be8",
"name": "Haftnotiz2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1800,
580
],
"parameters": {
"height": 80,
"content": "Create a new file for the workflow"
},
"typeVersion": 1
},
{
"id": "60a3953b-d9f1-4afd-b299-e314116b96c6",
"name": "Haftnotiz3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1300,
200
],
"parameters": {
"height": 80,
"content": "Check if file exists in the repository"
},
"typeVersion": 1
},
{
"id": "f2340ad0-71a1-4c74-8d90-bcb974b8b305",
"name": "Haftnotiz5",
"type": "n8n-nodes-base.stickyNote",
"position": [
780,
180
],
"parameters": {
"height": 80,
"content": "Get all workflows"
},
"typeVersion": 1
},
{
"id": "617bea19-341a-4e9d-b6fd-6b417e58d756",
"name": "Haftnotiz6",
"type": "n8n-nodes-base.stickyNote",
"position": [
500,
180
],
"parameters": {
"height": 80,
"content": "Set variables"
},
"typeVersion": 1
},
{
"id": "72f806d7-e30a-470b-9ba2-37fdc35de3c8",
"name": "SetzenDataUpdateNode",
"type": "n8n-nodes-base.set",
"position": [
1920,
240
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "0a6b769a-c66d-4784-92c7-a70caa28e1ba",
"name": "item",
"type": "object",
"value": "={{ $node[\"ForEach\"].json }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "bca5e2c4-7aa3-48df-9e5f-b31977970c28",
"name": "SetzenDataCreateNode",
"type": "n8n-nodes-base.set",
"position": [
1220,
640
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "0a6b769a-c66d-4784-92c7-a70caa28e1ba",
"name": "item",
"type": "object",
"value": "={{ $node[\"ForEach\"].json }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "bf74b1ea-e066-462b-9c3d-ed4a44a09a33",
"name": "Base64EncodeUpdate",
"type": "n8n-nodes-base.code",
"position": [
2140,
240
],
"parameters": {
"language": "python",
"pythonCode": "import json\nimport base64\nfrom js import Object\n\n# Assuming _input.all() returns a JavaScript object\njs_object = _input.all()\n\n# Convert the JsProxy object to a Python dictionary\ndef js_to_py(js_obj):\n if isinstance(js_obj, (str, int, float, bool)) or js_obj is None:\n # Base types are already Python-compatible\n return js_obj\n elif isinstance(js_obj, list):\n # Convert lists recursively\n return [js_to_py(item) for item in js_obj]\n elif hasattr(js_obj, \"__iter__\") and not isinstance(js_obj, str):\n # Handle JsProxy objects (JavaScript objects or arrays)\n if hasattr(js_obj, \"keys\"):\n # If it has keys, treat it as a dictionary\n return {key: js_to_py(js_obj[key]) for key in Object.keys(js_obj)}\n else:\n # Otherwise, treat it as a list\n return [js_to_py(item) for item in js_obj]\n else:\n # Fallback for other types\n return js_obj\n\n# Convert the JavaScript object to a Python dictionary\ninput_dict = js_to_py(js_object)\n\n# Step 0: get the correct data set of the workflow\ninner_data = input_dict[0].get('json').get('item')\n\n# Step 1: Convert the dictionary to a pretty-printed JSON string\njson_string = json.dumps(inner_data, indent=4)\n\n# Step 2: Encode the JSON string to bytes\njson_bytes = json_string.encode('utf-8')\n\n# Step 3: Convert the bytes to a base64 string\nbase64_string = base64.b64encode(json_bytes).decode('utf-8')\n\n# Step 5: Create the return object with the base64 string and its SHA-256 hash\nreturn_object = {\n \"item\": base64_string\n}\n\n# Return the object\nreturn return_object"
},
"typeVersion": 2
},
{
"id": "2d817c66-5aa0-45c9-b851-4b5e3dbecca4",
"name": "Base64EncodeCreate",
"type": "n8n-nodes-base.code",
"position": [
1520,
640
],
"parameters": {
"language": "python",
"pythonCode": "import json\nimport base64\nfrom js import Object\n\n# Assuming _input.all() returns a JavaScript object\njs_object = _input.all()\n\n# Convert the JsProxy object to a Python dictionary\ndef js_to_py(js_obj):\n if isinstance(js_obj, (str, int, float, bool)) or js_obj is None:\n # Base types are already Python-compatible\n return js_obj\n elif isinstance(js_obj, list):\n # Convert lists recursively\n return [js_to_py(item) for item in js_obj]\n elif hasattr(js_obj, \"__iter__\") and not isinstance(js_obj, str):\n # Handle JsProxy objects (JavaScript objects or arrays)\n if hasattr(js_obj, \"keys\"):\n # If it has keys, treat it as a dictionary\n return {key: js_to_py(js_obj[key]) for key in Object.keys(js_obj)}\n else:\n # Otherwise, treat it as a list\n return [js_to_py(item) for item in js_obj]\n else:\n # Fallback for other types\n return js_obj\n\n# Convert the JavaScript object to a Python dictionary\ninput_dict = js_to_py(js_object)\n\n# Step 0: get the correct data set of the workflow\ninner_data = input_dict[0].get('json').get('item')\n\n# Step 1: Convert the dictionary to a pretty-printed JSON string\njson_string = json.dumps(inner_data, indent=4)\n\n# Step 2: Encode the JSON string to bytes\njson_bytes = json_string.encode('utf-8')\n\n# Step 3: Convert the bytes to a base64 string\nbase64_string = base64.b64encode(json_bytes).decode('utf-8')\n\n# Step 4: Create the return object with the base64 string in 'item'\nreturn_object = {\n \"item\": base64_string\n}\n\n# Return the object\nreturn return_object"
},
"typeVersion": 2
},
{
"id": "41a7da89-1c8c-4100-8c30-d0788962efc1",
"name": "Exist",
"type": "n8n-nodes-base.if",
"position": [
1640,
260
],
"parameters": {
"options": {
"ignoreCase": false
},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "16a9182d-059d-4774-ba95-654fb4293fdb",
"operator": {
"type": "object",
"operation": "notExists",
"singleValue": true
},
"leftValue": "={{ $json.error }}",
"rightValue": 404
}
]
}
},
"executeOnce": false,
"typeVersion": 2.2,
"alwaysOutputData": false
},
{
"id": "ab9246eb-a253-4d76-b33b-5f8f12342542",
"name": "Changed",
"type": "n8n-nodes-base.if",
"position": [
2360,
240
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "e0c66624-429a-4f1f-bf7b-1cc1b32bad7b",
"operator": {
"type": "string",
"operation": "notEquals"
},
"leftValue": "={{ $json.item }}",
"rightValue": "={{ $('GetGitea').item.json.content }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "4278a176-6496-4817-82f8-591539619673",
"name": "PutGitea",
"type": "n8n-nodes-base.httpRequest",
"position": [
2700,
360
],
"parameters": {
"url": "={{ $('Globals').item.json.repo.url }}/api/v1/repos/{{ $('Globals').item.json.repo.owner }}/{{ $('Globals').item.json.repo.name }}/contents/{{ encodeURIComponent($('GetGitea').item.json.name) }}",
"method": "PUT",
"options": {},
"sendBody": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "content",
"value": "={{ $('Base64EncodeUpdate').item.json.item }}"
},
{
"name": "sha",
"value": "={{ $('GetGitea').item.json.sha }}"
}
]
},
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "gTvBAgkOmqhl5Nmr",
"name": "Gitea Token"
}
},
"typeVersion": 4.2
},
{
"id": "12307a61-e7cc-42f9-a7c7-8abbcab9e3ab",
"name": "GetGitea",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
1380,
260
],
"parameters": {
"url": "={{ $('Globals').item.json.repo.url }}/api/v1/repos/{{ encodeURIComponent($('Globals').item.json.repo.owner) }}/{{ encodeURIComponent($('Globals').item.json.repo.name) }}/contents/{{ encodeURIComponent($json.name) }}.json",
"options": {},
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "gTvBAgkOmqhl5Nmr",
"name": "Gitea Token"
}
},
"typeVersion": 4.2
},
{
"id": "24fda439-bb23-4392-a297-d8070907f9e6",
"name": "PostGitea",
"type": "n8n-nodes-base.httpRequest",
"position": [
1920,
640
],
"parameters": {
"url": "={{ $('Globals').item.json.repo.url }}/api/v1/repos/{{ $('Globals').item.json.repo.owner }}/{{ $('Globals').item.json.repo.name }}/contents/{{ encodeURIComponent($('ForEach').item.json.name) }}.json",
"method": "POST",
"options": {},
"sendBody": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "content",
"value": "={{ $json.item }}"
}
]
},
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "gTvBAgkOmqhl5Nmr",
"name": "Gitea Token"
}
},
"typeVersion": 4.2
},
{
"id": "43a60315-d381-4ac4-be4c-f6a158651a00",
"name": "ForEach",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1060,
240
],
"parameters": {
"options": {}
},
"executeOnce": false,
"typeVersion": 3
},
{
"id": "88578dc4-2398-48d0-b0ba-2198b35bb994",
"name": "Haftnotiz4",
"type": "n8n-nodes-base.stickyNote",
"position": [
380,
440
],
"parameters": {
"width": 560,
"height": 1620,
"content": "### **📌 Setup Guide for Backup Workflows to Git Repository on Gitea**\n\n#### **🔧 1. Configure Global Variables**\nGo to the **Globals** node and update the following:\n- **`repo.url`** → `https://your-gitea-instance.com` *(Replace with your actual Gitea URL)*\n- **`repo.name`** → `workflows` *(Repository name where backups will be stored)*\n- **`repo.owner`** → `octoleo` *(Gitea account that owns the repository)*\n\n📌 **These settings define where workflows will be backed up.**\n\n---\n\n#### **🔑 2. Set Up Gitea Authentication**\n1️⃣ **In Gitea:**\n- Generate a **Personal Access Token** under **Settings → Applications → Generate Token**\n- Ensure the token has **repo read/write permissions**\n\n2️⃣ **In the Credentials Manager:**\n- Create a new **Gitea Token** credential\n- Set the **Name** as `Authorization`\n- Set the **Value** as:\n```\nBearer YOUR_PERSONAL_ACCESS_TOKEN\n```\n📌 **Ensure there is a space after `Bearer` before the token!**\n\n---\n\n#### **🔗 3. Connect Gitea Credentials to Git Nodes**\n- Open each of these **three Git nodes**:\n- **GetGitea** → Retrieves existing repository data\n- **PutGitea** → Updates workflows\n- **PostGitea** → Adds new workflows\n\n- Assign the **Gitea Token** credential to each node.\n\n📌 **These nodes handle pushing your workflows to Gitea.**\n\n---\n\n#### **🌐 4. Set Up API Credentials for Workflow Retrieval**\n- Locate the API request node that **fetches workflows**.\n- Add your **API authentication credentials** (Token or Basic Auth).\n\n📌 **This ensures the workflow can fetch all available workflows from your system.**\n\n---\n\n#### **🛠️ 5. Test & Activate the Workflow**\n✅ **Run the workflow manually** → Check that workflows are being backed up correctly.\n✅ **Review the Gitea repository** → Ensure the files are updated.\n✅ **Enable the scheduled trigger** → Automates backups at defined intervals.\n\n📌 **The workflow automatically checks for changes before committing updates!**\n\n---\n\n### **🚀 Done! Your Workflows Are Now Backed Up Securely!**\n💬 Have issues? **Reach out on the forum for help!**"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "84ba3f3f-fbc8-4792-8e28-198f515fef4e",
"staticData": {
"node:Schedule Trigger": {
"recurrenceRules": []
}
},
"connections": {
"9df89713-220e-43b9-b234-b8f5612629cf": {
"main": [
[
{
"node": "43a60315-d381-4ac4-be4c-f6a158651a00",
"type": "main",
"index": 0
}
]
]
},
"41a7da89-1c8c-4100-8c30-d0788962efc1": {
"main": [
[
{
"node": "SetDataUpdateNode",
"type": "main",
"index": 0
}
],
[
{
"node": "SetDataCreateNode",
"type": "main",
"index": 0
}
]
]
},
"ab9246eb-a253-4d76-b33b-5f8f12342542": {
"main": [
[
{
"node": "4278a176-6496-4817-82f8-591539619673",
"type": "main",
"index": 0
}
],
[
{
"node": "43a60315-d381-4ac4-be4c-f6a158651a00",
"type": "main",
"index": 0
}
]
]
},
"43a60315-d381-4ac4-be4c-f6a158651a00": {
"main": [
[],
[
{
"node": "12307a61-e7cc-42f9-a7c7-8abbcab9e3ab",
"type": "main",
"index": 0
}
]
]
},
"639582ef-f13e-4844-bd10-647718079121": {
"main": [
[
{
"node": "9df89713-220e-43b9-b234-b8f5612629cf",
"type": "main",
"index": 0
}
]
]
},
"12307a61-e7cc-42f9-a7c7-8abbcab9e3ab": {
"main": [
[
{
"node": "41a7da89-1c8c-4100-8c30-d0788962efc1",
"type": "main",
"index": 0
}
]
]
},
"4278a176-6496-4817-82f8-591539619673": {
"main": [
[
{
"node": "43a60315-d381-4ac4-be4c-f6a158651a00",
"type": "main",
"index": 0
}
]
]
},
"24fda439-bb23-4392-a297-d8070907f9e6": {
"main": [
[
{
"node": "43a60315-d381-4ac4-be4c-f6a158651a00",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "639582ef-f13e-4844-bd10-647718079121",
"type": "main",
"index": 0
}
]
]
},
"SetDataCreateNode": {
"main": [
[
{
"node": "2d817c66-5aa0-45c9-b851-4b5e3dbecca4",
"type": "main",
"index": 0
}
]
]
},
"SetDataUpdateNode": {
"main": [
[
{
"node": "bf74b1ea-e066-462b-9c3d-ed4a44a09a33",
"type": "main",
"index": 0
}
]
]
},
"2d817c66-5aa0-45c9-b851-4b5e3dbecca4": {
"main": [
[
{
"node": "24fda439-bb23-4392-a297-d8070907f9e6",
"type": "main",
"index": 0
}
]
]
},
"bf74b1ea-e066-462b-9c3d-ed4a44a09a33": {
"main": [
[
{
"node": "ab9246eb-a253-4d76-b33b-5f8f12342542",
"type": "main",
"index": 0
}
]
]
}
},
"triggerCount": 1
}Häufig gestellte Fragen
Wie verwende ich diesen Workflow?
Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.
Für welche Szenarien ist dieser Workflow geeignet?
Experte - Sonstiges
Ist es kostenpflichtig?
Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.
Verwandte Workflows
Workflows zu GitHub (Unterordner) sichern
Sichere Workflows in GitHub (Unterverzeichnis)
If
N8n
Set
+
If
N8n
Set
25 NodesNazmy
Sonstiges
Workflows zu GitHub sichern
Sichere Workflows in GitHub
If
N8n
Set
+
If
N8n
Set
23 NodesSolomon
Sonstiges
KI-Agent Restaurant [Vorlage]
🤖 KI-Restaurantassistent für WhatsApp, Instagram und Messenger
If
N8n
Set
+
If
N8n
Set
239 NodesAmanda Benks
Sonstiges
Stündlicher Ausführungsversuch
Automatische Wiederholungs-Engine: Fehler-Wiederherstellungs-Workflows
If
N8n
Set
+
If
N8n
Set
14 NodesFrancis Njenga
Sonstiges
n8n-Workflows zu Bitbucket sichern
Sichere n8n Workflows in Bitbucket
If
N8n
Set
+
If
N8n
Set
9 NodesGareth B. Davies
Sonstiges
Workflows zu Git-Repository sichern
Sichere Workflows in ein git-Repository auf Github
If
N8n
Set
+
If
N8n
Set
17 NodesShashikanth
Sonstiges
Workflow-Informationen
Schwierigkeitsgrad
Experte
Anzahl der Nodes20
Kategorie1
Node-Typen8
Autor
Octoleo
@octoleoHi, I’m Llewellyn van der Merwe, also known as <<ewe>>yn, pioneering tools to automate freedom!
Externe Links
Auf n8n.io ansehen →
Diesen Workflow teilen