Créer automatiquement des Pull Requests GitHub et mettre à jour Jira à partir de Git commit (multi-dépôts)

Avancé

Ceci est uncontenant 39 nœuds.Utilise principalement des nœuds comme If, Code, Jira, Merge, Slack. Créer automatiquement une PR GitHub à partir des commandes Git et mettre à jour Jira (multi-dépôts)

Prérequis
  • Token Bot Slack ou URL Webhook
  • Clé API Notion
  • Point de terminaison HTTP Webhook (généré automatiquement par n8n)
  • Peut nécessiter les informations d'identification d'authentification de l'API cible

Catégorie

-
Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "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": "Analyse du message de commit",
      "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": "Vérification des commandes de PR",
      "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": "Demande de création de 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": "Message de commit invalide",
      "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": "La tâche JIRA n'existe pas",
      "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": "Vérification de la commande de tâche terminée",
      "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": "Obtenir les détails de la tâche pour la 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": "Obtenir les détails de la tâche sans 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": "Vérifier si la tâche existe",
      "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": "Mettre à jour le statut de la tâche après 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": "Vérifier si une PR existe déjà",
      "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": "Mettre à jour le statut de la tâche sans 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": "Vérifier si la PR existe",
      "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": "Vérifier si la tâche existe",
      "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
      ],
      "webhookId": "{YOUR_GITHUB_WEBHOOK_ID}",
      "parameters": {
        "path": "github-push",
        "options": {
          "rawBody": true
        },
        "httpMethod": "POST"
      },
      "typeVersion": 2
    },
    {
      "id": "2c37d886-5822-4c87-a2bb-e68c84a07e3f",
      "name": "Envoyer un message dans slack avec 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": "Envoyer un message dans slack sans 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": "Ajouter un bloc dans notion avec 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": "Ajouter un bloc dans notion sans 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": "Note adhésive1",
      "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": "Note adhésive",
      "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": "Note adhésive2",
      "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": "Note adhésive3",
      "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": "Note adhésive4",
      "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": "Note adhésive5",
      "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": "Note adhésive6",
      "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": "Note adhésive7",
      "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": "Note adhésive8",
      "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": "Note adhésive9",
      "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": "Note adhésive10",
      "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": "Note adhésive11",
      "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": "Note adhésive12",
      "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": "Note adhésive13",
      "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": "Note adhésive14",
      "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": "Note adhésive15",
      "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": "Note adhésive16",
      "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": "Note adhésive17",
      "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": {
    "0295041e-7f62-42af-bdc7-9e0d8a920053": {
      "main": [
        [
          {
            "node": "f3dd4a57-565a-461b-bf87-2a4f33da045f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c38d3be6-25bc-4373-8b9c-50644ebfb387": {
      "main": [
        [
          {
            "node": "dde2e24e-2ade-4422-90e5-4d340551797f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "866cd55e-0b51-4451-b5a2-bd6420d6f686": {
      "main": [
        [
          {
            "node": "2dff9822-74ef-47b9-8eda-db563f4718d9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "98cf28cc-9ac3-4109-bfc6-1e8c1e2a48ee": {
      "main": [
        [
          {
            "node": "0295041e-7f62-42af-bdc7-9e0d8a920053",
            "type": "main",
            "index": 0
          },
          {
            "node": "c38d3be6-25bc-4373-8b9c-50644ebfb387",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "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": "7a6ead0b-7975-4695-94b8-208620dd3402",
            "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": "7a6ead0b-7975-4695-94b8-208620dd3402",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "c38d3be6-25bc-4373-8b9c-50644ebfb387",
            "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
          }
        ]
      ]
    }
  }
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Avancé

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Informations sur le workflow
Niveau de difficulté
Avancé
Nombre de nœuds39
Catégorie-
Types de nœuds10
Description de la difficulté

Adapté aux utilisateurs avancés, avec des workflows complexes contenant 16+ nœuds

Auteur
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

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34