工作流备份至 GitHub
高级
这是一个DevOps领域的自动化工作流,包含 23 个节点。主要使用 If, N8n, Set, Merge, Slack 等节点。 自动化工作流备份至 GitHub,包含 PR 创建和 Slack 通知
前置要求
- •Slack Bot Token 或 Webhook URL
- •GitHub Personal Access Token
- •可能需要目标 API 的认证凭证
分类
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"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": "Find new workflows",
"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": "Find updated workflows",
"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": "Wait for GitHub create/edit file finished",
"type": "n8n-nodes-base.merge",
"position": [
2680,
-140
],
"parameters": {},
"typeVersion": 3.1
},
{
"id": "aefdbaf3-bbb9-426b-bc01-1dfd1f094a87",
"name": "Create new PR via 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": "Define Local Variables",
"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": "Get all workflows on 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": "Get content for each workflow",
"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": "Base64decode workflow content",
"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": "Wait for finished",
"type": "n8n-nodes-base.merge",
"position": [
1100,
-125
],
"parameters": {
"mode": "chooseBranch",
"output": "empty"
},
"typeVersion": 3.1
},
{
"id": "08db5cda-4059-4e96-9732-63bc824daa5d",
"name": "If there are any changes in workflows",
"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": "No Operation, do nothing",
"type": "n8n-nodes-base.noOp",
"position": [
1560,
160
],
"parameters": {},
"typeVersion": 1
},
{
"id": "d8b8a670-3ea1-4d5f-86e9-537f72d964fc",
"name": "Create new branch via 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": "Get latest commit SHA on main via 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": "Wait until branch created",
"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": "Wait until branch created1",
"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": "Filter empty data",
"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": "Filter empty data1",
"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": "Create new commit to add new workflow",
"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": "Create new commit to update changed workflow",
"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": "Click me to trigger",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-200,
-160
],
"parameters": {},
"typeVersion": 1
},
{
"id": "aa9c2d16-d87b-42a6-b8af-6785fe212eee",
"name": "Sticky Note",
"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": {
"n8n": {
"main": [
[
{
"node": "Find new workflows",
"type": "main",
"index": 0
},
{
"node": "Find updated workflows",
"type": "main",
"index": 0
}
]
]
},
"Filter empty data": {
"main": [
[
{
"node": "Create new commit to add new workflow",
"type": "main",
"index": 0
}
]
]
},
"Wait for finished": {
"main": [
[
{
"node": "If there are any changes in workflows",
"type": "main",
"index": 0
}
]
]
},
"Filter empty data1": {
"main": [
[
{
"node": "Create new commit to update changed workflow",
"type": "main",
"index": 0
}
]
]
},
"Find new workflows": {
"main": [
[
{
"node": "Wait until branch created1",
"type": "main",
"index": 1
},
{
"node": "Wait for finished",
"type": "main",
"index": 0
}
]
]
},
"Click me to trigger": {
"main": [
[
{
"node": "Define Local Variables",
"type": "main",
"index": 0
}
]
]
},
"Define Local Variables": {
"main": [
[
{
"node": "n8n",
"type": "main",
"index": 0
},
{
"node": "Get all workflows on GitHub",
"type": "main",
"index": 0
}
]
]
},
"Find updated workflows": {
"main": [
[
{
"node": "Wait for finished",
"type": "main",
"index": 1
},
{
"node": "Wait until branch created",
"type": "main",
"index": 1
}
]
]
},
"Wait until branch created": {
"main": [
[
{
"node": "Filter empty data1",
"type": "main",
"index": 0
}
]
]
},
"Wait until branch created1": {
"main": [
[
{
"node": "Filter empty data",
"type": "main",
"index": 0
}
]
]
},
"Get all workflows on GitHub": {
"main": [
[
{
"node": "Get content for each workflow",
"type": "main",
"index": 0
}
]
]
},
"Create new PR via GitHub API": {
"main": [
[
{
"node": "Slack",
"type": "main",
"index": 0
}
]
]
},
"Base64decode workflow content": {
"main": [
[
{
"node": "Find updated workflows",
"type": "main",
"index": 1
},
{
"node": "Find new workflows",
"type": "main",
"index": 1
}
]
]
},
"Get content for each workflow": {
"main": [
[
{
"node": "Base64decode workflow content",
"type": "main",
"index": 0
}
]
]
},
"Create new branch via GitHub API": {
"main": [
[
{
"node": "Wait until branch created1",
"type": "main",
"index": 0
},
{
"node": "Wait until branch created",
"type": "main",
"index": 0
}
]
]
},
"Create new commit to add new workflow": {
"main": [
[
{
"node": "Wait for GitHub create/edit file finished",
"type": "main",
"index": 0
}
]
]
},
"If there are any changes in workflows": {
"main": [
[
{
"node": "Get latest commit SHA on main via GitHub API",
"type": "main",
"index": 0
}
],
[
{
"node": "No Operation, do nothing",
"type": "main",
"index": 0
}
]
]
},
"Wait for GitHub create/edit file finished": {
"main": [
[
{
"node": "Create new PR via GitHub API",
"type": "main",
"index": 0
}
]
]
},
"Create new commit to update changed workflow": {
"main": [
[
{
"node": "Wait for GitHub create/edit file finished",
"type": "main",
"index": 1
}
]
]
},
"Get latest commit SHA on main via GitHub API": {
"main": [
[
{
"node": "Create new branch via GitHub API",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 开发运维
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
自动化n8n工作流备份至GitHub并追踪删除
自动化n8n工作流备份至GitHub并追踪删除
If
N8n
Set
+13
31 节点Marcial Ambriz
开发运维
将您的工作流保存到 GitHub 仓库
每日工作流备份至 GitHub 并发送 Slack 通知
If
N8n
Set
+10
18 节点Andrew
开发运维
GitHub 同步仪表板 - V2
具有提交历史和回滚功能的 GitHub 工作流版本控制仪表板
If
N8n
Set
+20
94 节点Eduard
开发运维
INST安装程序
打包部署多个n8n工作流 - 含自动凭证映射
If
N8n
Set
+12
31 节点Wyeth
开发运维
从 GitHub 恢复工作流
在拉取请求合并后将 GitHub 工作流同步至 n8n
N8n
Set
Filter
+5
14 节点Bao Duy Nguyen
开发运维
Typebot 流程与 GitHub 双向同步,使用 Typebot API
Typebot 流程与 GitHub 双向同步,使用 Typebot API
If
Set
Code
+12
31 节点Marcial Ambriz
开发运维