Copia de seguridad de flujos de trabajo a GitHub
Este es unDevOpsflujo de automatización del dominio deautomatización que contiene 23 nodos.Utiliza principalmente nodos como If, N8n, Set, Merge, Slack. Copia de seguridad automatizada de flujos de trabajo a GitHub, con creación de PR y notificación de Slack
- •Bot Token de Slack o URL de Webhook
- •Personal Access Token de GitHub
- •Pueden requerirse credenciales de autenticación para la API de destino
Nodos utilizados (23)
Categoría
{
"id": "GZqZRs30KLvYLk4T",
"meta": {
"instanceId": "e76981884963d13b9deb7bc5a6b15daf6838937e1dd529f22f2c146d8b79cae4",
"templateCredsSetupCompleted": true
},
"name": "Backup workflows to GitHub",
"tags": [],
"nodes": [
{
"id": "3abc6972-965d-4333-b1d2-d7097ea077da",
"name": "n8n",
"type": "n8n-nodes-base.n8n",
"position": [
660,
-300
],
"parameters": {
"filters": {},
"requestOptions": {}
},
"credentials": {
"n8nApi": {
"id": "f2iSnAHCaePA8jyU",
"name": "n8n account"
}
},
"typeVersion": 1
},
{
"id": "9c386d7c-dc48-4f92-bc2f-5c5772e931f8",
"name": "Buscar nuevos flujos de trabajo",
"type": "n8n-nodes-base.merge",
"position": [
880,
-250
],
"parameters": {
"mode": "combine",
"options": {},
"joinMode": "keepNonMatches",
"outputDataFrom": "input1",
"fieldsToMatchString": "id"
},
"typeVersion": 3.1,
"alwaysOutputData": true
},
{
"id": "a82b074d-b12f-49f9-a69b-492847bb3dfd",
"name": "Buscar flujos de trabajo actualizados",
"type": "n8n-nodes-base.merge",
"position": [
880,
0
],
"parameters": {
"mode": "combine",
"options": {},
"joinMode": "keepNonMatches",
"outputDataFrom": "input1",
"fieldsToMatchString": "id, updatedAt"
},
"typeVersion": 3.1,
"alwaysOutputData": true
},
{
"id": "8d6181f4-873b-46ad-aa88-a6005f78e618",
"name": "Esperar finalización de creación/edición en GitHub",
"type": "n8n-nodes-base.merge",
"position": [
2680,
-140
],
"parameters": {},
"typeVersion": 3.1
},
{
"id": "aefdbaf3-bbb9-426b-bc01-1dfd1f094a87",
"name": "Crear nuevo PR mediante GitHub API",
"type": "n8n-nodes-base.httpRequest",
"position": [
2900,
-140
],
"parameters": {
"url": "=https://api.github.com/repos/{{ $('Define Local Variables').item.json.github_owner }}/{{ $('Define Local Variables').item.json.repo_name }}/pulls",
"method": "POST",
"options": {},
"jsonBody": "={\n\"title\": \"Automated PR for {{ $('Define Local Variables').item.json.branch_name }}\",\n\"body\": \"\",\n\"head\": \"{{ $('Define Local Variables').item.json.branch_name }}\",\n\"base\": \"main\"\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "githubApi"
},
"credentials": {
"githubApi": {
"id": "R8n2QZnsA7dlSq4d",
"name": "GitHub account"
}
},
"executeOnce": true,
"typeVersion": 4.2
},
{
"id": "bdcd0ef4-ebcd-43fc-b320-ee62bb3b9c71",
"name": "Definir variables locales",
"type": "n8n-nodes-base.set",
"position": [
40,
-160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "575b2ca9-528f-421f-8352-073c916fcd63",
"name": "branch_name",
"type": "string",
"value": "=workflows_{{ $now.format('yyyy-MM-dd-hh-mm-ss')}}"
},
{
"id": "6f7a1168-1c55-4e50-b7d2-0868104ee1db",
"name": "github_owner",
"type": "string",
"value": "duynb92"
},
{
"id": "9c8cf8ba-9e64-4fb5-ba38-8429264c84dd",
"name": "repo_name",
"type": "string",
"value": "n8n-workflows"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b74a8a0c-5205-47fd-a9c9-60d8299a4254",
"name": "Obtener todos los flujos en GitHub",
"type": "n8n-nodes-base.github",
"position": [
220,
50
],
"webhookId": "481a47c9-57bf-4c5f-a9c8-7246190c4b3c",
"parameters": {
"owner": {
"__rl": true,
"mode": "name",
"value": "={{ $('Define Local Variables').item.json.github_owner }}"
},
"filePath": "workflows",
"resource": "file",
"operation": "list",
"repository": {
"__rl": true,
"mode": "name",
"value": "={{ $('Define Local Variables').item.json.repo_name }}"
}
},
"credentials": {
"githubApi": {
"id": "R8n2QZnsA7dlSq4d",
"name": "GitHub account"
}
},
"typeVersion": 1.1
},
{
"id": "fd86d8e4-948e-4679-a995-87fcad2ceaaf",
"name": "Obtener contenido de cada flujo",
"type": "n8n-nodes-base.github",
"position": [
440,
50
],
"webhookId": "bfb94e71-96eb-4fc3-9fe0-1b5255d48b53",
"parameters": {
"owner": {
"__rl": true,
"mode": "name",
"value": "={{ $('Define Local Variables').item.json.github_owner }}"
},
"filePath": "={{ $json.path }}",
"resource": "file",
"operation": "get",
"repository": {
"__rl": true,
"mode": "name",
"value": "={{ $('Define Local Variables').item.json.repo_name }}"
},
"asBinaryProperty": false,
"additionalParameters": {}
},
"credentials": {
"githubApi": {
"id": "R8n2QZnsA7dlSq4d",
"name": "GitHub account"
}
},
"typeVersion": 1.1
},
{
"id": "60b86288-22cd-460e-9da2-67de123b1cb1",
"name": "Decodificar contenido Base64",
"type": "n8n-nodes-base.set",
"position": [
660,
50
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={{ $json.content.base64Decode() }}"
},
"typeVersion": 3.4
},
{
"id": "fc4d4f78-e6b3-418f-8c4f-8ad70eb5a32b",
"name": "Esperar finalización",
"type": "n8n-nodes-base.merge",
"position": [
1100,
-125
],
"parameters": {
"mode": "chooseBranch",
"output": "empty"
},
"typeVersion": 3.1
},
{
"id": "08db5cda-4059-4e96-9732-63bc824daa5d",
"name": "Si hay cambios en los flujos",
"type": "n8n-nodes-base.if",
"position": [
1320,
-125
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "cec5563a-01dd-4372-882a-2114c8e476a7",
"operator": {
"type": "array",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $('Find updated workflows').all() }}",
"rightValue": ""
},
{
"id": "fb800963-acc7-495f-8bf2-c29c3b3d0450",
"operator": {
"type": "array",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $('Find new workflows').all() }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "45369a54-bc73-4287-9037-1286d8a9690d",
"name": "Sin operación (no hacer nada)",
"type": "n8n-nodes-base.noOp",
"position": [
1560,
160
],
"parameters": {},
"typeVersion": 1
},
{
"id": "d8b8a670-3ea1-4d5f-86e9-537f72d964fc",
"name": "Crear rama mediante GitHub API",
"type": "n8n-nodes-base.httpRequest",
"position": [
1760,
-125
],
"parameters": {
"url": "=https://api.github.com/repos/{{ $('Define Local Variables').item.json.github_owner }}/{{ $('Define Local Variables').item.json.repo_name }}/git/refs",
"method": "POST",
"options": {},
"jsonBody": "={\n \"ref\": \"refs/heads/{{ $('Define Local Variables').item.json.branch_name }}\",\n \"sha\": \"{{ $json.object.sha }}\"\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "githubApi"
},
"credentials": {
"githubApi": {
"id": "R8n2QZnsA7dlSq4d",
"name": "GitHub account"
}
},
"executeOnce": true,
"typeVersion": 4.2
},
{
"id": "4292f0e4-3012-4165-bcda-e4a1519ca80c",
"name": "Obtener SHA de commit principal en GitHub API",
"type": "n8n-nodes-base.httpRequest",
"position": [
1540,
-125
],
"parameters": {
"url": "=https://api.github.com/repos/{{ $('Define Local Variables').item.json.github_owner }}/{{ $('Define Local Variables').item.json.repo_name }}/git/ref/heads/main",
"options": {},
"authentication": "predefinedCredentialType",
"nodeCredentialType": "githubApi"
},
"credentials": {
"githubApi": {
"id": "R8n2QZnsA7dlSq4d",
"name": "GitHub account"
}
},
"executeOnce": true,
"typeVersion": 4.2
},
{
"id": "d0d727d9-f547-440b-8213-9ec5ce23c1fa",
"name": "Esperar creación de rama",
"type": "n8n-nodes-base.merge",
"position": [
1980,
0
],
"parameters": {
"mode": "chooseBranch",
"useDataOfInput": 2
},
"typeVersion": 3.1,
"alwaysOutputData": false
},
{
"id": "89f36b7c-6de1-4069-83bd-8b6aeed4a069",
"name": "Esperar creación de rama1",
"type": "n8n-nodes-base.merge",
"position": [
1980,
-250
],
"parameters": {
"mode": "chooseBranch",
"useDataOfInput": 2
},
"typeVersion": 3.1,
"alwaysOutputData": false
},
{
"id": "f8088f5b-cb9a-40eb-ab8f-de6aeddfdaa6",
"name": "Filtrar datos vacíos",
"type": "n8n-nodes-base.filter",
"notes": "Empty data can happen because 'Find new workflows' always output data",
"position": [
2200,
-250
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "835f2dab-de42-4c97-a747-47b23d55c990",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.id }}",
"rightValue": ""
}
]
}
},
"notesInFlow": true,
"typeVersion": 2.2
},
{
"id": "157955f3-88bf-448d-b424-c71ba32d4fb5",
"name": "Filtrar datos vacíos1",
"type": "n8n-nodes-base.filter",
"notes": "Empty data can happen because 'Find updated workflows' always output data",
"position": [
2200,
0
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "1d8312fd-5157-4058-823c-35f7574541fa",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.id }}",
"rightValue": ""
}
]
}
},
"notesInFlow": true,
"typeVersion": 2.2
},
{
"id": "0c3e9957-d4e8-4b30-b368-7698087b37e7",
"name": "Crear commit para nuevo flujo",
"type": "n8n-nodes-base.github",
"position": [
2420,
-250
],
"webhookId": "843c09e3-953a-40c4-a208-38acdd2ea466",
"parameters": {
"owner": {
"__rl": true,
"mode": "name",
"value": "={{ $('Define Local Variables').item.json.github_owner }}"
},
"filePath": "=workflows/{{ $json.id }}.json",
"resource": "file",
"repository": {
"__rl": true,
"mode": "name",
"value": "={{ $('Define Local Variables').item.json.repo_name }}"
},
"fileContent": "={{ $json.toJsonString() }}",
"commitMessage": "=Add new workflow {{ $json.id }}",
"additionalParameters": {
"branch": {
"branch": "={{ $('Define Local Variables').item.json.branch_name }}"
}
}
},
"credentials": {
"githubApi": {
"id": "R8n2QZnsA7dlSq4d",
"name": "GitHub account"
}
},
"typeVersion": 1.1
},
{
"id": "fd5091b9-7c6e-4408-8656-4dac64f10088",
"name": "Crear commit para flujo actualizado",
"type": "n8n-nodes-base.github",
"position": [
2420,
0
],
"webhookId": "843c09e3-953a-40c4-a208-38acdd2ea466",
"parameters": {
"owner": {
"__rl": true,
"mode": "name",
"value": "={{ $('Define Local Variables').item.json.github_owner }}"
},
"filePath": "=workflows/{{ $json.id }}.json",
"resource": "file",
"operation": "edit",
"repository": {
"__rl": true,
"mode": "name",
"value": "={{ $('Define Local Variables').item.json.repo_name }}"
},
"fileContent": "={{ $json.toJsonString() }}",
"commitMessage": "=Update workflow {{ $json.id }}",
"additionalParameters": {
"branch": {
"branch": "={{ $('Define Local Variables').item.json.branch_name }}"
}
}
},
"credentials": {
"githubApi": {
"id": "R8n2QZnsA7dlSq4d",
"name": "GitHub account"
}
},
"typeVersion": 1.1
},
{
"id": "63a97673-c96e-43ca-b3b2-cf264b2b1381",
"name": "Slack",
"type": "n8n-nodes-base.slack",
"position": [
3120,
-140
],
"webhookId": "799530a9-9c2f-482e-9265-a2d58663223e",
"parameters": {
"text": "=:firework: {{ $workflow.name }} executed succesfully. \nIt created a new <{{ $json.html_url }}|GitHub PR>.",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C08NZ6D9CRF",
"cachedResultName": "n8n-notifications"
},
"otherOptions": {}
},
"credentials": {
"slackApi": {
"id": "gz8u4Mu9o2dA9gbl",
"name": "Slack Bot Access Token"
}
},
"typeVersion": 2.3
},
{
"id": "1ea514d9-bf41-4de4-938a-68bde8be660b",
"name": "Haz clic para activar",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-200,
-160
],
"parameters": {},
"typeVersion": 1
},
{
"id": "aa9c2d16-d87b-42a6-b8af-6785fe212eee",
"name": "Nota adhesiva",
"type": "n8n-nodes-base.stickyNote",
"position": [
-280,
-500
],
"parameters": {
"width": 280,
"height": 260,
"content": "## Setup\n1. GitHub credentials: Add your GitHub API credentials in n8n.\n2. Slack integration: Connect your Slack Bot token if you want PR notifications.\n3. Repository details: Update github_owner, repo_name, and workflow directory path in the “Define Local Variables” node.\n4. n8n API key - [Check this doc](https://docs.n8n.io/api/authentication/)"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "c2e49f18-b2a4-4ced-a1a7-67dc69926a78",
"connections": {
"3abc6972-965d-4333-b1d2-d7097ea077da": {
"main": [
[
{
"node": "9c386d7c-dc48-4f92-bc2f-5c5772e931f8",
"type": "main",
"index": 0
},
{
"node": "a82b074d-b12f-49f9-a69b-492847bb3dfd",
"type": "main",
"index": 0
}
]
]
},
"f8088f5b-cb9a-40eb-ab8f-de6aeddfdaa6": {
"main": [
[
{
"node": "0c3e9957-d4e8-4b30-b368-7698087b37e7",
"type": "main",
"index": 0
}
]
]
},
"fc4d4f78-e6b3-418f-8c4f-8ad70eb5a32b": {
"main": [
[
{
"node": "08db5cda-4059-4e96-9732-63bc824daa5d",
"type": "main",
"index": 0
}
]
]
},
"157955f3-88bf-448d-b424-c71ba32d4fb5": {
"main": [
[
{
"node": "fd5091b9-7c6e-4408-8656-4dac64f10088",
"type": "main",
"index": 0
}
]
]
},
"9c386d7c-dc48-4f92-bc2f-5c5772e931f8": {
"main": [
[
{
"node": "89f36b7c-6de1-4069-83bd-8b6aeed4a069",
"type": "main",
"index": 1
},
{
"node": "fc4d4f78-e6b3-418f-8c4f-8ad70eb5a32b",
"type": "main",
"index": 0
}
]
]
},
"1ea514d9-bf41-4de4-938a-68bde8be660b": {
"main": [
[
{
"node": "bdcd0ef4-ebcd-43fc-b320-ee62bb3b9c71",
"type": "main",
"index": 0
}
]
]
},
"bdcd0ef4-ebcd-43fc-b320-ee62bb3b9c71": {
"main": [
[
{
"node": "3abc6972-965d-4333-b1d2-d7097ea077da",
"type": "main",
"index": 0
},
{
"node": "b74a8a0c-5205-47fd-a9c9-60d8299a4254",
"type": "main",
"index": 0
}
]
]
},
"a82b074d-b12f-49f9-a69b-492847bb3dfd": {
"main": [
[
{
"node": "fc4d4f78-e6b3-418f-8c4f-8ad70eb5a32b",
"type": "main",
"index": 1
},
{
"node": "d0d727d9-f547-440b-8213-9ec5ce23c1fa",
"type": "main",
"index": 1
}
]
]
},
"d0d727d9-f547-440b-8213-9ec5ce23c1fa": {
"main": [
[
{
"node": "157955f3-88bf-448d-b424-c71ba32d4fb5",
"type": "main",
"index": 0
}
]
]
},
"89f36b7c-6de1-4069-83bd-8b6aeed4a069": {
"main": [
[
{
"node": "f8088f5b-cb9a-40eb-ab8f-de6aeddfdaa6",
"type": "main",
"index": 0
}
]
]
},
"b74a8a0c-5205-47fd-a9c9-60d8299a4254": {
"main": [
[
{
"node": "fd86d8e4-948e-4679-a995-87fcad2ceaaf",
"type": "main",
"index": 0
}
]
]
},
"aefdbaf3-bbb9-426b-bc01-1dfd1f094a87": {
"main": [
[
{
"node": "63a97673-c96e-43ca-b3b2-cf264b2b1381",
"type": "main",
"index": 0
}
]
]
},
"60b86288-22cd-460e-9da2-67de123b1cb1": {
"main": [
[
{
"node": "a82b074d-b12f-49f9-a69b-492847bb3dfd",
"type": "main",
"index": 1
},
{
"node": "9c386d7c-dc48-4f92-bc2f-5c5772e931f8",
"type": "main",
"index": 1
}
]
]
},
"fd86d8e4-948e-4679-a995-87fcad2ceaaf": {
"main": [
[
{
"node": "60b86288-22cd-460e-9da2-67de123b1cb1",
"type": "main",
"index": 0
}
]
]
},
"d8b8a670-3ea1-4d5f-86e9-537f72d964fc": {
"main": [
[
{
"node": "89f36b7c-6de1-4069-83bd-8b6aeed4a069",
"type": "main",
"index": 0
},
{
"node": "d0d727d9-f547-440b-8213-9ec5ce23c1fa",
"type": "main",
"index": 0
}
]
]
},
"0c3e9957-d4e8-4b30-b368-7698087b37e7": {
"main": [
[
{
"node": "8d6181f4-873b-46ad-aa88-a6005f78e618",
"type": "main",
"index": 0
}
]
]
},
"08db5cda-4059-4e96-9732-63bc824daa5d": {
"main": [
[
{
"node": "4292f0e4-3012-4165-bcda-e4a1519ca80c",
"type": "main",
"index": 0
}
],
[
{
"node": "45369a54-bc73-4287-9037-1286d8a9690d",
"type": "main",
"index": 0
}
]
]
},
"8d6181f4-873b-46ad-aa88-a6005f78e618": {
"main": [
[
{
"node": "aefdbaf3-bbb9-426b-bc01-1dfd1f094a87",
"type": "main",
"index": 0
}
]
]
},
"fd5091b9-7c6e-4408-8656-4dac64f10088": {
"main": [
[
{
"node": "8d6181f4-873b-46ad-aa88-a6005f78e618",
"type": "main",
"index": 1
}
]
]
},
"4292f0e4-3012-4165-bcda-e4a1519ca80c": {
"main": [
[
{
"node": "d8b8a670-3ea1-4d5f-86e9-537f72d964fc",
"type": "main",
"index": 0
}
]
]
}
}
}¿Cómo usar este flujo de trabajo?
Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.
¿En qué escenarios es adecuado este flujo de trabajo?
Avanzado - DevOps
¿Es de pago?
Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.
Flujos de trabajo relacionados recomendados
Bao Duy Nguyen
@duynbCompartir este flujo de trabajo