{
  "id": "DhwPhvyAJzzDoAiq",
  "meta": {
    "templateId": "11728",
    "templateCredsSetupCompleted": true
  },
  "name": "Auto-resolve Jira tickets with GitHub Copilot using Port Context",
  "tags": [],
  "nodes": [
    {
      "id": "dc5b0535-793f-4ba7-b748-2798a3c4e22e",
      "name": "Is issue creation successful?",
      "type": "n8n-nodes-base.if",
      "position": [
        2080,
        544
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "ded3f45f-fd63-493a-a5fc-225004d5d292",
              "operator": {
                "type": "number",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.number }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "222058f6-cc6c-450a-8fbb-be3ed01c1f4a",
      "name": "Is ready for assignment?",
      "type": "n8n-nodes-base.if",
      "position": [
        1184,
        560
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8800068e-ddaa-4979-a589-6442f424bb09",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.webhookEvent == \"jira:issue_updated\" && $json.issue.fields.status.name == \"In Progress\" && $json.issue.fields.labels.includes(\"product_approved\") && !$json.issue.fields.labels.includes(\"copilot_assigned\") }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "03c29fb9-c747-4602-941e-a8f279cda515",
      "name": "Create a GitHub issue",
      "type": "n8n-nodes-base.github",
      "position": [
        1872,
        544
      ],
      "parameters": {
        "body": "={{ $json.result.message.parseJson().github_issue_body }}",
        "owner": {
          "__rl": true,
          "mode": "url",
          "value": "https://github.com/ORG"
        },
        "title": "={{ $json.result.message.parseJson().github_issue_title }}",
        "labels": [
          {
            "label": "n8n"
          },
          {
            "label": "ai-workflow"
          }
        ],
        "assignees": [],
        "repository": {
          "__rl": true,
          "mode": "list",
          "value": "aws-codeploy-demo"
        }
      },
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "bd136228-82c3-4342-9a39-1461bf59b170",
      "name": "Assign issue to Copilot",
      "type": "n8n-nodes-base.github",
      "position": [
        2288,
        544
      ],
      "parameters": {
        "body": "@copilot please take ownership of this issue and begin working on a solution.\n\nUse the information in the issue body and title to propose and implement the necessary code changes.\n",
        "owner": {
          "__rl": true,
          "mode": "url",
          "value": "https://github.com/ORG"
        },
        "operation": "createComment",
        "repository": {
          "__rl": true,
          "mode": "list",
          "value": "aws-codeploy-demo"
        },
        "issueNumber": "={{ $('Create a GitHub issue').item.json.number }}"
      },
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "ee576573-0a96-4713-b71e-cf6b48d1aabe",
      "name": "Add issue link to Jira ticket",
      "type": "n8n-nodes-base.jira",
      "position": [
        2592,
        416
      ],
      "parameters": {
        "comment": "=We've created an issue at {{ $('Create a GitHub issue').item.json.html_url }} and assigned it to Copilot.",
        "options": {},
        "issueKey": "={{ $('On Jira ticket updated').item.json.issue.key }}",
        "resource": "issueComment"
      },
      "credentials": {
        "jiraSoftwareCloudApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "46c0c5c2-4670-4a68-8338-5ded401e7242",
      "name": "Mark ticket as assigned",
      "type": "n8n-nodes-base.jira",
      "position": [
        2592,
        656
      ],
      "parameters": {
        "issueKey": "={{ $('On Jira ticket updated').item.json.issue.key }}",
        "operation": "update",
        "updateFields": {
          "labels": "={{ $('On Jira ticket updated').item.json.issue.fields.labels.concat('copilot_assigned') }}"
        }
      },
      "credentials": {
        "jiraSoftwareCloudApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "155cb785-4a98-4d57-a8ed-fb45cd8a800e",
      "name": "On Jira ticket updated",
      "type": "n8n-nodes-base.jiraTrigger",
      "position": [
        960,
        560
      ],
      "parameters": {
        "events": [
          "jira:issue_updated"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "jiraSoftwareCloudApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "4193fee9-a6b8-4fa3-a0cd-17397c54d64e",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        240
      ],
      "parameters": {
        "width": 512,
        "height": 672,
        "content": "## Auto-resolve Jira tickets with coding agents\n\nImprove issue resolution by assigning Jira tickets to coding agents with full operational context from Port, ensuring faster, accurate, and context-aware development\n\n### How it works\n1. Listen for Jira ticket updates and detect when an issue moves to \\\"In Progress\\\" with the label product_approved and without copilot_assigned.\n2. Query the Port catalog to extract only contextual information relevant to the Jira issue (services, repos, docs, resources, dependencies).\n3. Generate a concise GitHub issue title and a self-contained issue body that summarizes the Jira description and includes any found Port context.\n4. Create the GitHub issue in the target repository and post a comment that requests Copilot to take ownership.\n5. Write the GitHub link back to the Jira ticket and add the copilot_assigned label so the ticket is marked as handled.\n\n### Setup\n- [ ] Connect your Jira Cloud account and enable issue_updated events\n- [ ] Register for free on [Port.io](https://www.port.io)\n- [ ]  Connect your Port.io account and add the API key\n- [ ] Connect your GitHub account and select the target repository\n- [ ] Ensure a Copilot bot or @copilot user has access to the repository\n- [ ] Confirm the workflow webhook or Jira trigger URL is active\n- [ ] Test by moving a product_approved ticket to In Progress"
      },
      "typeVersion": 1
    },
    {
      "id": "ff5792b7-5bcf-4837-9cc8-232f7dc69f7b",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1408,
        256
      ],
      "parameters": {
        "color": 6,
        "width": 400,
        "height": 560,
        "content": "## Port Context Lake\n\nTo extract contextual information relevant to the Jira issue (services, repos, docs, resources, dependencies)."
      },
      "typeVersion": 1
    },
    {
      "id": "c4d094bd-342f-4625-a881-484ea9b2ad45",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1840,
        256
      ],
      "parameters": {
        "color": 4,
        "width": 592,
        "height": 560,
        "content": "## Github Copilot Assignment\n\nTo assign a ticket to Copilot, we first create a GitHub issue and then add a @copilot comment to the GitHub issue instructing Copilot to take ownership."
      },
      "typeVersion": 1
    },
    {
      "id": "c0593d1b-48f9-4bfe-88db-6b2e2a0dbbf4",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2464,
        256
      ],
      "parameters": {
        "color": 5,
        "width": 464,
        "height": 560,
        "content": "## Jira Ticket Linkage\n\nTo ensure that any new Github issue related to a Jira ticket is promptly linked back to the ticket in a comment, providing clear traceability and context for development progress."
      },
      "typeVersion": 1
    },
    {
      "id": "da319617-4f73-4988-8558-370cea868d60",
      "name": "Parse Port AI response",
      "type": "@port-labs/n8n-nodes-portio-experimental.portApiAi",
      "position": [
        1664,
        544
      ],
      "parameters": {
        "operation": "getInvocation",
        "invocation_identifier": "={{ $json.invocationIdentifier }}"
      },
      "credentials": {
        "portApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "9f3068e9-cbbe-47a6-a617-35914ba2c366",
      "name": "Extract context from Port",
      "type": "@port-labs/n8n-nodes-portio-experimental.portApiAi",
      "position": [
        1472,
        544
      ],
      "parameters": {
        "operation": "generalInvoke",
        "userPrompt": "=A Jira issue has moved to In Progress.\n\nIssue Details:\n- Key: {{ $('On Jira ticket updated').item.json.issue.key }}\n- Title: {{ $('On Jira ticket updated').item.json.issue.fields.summary }}\n- Type: {{ $('On Jira ticket updated').item.json.issue.fields.issuetype.name }}\n- Description: {{ $('On Jira ticket updated').item.json.issue.fields.description }}\n\nRelated Jira Project:\n- Key: {{ $('On Jira ticket updated').item.json.issue.fields.project.key }}\n- Name: {{ $('On Jira ticket updated').item.json.issue.fields.project.name }}\n\nRelated Service or Github Repo entity ID:\n{{ $('On Jira ticket updated').item.json.issue.fields.customfield_10308.value }}\n\nYour task:\nUse the Related Service/Repo ID and Issue ID to query the Port catalog.\n\nWhen querying Port entities via MCP (e.g. list_entities):\n- Always fetch ALL available properties for each entity\n- Do not limit properties unless explicitly required\n\nExtract ONLY context that actually exists and is directly related via Port relationships.\n\n### Core service context (if available)\n- Service description and tier based on the README\n- Owning team(s)\n- Deployment environments (e.g. prod, staging, dev)\n- Key dependencies (upstream/downstream services)\n\n### Relationship-heavy context (AGGREGATE, DO NOT LIST)\nFor the related service/repository, summarize:\n- PagerDuty incidents:\n  - Total number of open incidents\n- Deployments:\n  - Total number of deployments\n  - Environments deployed to\n  - Most recent deployment timestamp (if available)\n- Security vulnerabilities:\n  - Total number of open vulnerabilities\n  - Breakdown by severity (e.g. critical / high / medium)\n\nDo NOT include:\n- Raw logs\n- \u201cNone found\u201d bullet lists\n\nOnly mention a category if at least one related entity exists.\n\nThen prepare:\n1. A GitHub issue title that starts with the Jira key.\n2. A GitHub issue body that:\n- Clearly summarizes the Jira issue in developer-friendly language\n- Adds concise business-relevant Port context (ownership, risk, stability, deploy state)\n- Uses aggregated facts, not exhaustive lists\n- Avoids assumptions or inferred data\n- Is fully self-contained\n- Ends exactly with: @github-copilot please begin working on this issue.\n\nIMPORTANT OUTPUT CONSTRAINT (HIGHEST PRIORITY)\n- If no relevant Port context exists, use empty strings (\"\") for fields where applicable.\n- You must return ONLY a valid JSON object and nothing else.\n\nOutput format:\nThe response must be parseable by JSON.parse() with no cleanup.\nReturn EXACTLY:\n{\"github_issue_title\":\"\",\"github_issue_body\":\"\"}\n",
        "generalModel": "gpt-5",
        "systemPrompt": "You are a helpful assistant that extracts contextual information from the Port catalogue. You must return ONLY a valid JSON object and nothing else. If you violate this output format, downstream systems will fail.",
        "executionMode": "Automatic",
        "generalProvider": "port"
      },
      "credentials": {
        "portApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "de493068-851e-422d-96f5-9891b3e6868e",
  "connections": {
    "Create a GitHub issue": {
      "main": [
        [
          {
            "node": "Is issue creation successful?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On Jira ticket updated": {
      "main": [
        [
          {
            "node": "Is ready for assignment?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Port AI response": {
      "main": [
        [
          {
            "node": "Create a GitHub issue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Assign issue to Copilot": {
      "main": [
        [
          {
            "node": "Add issue link to Jira ticket",
            "type": "main",
            "index": 0
          },
          {
            "node": "Mark ticket as assigned",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is ready for assignment?": {
      "main": [
        [
          {
            "node": "Extract context from Port",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract context from Port": {
      "main": [
        [
          {
            "node": "Parse Port AI response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is issue creation successful?": {
      "main": [
        [
          {
            "node": "Assign issue to Copilot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}