This workflow corresponds to n8n.io template #7048 — we link there as the canonical source.
This workflow follows the HTTP Request → Notion recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "XrACI58wgVlnNv1M",
"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": "Code",
"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": "Merge",
"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
],
"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
],
"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
],
"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": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2800,
400
],
"parameters": {
"color": 4,
"width": 680,
"height": 280,
"content": "## \ud83d\udd27 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": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3160,
1040
],
"parameters": {
"color": 6,
"width": 540,
"height": 320,
"content": "### Step 1: Webhook Activated! \ud83e\ude9d\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\u2019s what it does:\n\n- \ud83d\udce6 Listens for `push` requests on specific branches.\n- \ud83d\udea6 Triggers the workflow only when new commits hit the repo.\n- \ud83c\udfaf Ensures everything starts from the moment you push code.\n\nIt\u2019s the spark that kicks off the automation engine. \ud83d\udd27\u26a1\n"
},
"typeVersion": 1
},
{
"id": "ee39ccc2-c7d8-4783-bc79-b7710dda0cb8",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2460,
1520
],
"parameters": {
"width": 560,
"height": 280,
"content": "### Step 2: The Decoder Ring \ud83e\udde0\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": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1820,
1040
],
"parameters": {
"color": 6,
"width": 480,
"height": 300,
"content": "### Step 3: To PR, or Not to PR? \ud83e\udd14\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": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1300,
380
],
"parameters": {
"color": 4,
"width": 400,
"height": 260,
"content": "### Step 4: Task Intel Incoming! \ud83d\udd75\ufe0f\u200d\u2642\ufe0f\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\u2014like the task title, status, assignee, and more.\n\nIn short: it\u2019s the bridge between your code and your backlog. \ud83e\udde9\n"
},
"typeVersion": 1
},
{
"id": "8994f439-0876-4a7f-97b6-00a7df59ecfe",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-540,
100
],
"parameters": {
"color": 3,
"width": 420,
"height": 280,
"content": "### Step 5: PR Radar Activated! \ud83d\udce1\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. \ud83e\udde8\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. \ud83e\uddfc\n"
},
"typeVersion": 1
},
{
"id": "2795b793-1389-4459-814e-29fed2455ef7",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-60,
-40
],
"parameters": {
"color": 6,
"width": 580,
"height": 300,
"content": "### Step 6: PR Data Extractor \ud83e\udde0\ud83d\udcc4\n\nThis node digs into GitHub to check if a **Pull Request already exists** for the current branch.\n\nHere\u2019s what it does:\n\n- \u2705 **If a PR exists**: It extracts and formats key details like PR title, description, status, URL, and number\u2014ready to be used in the next steps.\n- \u274c **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\u2014and avoid duplication. \ud83d\udce6\ud83e\uddf9\n"
},
"typeVersion": 1
},
{
"id": "b087e06b-7ac1-4c31-9312-3fcd4828a2a6",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
60,
880
],
"parameters": {
"color": 3,
"width": 520,
"height": 360,
"content": "### Step 7: PR Data Merge Hub \ud83d\udd17\ud83e\udde9\n\nThis node acts as a smart **merge point** for Pull Request data.\n\nIt brings together inputs from:\n\n- \ud83e\udde0 **Extracted PR details** (if a PR already exists).\n- \u2705 **PR existence check** (whether or not a PR is found).\n\nWhat\u2019s 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\u2014clean, connected, and ready to go. \ud83d\udd04\ud83e\uddf7\n"
},
"typeVersion": 1
},
{
"id": "f91c2b1d-80a5-4563-9c00-37f8216985bb",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
740,
860
],
"parameters": {
"color": 4,
"width": 480,
"height": 300,
"content": "### Step 8: Launch the PR! \ud83d\ude80\n\nThis is the final move\u2014the 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- \u2705 A clean PR title.\n- \ud83d\udcdd A brief and clean description\n\nIt\u2019s automation magic at its finest. \u2728"
},
"typeVersion": 1
},
{
"id": "bdd25203-fe9c-434e-a4bd-967c3e3632a6",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
1940,
460
],
"parameters": {
"color": 5,
"width": 620,
"height": 320,
"content": "### Step 7: Status Update Sent! \ud83d\udcec\n\nTime to close the loop with Jira.\n\nThis node takes care of updating the **task status to \u201cDevelopment Done\u201d** once the PR is successfully created.\n\nWhy does this matter?\n\n- \u2705 Keeps your Jira board up to date automatically.\n- \ud83d\udcca Gives your team instant visibility into progress.\n- \ud83d\udd04 Ensures a smooth handoff to the next stage (like QA or Code Review).\n\nNo need to switch tabs\u2014your workflow just updated itself. \ud83d\udd01\n"
},
"typeVersion": 1
},
{
"id": "4a379c5e-bc5d-4ce5-818b-68aca73c45ce",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
1560,
1160
],
"parameters": {
"color": 3,
"width": 580,
"height": 300,
"content": "### Heads-Up Node: Something\u2019s Missing! \u26a0\ufe0f\n\nThis node acts as a checkpoint when things don\u2019t go as planned.\n\nIt checks two key conditions:\n\n1. \u274c The **Jira task** couldn\u2019t be found based on the commit message.\n2. \ud83d\uded1 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\u2019s a safety net to keep your workflow clean and error-free. \ud83e\uddef\n"
},
"typeVersion": 1
},
{
"id": "4040caf2-2b6d-4194-afc5-e1fa376b6c7a",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
2980,
820
],
"parameters": {
"color": 4,
"width": 640,
"height": 300,
"content": "### Step 8: Spread the Word! \ud83d\udce3\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**\u2014all in real-time.\n\nWhere does the message go?\n\n- \ud83d\udcac **Slack** \u2013 Keeps your team in the loop instantly.\n- \ud83d\uddc2\ufe0f **Notion** \u2013 Logs the activity for async tracking and documentation.\n\nClear, consistent, and automatic communication. Your workflow just became a team player. \ud83e\udd1d\n"
},
"typeVersion": 1
},
{
"id": "12c79a7b-edb9-4233-9fd4-33ff9efdf462",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1040,
2680
],
"parameters": {
"color": 3,
"width": 540,
"height": 320,
"content": "### Halt! Invalid Commit Detected \ud83d\udeab\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- \ud83d\uded1 The workflow is **stopped immediately**.\n- \ud83d\udd12 No PR is created.\n- \u26a0\ufe0f No task is updated.\n\nThis ensures only intentional, well-formed commits trigger automation\u2014keeping your pipeline smart and safe. \ud83e\udde0\u2705\n"
},
"typeVersion": 1
},
{
"id": "b007ed13-aaef-4f7d-bea4-7ae2aa77a213",
"name": "Sticky Note13",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1200,
1440
],
"parameters": {
"width": 480,
"height": 340,
"content": "### Step 4: Task Completion Check \u2705\u2753\n\nThis node plays detective for the `[taskcompleted]` command.\n\nIt scans the commit message to see if you\u2019ve marked the task as complete\u2014by including the `[taskcompleted]` keyword.\n\nWhy is this important?\n\n- \u2705 If present, we\u2019ll proceed to update the Jira task status in later steps.\n- \u274c If missing, we assume the task isn\u2019t done yet and **skip the status update**.\n\nIt\u2019s a smart way to give **you control over when the task is marked complete**\u2014all from the comfort of your commit message. \ud83e\uddd8\u200d\u2642\ufe0f\n"
},
"typeVersion": 1
},
{
"id": "38fa4c21-97e6-4cbb-bd56-01b22ab9dcaf",
"name": "Sticky Note14",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
1760
],
"parameters": {
"color": 6,
"width": 500,
"height": 320,
"content": "### Step 5: Task Hunt Begins! \ud83d\udd0d\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\u2019s what it does:\n\n- \u2705 If the task exists, we move forward confidently.\n- \u274c If not, we stop here to avoid pushing changes to a non-existent or incorrect task.\n\nThink of it as a sanity check\u2014because broken links to Jira help no one. \ud83e\udde0\ud83d\uded1\n"
},
"typeVersion": 1
},
{
"id": "f9dc7b51-164b-493a-88f3-123e80fb4d1d",
"name": "Sticky Note15",
"type": "n8n-nodes-base.stickyNote",
"position": [
940,
1800
],
"parameters": {
"color": 5,
"width": 580,
"height": 300,
"content": "### Step 6: Silent Status Update \ud83e\udd2b\u2705\n\nThis node updates the **Jira task status to \u201cDevelopment Done\u201d**, 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**\u2014for example, in cases of non-code or internal changes.\n\nIt\u2019s a clean way to **signal task completion in Jira** while keeping your GitHub untouched. \ud83c\udfaf\n"
},
"typeVersion": 1
},
{
"id": "39389ae3-505b-4c2d-8747-8d95bf22613b",
"name": "Sticky Note16",
"type": "n8n-nodes-base.stickyNote",
"position": [
2200,
2000
],
"parameters": {
"color": 4,
"width": 560,
"height": 260,
"content": "### Step 7: Task Update Broadcast! \ud83d\udce2\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- \ud83d\udcac **Slack** \u2013 So your team knows the task has moved to \u201cDevelopment Done\u201d.\n- \ud83d\uddc2\ufe0f **Notion** \u2013 For async tracking, visibility, and documentation.\n\nNo more \u201cDid you finish this?\u201d messages\u2014your workflow answers for you. \u2705\ud83e\uddd8\u200d\u2640\ufe0f\n"
},
"typeVersion": 1
},
{
"id": "7fc5e9aa-2bfe-4bb8-b7e9-1c6c587769b3",
"name": "Sticky Note17",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3780,
180
],
"parameters": {
"color": 6,
"width": 900,
"height": 700,
"content": "\n\n### \u270d\ufe0f 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` | **\ud83d\ude80 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` | **\u2699\ufe0f 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]` | **\u2705 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* | **\ud83d\udeab 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]` | **\u26a0\ufe0f 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,
"settings": {
"executionOrder": "v1"
},
"versionId": "fa5c1a3b-1869-42e8-a94f-1ac9e5d52b5b",
"connections": {
"Code": {
"main": [
[
{
"node": "Check whether a PR already exists",
"type": "main",
"index": 0
}
]
]
},
"Merge": {
"main": [
[
{
"node": "Request to create PR",
"type": "main",
"index": 0
}
]
]
},
"Webhook": {
"main": [
[
{
"node": "Commit Message Breakdown",
"type": "main",
"index": 0
}
]
]
},
"Check if PR exists": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
},
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Check if task exist": {
"main": [
[
{
"node": "Update task status after PR",
"type": "main",
"index": 0
}
],
[
{
"node": "JIRA Task does not exist",
"type": "main",
"index": 0
}
]
]
},
"Check if task exists": {
"main": [
[
{
"node": "Update the task status without PR",
"type": "main",
"index": 0
}
],
[
{
"node": "JIRA Task does not exist",
"type": "main",
"index": 0
}
]
]
},
"Request to create PR": {
"main": [
[
{
"node": "Check if task exist",
"type": "main",
"index": 0
}
]
]
},
"Check for PR commands": {
"main": [
[
{
"node": "Get task details for PR",
"type": "main",
"index": 0
}
],
[
{
"node": "Check for task completed command",
"type": "main",
"index": 0
}
]
]
},
"Get task details for PR": {
"main": [
[
{
"node": "Check if PR exists",
"type": "main",
"index": 0
}
]
]
},
"Commit Message Breakdown": {
"main": [
[
{
"node": "Check for PR commands",
"type": "main",
"index": 0
}
]
]
},
"Update task status after PR": {
"main": [
[
{
"node": "Send message in slack with PR",
"type": "main",
"index": 0
},
{
"node": "Append a block in notion with PR",
"type": "main",
"index": 0
}
]
]
},
"Get Task Details without PR.": {
"main": [
[
{
"node": "Check if task exists",
"type": "main",
"index": 0
}
]
]
},
"Check for task completed command": {
"main": [
[
{
"node": "Get Task Details without PR.",
"type": "main",
"index": 0
}
],
[
{
"node": "Invalid commit message",
"type": "main",
"index": 0
}
]
]
},
"Check whether a PR already exists": {
"main": [
[
{
"node": "Check if task exist",
"type": "main",
"index": 0
}
],
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Update the task status without PR": {
"main": [
[
{
"node": "Send message in slack without PR",
"type": "main",
"index": 0
},
{
"node": "Append a block in notion without PR",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Are you tired of the repetitive dance between git push, creating a pull request in GitHub, updating the corresponding task in JIRA, and then manually notifying your team in Slack, or Notion?
Source: https://n8n.io/workflows/7048/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow is an AI-assisted clean plate and object removal pipeline built for modern VFX production environments. It transforms a single plate image and removal brief into multiple high-quality cl
This n8n template from Intuz provides a complete and automated solution for preparing and delivering context-rich briefings directly to attendees before every meeting.
This workflow is an AI-driven FX concept generation pipeline that transforms a single VFX brief into multiple high-quality simulation-ready video concepts. It automates ideation, rendering, storage, a
This workflow is an AI-powered style look transfer and quality control pipeline designed for VFX and editorial production. It transforms a new shot brief and a hero reference image into multiple style
HR teams, IT Operations, and System Administrators managing employee onboarding at scale. It’s perfect if you use Odoo 18 to trigger account requests and need Redmine + GitLab accounts created instant