8
n8n 한국어amn8n.com

Git 커밋 명령을 기반으로 GitHub PR 자동 생성 및 Jira 업데이트 (다중 저장소)

고급

이것은자동화 워크플로우로, 39개의 노드를 포함합니다.주로 If, Code, Jira, Merge, Slack 등의 노드를 사용하며. Git 커밋 명령어 기반 GitHub PR 자동 생성 및 Jira 업데이트 (다중 저장소)

사전 요구사항
  • Slack Bot Token 또는 Webhook URL
  • Notion API Key
  • HTTP Webhook 엔드포인트(n8n이 자동으로 생성)
  • 대상 API의 인증 정보가 필요할 수 있음

카테고리

-
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "id": "XrACI58wgVlnNv1M",
  "meta": {
    "instanceId": "1a54c41d9050a8f1fa6f74ca858828ad9fb97b9fafa3e9760e576171c531a787"
  },
  "name": "Auto-Create GitHub PRs & Jira Updates from Git Commit Commands (Multi-Repo)",
  "tags": [],
  "nodes": [
    {
      "id": "2dff9822-74ef-47b9-8eda-db563f4718d9",
      "name": "Commit Message Breakdown",
      "type": "n8n-nodes-base.code",
      "position": [
        -2220,
        1360
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const commitMessage = $json.body.commits[0].message;\nconst fullRef = $json.body.ref;\nconst pushBranch = fullRef.startsWith('refs/heads/') ? fullRef.slice('refs/heads/'.length) : fullRef;\n\n// Updated regex to make the [...] part optional\nconst regex = /^([A-Z]+-\\d+)\\s(.*?)(?:\\s\\[(.*)\\])?$/;\nconst match = commitMessage.match(regex);\n\nif (!match) {\n  throw new Error(\"Commit message format is incorrect. Missing task key or message.\");\n}\n\nconst jiraKey = match[1];\nconst commitDescription = match[2].trim();\nconst flagString = match[3];\n\nconst flags = flagString ? flagString.split(',').map(s => s.trim()) : [];\n\nconst baseBranch = flags.find(f => !['auto-pr', 'taskcompleted'].includes(f));\nconst autoPR = flags.includes('auto-pr');\nconst taskCompleted = flags.includes('taskcompleted');\n\n// Validation rules\nif (autoPR && !baseBranch) {\n  throw new Error(\"Commit message error: Please enter a base branch to create the PR in.\");\n}\n\nreturn {\n  json: {\n    jiraKey,\n    commitDescription,\n    commands: flags,\n    baseBranch,\n    autoPR,\n    taskCompleted,\n    pushBranch\n  }\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "40c7ec38-ce05-4cf0-b685-764fb1e3e8f8",
      "name": "Check for PR commands",
      "type": "n8n-nodes-base.if",
      "position": [
        -1500,
        1360
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "0837a6e7-03a7-4a80-b263-4e75a4cc3efb",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.autoPR.toString() }}",
              "rightValue": "true"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "dde2e24e-2ade-4422-90e5-4d340551797f",
      "name": "Request to create PR",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        920,
        680
      ],
      "parameters": {
        "url": "=https://api.github.com/repos/{{ $('Webhook').item.json.body.repository.owner.name }}/{{ $('Webhook').item.json.body.repository.name }}/pulls",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"title\": \"{{$('Commit Message Breakdown').item.json.jiraKey}} {{$('Commit Message Breakdown').item.json.commitDescription}}\",\n  \"head\": \"{{$('Commit Message Breakdown').item.json.pushBranch}}\",\n  \"base\": \"{{$('Commit Message Breakdown').item.json.baseBranch}}\",\n  \"body\": \"Auto Generated PR for Jira Task {{$('Commit Message Breakdown').item.json.jiraKey}}\"\n}\n",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "githubApi"
      },
      "typeVersion": 4.2
    },
    {
      "id": "b5066bae-dfa3-45ab-9858-37bb5461de7e",
      "name": "Invalid commit message",
      "type": "n8n-nodes-base.stopAndError",
      "position": [
        -860,
        2500
      ],
      "parameters": {
        "errorMessage": "Workflow stopped due to invalid commit message or no commands provided"
      },
      "typeVersion": 1
    },
    {
      "id": "ce18dcbc-9708-44a1-8b21-2230bfc6478f",
      "name": "JIRA Task does not exist",
      "type": "n8n-nodes-base.stopAndError",
      "position": [
        1400,
        1280
      ],
      "parameters": {
        "errorMessage": "Workflow stopped due to invalid task or no taskcompleted command"
      },
      "typeVersion": 1
    },
    {
      "id": "d2779f44-67c3-419e-8957-4963360f6071",
      "name": "Check for task completed command",
      "type": "n8n-nodes-base.if",
      "position": [
        -1140,
        1840
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "3945b951-fc98-45b2-8194-9b712cc15705",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.taskCompleted.toString() }}",
              "rightValue": "true"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c21c433f-1b97-485d-8936-79f9b884cd28",
      "name": "Get task details for PR",
      "type": "n8n-nodes-base.jira",
      "position": [
        -1140,
        700
      ],
      "parameters": {
        "issueKey": "={{ $('Check for PR commands').item.json.jiraKey }}",
        "operation": "get",
        "additionalFields": {}
      },
      "typeVersion": 1,
      "alwaysOutputData": false
    },
    {
      "id": "87aa1a73-12bb-4cf7-bf83-b2a552c41b71",
      "name": "Get Task Details without PR.",
      "type": "n8n-nodes-base.jira",
      "position": [
        -420,
        2020
      ],
      "parameters": {
        "issueKey": "={{ $json.jiraKey }}",
        "operation": "get",
        "additionalFields": {}
      },
      "typeVersion": 1
    },
    {
      "id": "43311650-47f2-4166-b916-2f956605504a",
      "name": "Check if task exist",
      "type": "n8n-nodes-base.if",
      "position": [
        1540,
        540
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "3bda73c5-47f6-4605-b9db-17e74ccc2bcb",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{$('Get task details for PR').item.json.id}}",
              "rightValue": ""
            },
            {
              "id": "77d6fa4e-a7c2-4f66-810a-5566a1d78501",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Commit Message Breakdown').item.json.taskCompleted.toString() }}",
              "rightValue": "true"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "07939a6f-184b-4552-9b9b-2e64a7547a40",
      "name": "Update task status after PR",
      "type": "n8n-nodes-base.jira",
      "position": [
        2120,
        880
      ],
      "parameters": {
        "issueKey": "={{ $('Get task details for PR').item.json.key}}",
        "operation": "update",
        "updateFields": {
          "statusId": {
            "__rl": true,
            "mode": "list",
            "value": "61",
            "cachedResultName": "Development Done"
          }
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f3dd4a57-565a-461b-bf87-2a4f33da045f",
      "name": "Check whether a PR already exists",
      "type": "n8n-nodes-base.if",
      "position": [
        660,
        420
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b63c7d9a-7f1d-497b-838b-f617bcab9457",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.prExists.toString()}}",
              "rightValue": "true"
            }
          ]
        }
      },
      "typeVersion": 2.2,
      "alwaysOutputData": false
    },
    {
      "id": "8a138396-1513-4542-bd88-9d24d99caf51",
      "name": "Update the task status without PR",
      "type": "n8n-nodes-base.jira",
      "position": [
        1220,
        2140
      ],
      "parameters": {
        "issueKey": "={{ $json.key }}",
        "operation": "update",
        "updateFields": {
          "statusId": {
            "__rl": true,
            "mode": "list",
            "value": "61",
            "cachedResultName": "Development Done"
          }
        }
      },
      "typeVersion": 1
    },
    {
      "id": "98cf28cc-9ac3-4109-bfc6-1e8c1e2a48ee",
      "name": "Check if PR exists",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -400,
        420
      ],
      "parameters": {
        "url": "=https://api.github.com/repos/{{ $('Webhook').item.json.body.repository.owner.name }}/{{ $('Webhook').item.json.body.repository.name }}/pulls?head={{ $('Webhook').item.json.body.repository.owner.name }}:{{ $('Commit Message Breakdown').item.json.pushBranch }}",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "githubApi"
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "7a6ead0b-7975-4695-94b8-208620dd3402",
      "name": "Check if task exists",
      "type": "n8n-nodes-base.if",
      "position": [
        100,
        2140
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "26d8ff5a-c830-4443-8acb-16fd095aead5",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            },
            {
              "id": "315fd79c-263b-448d-ae26-bd2b448e5212",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Commit Message Breakdown').item.json.taskCompleted.toString() }}",
              "rightValue": "true"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0295041e-7f62-42af-bdc7-9e0d8a920053",
      "name": "코드",
      "type": "n8n-nodes-base.code",
      "position": [
        140,
        300
      ],
      "parameters": {
        "jsCode": "const inputItems = $input.all();\n\nif (\n  inputItems.length === 0 || \n  !inputItems[0].json || \n  Object.keys(inputItems[0].json).length === 0\n) {\n  // PR doesn't exist, return original data + prExists = false\n  return [\n    {\n      json: {\n        ...($input.first()?.json || {}),\n        prExists: false\n      }\n    }\n  ];\n} else {\n  // PR exists, return existing PR data + prExists = true\n  return inputItems.map(item => ({\n    json: {\n      ...item.json,\n      prExists: true\n    }\n  }));\n}\n"
      },
      "typeVersion": 2
    },
    {
      "id": "c38d3be6-25bc-4373-8b9c-50644ebfb387",
      "name": "병합",
      "type": "n8n-nodes-base.merge",
      "position": [
        260,
        720
      ],
      "parameters": {
        "mode": "chooseBranch"
      },
      "typeVersion": 3.2
    },
    {
      "id": "866cd55e-0b51-4451-b5a2-bd6420d6f686",
      "name": "Webhook 트리거",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -2940,
        1380
      ],
      "webhookId": "{YOUR_GITHUB_WEBHOOK_ID}",
      "parameters": {
        "path": "github-push",
        "options": {
          "rawBody": true
        },
        "httpMethod": "POST"
      },
      "typeVersion": 2
    },
    {
      "id": "2c37d886-5822-4c87-a2bb-e68c84a07e3f",
      "name": "Send message in slack with PR",
      "type": "n8n-nodes-base.slack",
      "position": [
        2780,
        700
      ],
      "webhookId": "{YOUR_SLACK_WEBHOOK_ID}",
      "parameters": {
        "text": "=PR has been created for the repository '{{ $('Webhook').item.json.body.repository.name }}' and task status of the task {{ $('Get task details for PR').item.json.key }} has been changed to development done\n\n",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0994RB3VAR",
          "cachedResultName": "{YOUR_SLACK_CHANNEL_NAME}"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.3
    },
    {
      "id": "0df5af64-7250-4cfb-b050-91440a90efcf",
      "name": "Send message in slack without PR",
      "type": "n8n-nodes-base.slack",
      "position": [
        2020,
        1800
      ],
      "webhookId": "{YOUR_SLACK_WEBHOOK_ID}",
      "parameters": {
        "text": "=Task status of the task {{ $('Get Task Details without PR.').item.json.key }} has been changed to development done",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0994RB3VAR",
          "cachedResultName": "{YOUR_SLACK_CHANNEL_NAME}"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.3
    },
    {
      "id": "c4615c8a-9d1e-4ab1-acce-cbbfc3857f54",
      "name": "Append a block in notion with PR",
      "type": "n8n-nodes-base.notion",
      "position": [
        2780,
        1140
      ],
      "parameters": {
        "blockId": {
          "__rl": true,
          "mode": "url",
          "value": "https://www.notion.so/{YOUR_NOTION_PAGE_ID}"
        },
        "blockUi": {
          "blockValues": [
            {
              "textContent": "=PR has been created from the repository {{ $('Webhook').item.json.body.repository.name }} and task status for the task{{ $('Get task details for PR').item.json.fields.parent.key }}  has been updated to Development Done\n"
            }
          ]
        },
        "resource": "block"
      },
      "typeVersion": 2.2
    },
    {
      "id": "2f8f6c68-2a63-4a20-8771-9b616b1e37b9",
      "name": "Append a block in notion without PR",
      "type": "n8n-nodes-base.notion",
      "position": [
        2040,
        2360
      ],
      "parameters": {
        "blockId": {
          "__rl": true,
          "mode": "url",
          "value": "https://www.notion.so/{YOUR_NOTION_PAGE_ID}"
        },
        "blockUi": {
          "blockValues": [
            {
              "textContent": "=Task status for the task {{ $('Get Task Details without PR.').item.json.key }} has been updated to Development Done"
            }
          ]
        },
        "resource": "block"
      },
      "typeVersion": 2.2
    },
    {
      "id": "0acdb107-372c-46ae-8be1-1dfca5c03f08",
      "name": "메모1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2800,
        400
      ],
      "parameters": {
        "color": 4,
        "width": 680,
        "height": 280,
        "content": "## 🔧 Quick Setup Required!\n\nWelcome! To make this workflow yours, you just need to do two things:\n\n1.  **Connect Your Accounts:** Click on the GitHub and Jira nodes and select your credentials. Also, add the slack and notion credentials to ensure smooth message delivery\n\n2.  **Add Webhooks to the required repositories:** Add the production webhook link to the concerned repositories\n \n\n\nThat's it! You're ready to automate."
      },
      "typeVersion": 1
    },
    {
      "id": "00004e99-bfa8-41ba-bff6-0e9b0a882c4c",
      "name": "메모",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3160,
        1040
      ],
      "parameters": {
        "color": 6,
        "width": 540,
        "height": 320,
        "content": "### Step 1: Webhook Activated! 🪝\n\nThis is the entry point of the workflow.\n\nIt acts as a **listener for GitHub push events**, tapping into your repositories to catch every new commit.\n\nHere’s what it does:\n\n- 📦 Listens for `push` requests on specific branches.\n- 🚦 Triggers the workflow only when new commits hit the repo.\n- 🎯 Ensures everything starts from the moment you push code.\n\nIt’s the spark that kicks off the automation engine. 🔧⚡\n"
      },
      "typeVersion": 1
    },
    {
      "id": "ee39ccc2-c7d8-4783-bc79-b7710dda0cb8",
      "name": "메모2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2460,
        1520
      ],
      "parameters": {
        "width": 560,
        "height": 280,
        "content": "### Step 2: The Decoder Ring 🧠\n\nThis is where the magic happens! Think of this node as a translator.\n\nIt carefully reads the commit message you wrote (e.g., \"FF-1196...[auto-pr]...\") and intelligently pulls out the three key pieces of information we need:\n\n1.  **Who:** The Jira ticket number.\n\n2.  **What:** The special commands (`[auto-pr]`, `[taskcompleted]`).\n\n3.  **Where:** The target branch for the PR."
      },
      "typeVersion": 1
    },
    {
      "id": "5abbabd7-f911-4905-a810-fb473cceb6f8",
      "name": "메모3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1820,
        1040
      ],
      "parameters": {
        "color": 6,
        "width": 480,
        "height": 300,
        "content": "### Step 3: To PR, or Not to PR? 🤔\n\nThis is a checkpoint that gives you control.\n\nIt asks a simple question: \"Did the developer include the `[auto-pr]` command?\"\n\n- If **YES**, we proceed down the \"True\" path to create the Pull Request automatically. No more manual form-filling in GitHub!\n\n- If **NO**, we skip it. This lets you push multiple work-in-progress commits without flooding your team with PRs."
      },
      "typeVersion": 1
    },
    {
      "id": "f5b6e4b5-130f-4ebc-8e76-d968642404c1",
      "name": "메모4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1300,
        380
      ],
      "parameters": {
        "color": 4,
        "width": 400,
        "height": 260,
        "content": "### Step 4: Task Intel Incoming! 🕵️‍♂️\n\nThis node is your mission control for task details.\n\nIt takes the **Jira ticket number** extracted in Step 2 and dives into your project management system to fetch all the juicy details—like the task title, status, assignee, and more.\n\nIn short: it’s the bridge between your code and your backlog. 🧩\n"
      },
      "typeVersion": 1
    },
    {
      "id": "8994f439-0876-4a7f-97b6-00a7df59ecfe",
      "name": "메모5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -540,
        100
      ],
      "parameters": {
        "color": 3,
        "width": 420,
        "height": 280,
        "content": "### Step 5: PR Radar Activated! 📡\n\nThis node is on patrol to prevent duplicates.\n\nIt scans the repository to check if a **Pull Request already exists** from the current branch. Why? Because creating multiple PRs for the same work = chaos. 🧨\n\n- If a PR already exists, we skip creating a new one.\n- If no PR is found, we move ahead to create it.\n\nSimple, smart, and keeps your GitHub tidy. 🧼\n"
      },
      "typeVersion": 1
    },
    {
      "id": "2795b793-1389-4459-814e-29fed2455ef7",
      "name": "메모6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -60,
        -40
      ],
      "parameters": {
        "color": 6,
        "width": 580,
        "height": 300,
        "content": "### Step 6: PR Data Extractor 🧠📄\n\nThis node digs into GitHub to check if a **Pull Request already exists** for the current branch.\n\nHere’s what it does:\n\n- ✅ **If a PR exists**: It extracts and formats key details like PR title, description, status, URL, and number—ready to be used in the next steps.\n- ❌ **If no PR is found**: It returns `false`, signaling that a new PR may need to be created.\n\nThis step ensures we always work with clean, structured data—and avoid duplication. 📦🧹\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b087e06b-7ac1-4c31-9312-3fcd4828a2a6",
      "name": "메모7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        60,
        880
      ],
      "parameters": {
        "color": 3,
        "width": 520,
        "height": 360,
        "content": "### Step 7: PR Data Merge Hub 🔗🧩\n\nThis node acts as a smart **merge point** for Pull Request data.\n\nIt brings together inputs from:\n\n- 🧠 **Extracted PR details** (if a PR already exists).\n- ✅ **PR existence check** (whether or not a PR is found).\n\nWhat’s the result?\n\n- A single, unified dataset that combines both logic and content.\n- Downstream nodes can now operate on **consistent and complete PR info**, regardless of the path taken.\n\nThink of it as your data convergence checkpoint—clean, connected, and ready to go. 🔄🧷\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f91c2b1d-80a5-4563-9c00-37f8216985bb",
      "name": "메모8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        740,
        860
      ],
      "parameters": {
        "color": 4,
        "width": 480,
        "height": 300,
        "content": "### Step 8: Launch the PR! 🚀\n\nThis is the final move—the grand finale.\n\nIf everything checks out, this node **creates the Pull Request** automatically using the details we gathered earlier (task info, branch name, etc.).\n\nNo manual clicking. No copy-pasting. Just:\n\n- ✅ A clean PR title.\n- 📝 A brief and clean description\n\nIt’s automation magic at its finest. ✨"
      },
      "typeVersion": 1
    },
    {
      "id": "bdd25203-fe9c-434e-a4bd-967c3e3632a6",
      "name": "메모9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1940,
        460
      ],
      "parameters": {
        "color": 5,
        "width": 620,
        "height": 320,
        "content": "### Step 7: Status Update Sent! 📬\n\nTime to close the loop with Jira.\n\nThis node takes care of updating the **task status to “Development Done”** once the PR is successfully created.\n\nWhy does this matter?\n\n- ✅ Keeps your Jira board up to date automatically.\n- 📊 Gives your team instant visibility into progress.\n- 🔄 Ensures a smooth handoff to the next stage (like QA or Code Review).\n\nNo need to switch tabs—your workflow just updated itself. 🔁\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4a379c5e-bc5d-4ce5-818b-68aca73c45ce",
      "name": "메모10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1560,
        1160
      ],
      "parameters": {
        "color": 3,
        "width": 580,
        "height": 300,
        "content": "### Heads-Up Node: Something’s Missing! ⚠️\n\nThis node acts as a checkpoint when things don’t go as planned.\n\nIt checks two key conditions:\n\n1. ❌ The **Jira task** couldn’t be found based on the commit message.\n2. 🛑 The PR **does not include** the `[taskcompleted]` keyword.\n\nIf either is true, we **skip the task status update** to avoid pushing incomplete or incorrect changes to Jira.\n\nIt’s a safety net to keep your workflow clean and error-free. 🧯\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4040caf2-2b6d-4194-afc5-e1fa376b6c7a",
      "name": "메모11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2980,
        820
      ],
      "parameters": {
        "color": 4,
        "width": 640,
        "height": 300,
        "content": "### Step 8: Spread the Word! 📣\n\nTime to notify the crew.\n\nThese nodes send out alerts that a **Pull Request has been created** and the **Jira task status has been updated**—all in real-time.\n\nWhere does the message go?\n\n- 💬 **Slack** – Keeps your team in the loop instantly.\n- 🗂️ **Notion** – Logs the activity for async tracking and documentation.\n\nClear, consistent, and automatic communication. Your workflow just became a team player. 🤝\n"
      },
      "typeVersion": 1
    },
    {
      "id": "12c79a7b-edb9-4233-9fd4-33ff9efdf462",
      "name": "메모12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1040,
        2680
      ],
      "parameters": {
        "color": 3,
        "width": 540,
        "height": 320,
        "content": "### Halt! Invalid Commit Detected 🚫\n\nThis node is the gatekeeper for clean automation.\n\nIt checks if the commit message is **missing the required format or commands** (like `[auto-pr]`, `[taskcompleted]`, etc.).\n\nIf the message is invalid or empty:\n\n- 🛑 The workflow is **stopped immediately**.\n- 🔒 No PR is created.\n- ⚠️ No task is updated.\n\nThis ensures only intentional, well-formed commits trigger automation—keeping your pipeline smart and safe. 🧠✅\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b007ed13-aaef-4f7d-bea4-7ae2aa77a213",
      "name": "메모13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        1440
      ],
      "parameters": {
        "width": 480,
        "height": 340,
        "content": "### Step 4: Task Completion Check ✅❓\n\nThis node plays detective for the `[taskcompleted]` command.\n\nIt scans the commit message to see if you’ve marked the task as complete—by including the `[taskcompleted]` keyword.\n\nWhy is this important?\n\n- ✅ If present, we’ll proceed to update the Jira task status in later steps.\n- ❌ If missing, we assume the task isn’t done yet and **skip the status update**.\n\nIt’s a smart way to give **you control over when the task is marked complete**—all from the comfort of your commit message. 🧘‍♂️\n"
      },
      "typeVersion": 1
    },
    {
      "id": "38fa4c21-97e6-4cbb-bd56-01b22ab9dcaf",
      "name": "메모14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        1760
      ],
      "parameters": {
        "color": 6,
        "width": 500,
        "height": 320,
        "content": "### Step 5: Task Hunt Begins! 🔍\n\nThis node verifies whether the **Jira task actually exists**.\n\nUsing the ticket number extracted earlier, it queries Jira to confirm that the task is valid and accessible.\n\nHere’s what it does:\n\n- ✅ If the task exists, we move forward confidently.\n- ❌ If not, we stop here to avoid pushing changes to a non-existent or incorrect task.\n\nThink of it as a sanity check—because broken links to Jira help no one. 🧠🛑\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f9dc7b51-164b-493a-88f3-123e80fb4d1d",
      "name": "메모15",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        940,
        1800
      ],
      "parameters": {
        "color": 5,
        "width": 580,
        "height": 300,
        "content": "### Step 6: Silent Status Update 🤫✅\n\nThis node updates the **Jira task status to “Development Done”**, but skips the PR creation process.\n\nWhy would this happen?\n\n- The commit message includes `[taskcompleted]`, but **does not** include `[auto-pr]`.\n- You want to mark the task as finished **without creating a Pull Request**—for example, in cases of non-code or internal changes.\n\nIt’s a clean way to **signal task completion in Jira** while keeping your GitHub untouched. 🎯\n"
      },
      "typeVersion": 1
    },
    {
      "id": "39389ae3-505b-4c2d-8747-8d95bf22613b",
      "name": "메모16",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2200,
        2000
      ],
      "parameters": {
        "color": 4,
        "width": 560,
        "height": 260,
        "content": "### Step 7: Task Update Broadcast! 📢\n\nThis node handles communication after the Jira task status has been updated.\n\nIt sends out friendly alerts to keep everyone in the loop:\n\n- 💬 **Slack** – So your team knows the task has moved to “Development Done”.\n- 🗂️ **Notion** – For async tracking, visibility, and documentation.\n\nNo more “Did you finish this?” messages—your workflow answers for you. ✅🧘‍♀️\n"
      },
      "typeVersion": 1
    },
    {
      "id": "7fc5e9aa-2bfe-4bb8-b7e9-1c6c587769b3",
      "name": "메모17",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3780,
        180
      ],
      "parameters": {
        "color": 6,
        "width": 900,
        "height": 700,
        "content": "\n\n### ✍️ Commit Message Command Guide\n\nYour `git commit` message is the remote control for this automation. Use the format below to trigger specific actions.\n\n**Base Format:**\n`TICKET-ID Your descriptive message [command1,command2,base-branch]`\n\n---\n\n| Commit Message Example | Commands Used | Automation Triggered |\n| :--- | :--- | :--- |\n\n| **`DEV-123 Fix login bug [auto-pr, taskcompleted, develop]`** | `[auto-pr]`<br>`[taskcompleted]`<br>`develop` | **🚀 Full Automation:**<br>1. Creates a Pull Request to the `develop` branch.<br>2. Updates Jira task `DEV-123` to \"Done\".<br>3. Sends notifications about both actions. |\n\n| **`DEV-456 WIP on new UI [auto-pr, main]`** | `[auto-pr]`<br>`main` | **⚙️ PR Creation Only:**<br>1. Creates a Pull Request to the `main` branch.<br>2. Jira task status is **not changed**. |\n\n| **`DEV-789 Final docs added [taskcompleted]`** | `[taskcompleted]` | **✅ Jira Update Only:**<br>1. **No Pull Request** is created.<br>2. Updates Jira task `DEV-789` to \"Done\".<br>3. Sends notifications about the task update. |\n\n| **`DEV-111 Minor typo fix`** | *None* | **🚫 No Automation:**<br>The commit is pushed, but the workflow does nothing. This is for standard commits that don't need automation. |\n\n| **`DEV-222 This will fail [auto-pr]`** | `[auto-pr]` | **⚠️ Error - Workflow Stops:**<br>The workflow's validation will catch that `[auto-pr]` was used without a target branch and will stop, preventing an error. |"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "fa5c1a3b-1869-42e8-a94f-1ac9e5d52b5b",
  "connections": {
    "Code": {
      "main": [
        [
          {
            "node": "f3dd4a57-565a-461b-bf87-2a4f33da045f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "dde2e24e-2ade-4422-90e5-4d340551797f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "2dff9822-74ef-47b9-8eda-db563f4718d9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "98cf28cc-9ac3-4109-bfc6-1e8c1e2a48ee": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "43311650-47f2-4166-b916-2f956605504a": {
      "main": [
        [
          {
            "node": "07939a6f-184b-4552-9b9b-2e64a7547a40",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ce18dcbc-9708-44a1-8b21-2230bfc6478f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7a6ead0b-7975-4695-94b8-208620dd3402": {
      "main": [
        [
          {
            "node": "8a138396-1513-4542-bd88-9d24d99caf51",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ce18dcbc-9708-44a1-8b21-2230bfc6478f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "dde2e24e-2ade-4422-90e5-4d340551797f": {
      "main": [
        [
          {
            "node": "43311650-47f2-4166-b916-2f956605504a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "40c7ec38-ce05-4cf0-b685-764fb1e3e8f8": {
      "main": [
        [
          {
            "node": "c21c433f-1b97-485d-8936-79f9b884cd28",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "d2779f44-67c3-419e-8957-4963360f6071",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c21c433f-1b97-485d-8936-79f9b884cd28": {
      "main": [
        [
          {
            "node": "98cf28cc-9ac3-4109-bfc6-1e8c1e2a48ee",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2dff9822-74ef-47b9-8eda-db563f4718d9": {
      "main": [
        [
          {
            "node": "40c7ec38-ce05-4cf0-b685-764fb1e3e8f8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "07939a6f-184b-4552-9b9b-2e64a7547a40": {
      "main": [
        [
          {
            "node": "2c37d886-5822-4c87-a2bb-e68c84a07e3f",
            "type": "main",
            "index": 0
          },
          {
            "node": "c4615c8a-9d1e-4ab1-acce-cbbfc3857f54",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "87aa1a73-12bb-4cf7-bf83-b2a552c41b71": {
      "main": [
        [
          {
            "node": "7a6ead0b-7975-4695-94b8-208620dd3402",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d2779f44-67c3-419e-8957-4963360f6071": {
      "main": [
        [
          {
            "node": "87aa1a73-12bb-4cf7-bf83-b2a552c41b71",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "b5066bae-dfa3-45ab-9858-37bb5461de7e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "f3dd4a57-565a-461b-bf87-2a4f33da045f": {
      "main": [
        [
          {
            "node": "43311650-47f2-4166-b916-2f956605504a",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8a138396-1513-4542-bd88-9d24d99caf51": {
      "main": [
        [
          {
            "node": "0df5af64-7250-4cfb-b050-91440a90efcf",
            "type": "main",
            "index": 0
          },
          {
            "node": "2f8f6c68-2a63-4a20-8771-9b616b1e37b9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

고급

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
고급
노드 수39
카테고리-
노드 유형10
난이도 설명

고급 사용자를 위한 16+개 노드의 복잡한 워크플로우

저자
Intuz

Intuz

@intuz

Workflow automation can help automate your routine activities and help saves $$$, as well as hours of time. As a boutique tech consulting company, Intuz help businesses with custom AI/ML, AI Workflow Automations, and software development. Automate your business workflow for: Sales Marketing Accounting Finance Operations E-Commerce Customer Support Admin & Backoffice Logistics & Supply Chain

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34