Skip to main content

Check out Port for yourself ➜ 

Automatically resolve tickets with coding agents

Available Github Integrations

This guide includes one or more steps that require integration with GitHub.
Port supports two GitHub integrations:

  • GitHub (Legacy) - uses a GitHub app, which is soon to be deprecated.
  • GitHub (Ocean) - uses the Ocean framework, recommended for new integrations.

Both integration options are present in this guide via tabs, choose the one that fits your needs.

Coding agents can significantly speed up development, but crucial engineering context often gets lost in the process. This guide shows how to automate the flow from Jira ticket to GitHub issue to coding agent (e.g. GitHub Copilot) and back to Jira.

You can implement this in one of two ways:

  1. Workflow — a single Port workflow runs when a Jira ticket moves to In Progress: it enriches the ticket with catalog context, creates a GitHub issue, triggers Copilot, and comments on Jira with the issue link.

  2. Actions & Automations — an AI agent creates GitHub issues from Jira tickets (with catalog context), and automations trigger the agent and add the PR link to Jira when Copilot opens a pull request.

Both approaches use the same data model and external setup; only the implementation (workflow vs. actions + automations + AI agent) differs.

Automatic ticket resolution with coding agents

Common use cases

  • Auto-create PRs for bug fixes to minimize manual work.
  • Integrate with Copilot for teams not relying on GitHub Issues.
  • Link Jira tickets to PRs to improve cross-platform collaboration.
  • Generate GitHub issues from Jira for faster prototyping.

Prerequisites

This guide assumes the following:

  • You have completed the setup in the Trigger GitHub Copilot from Port guide, so that Copilot is automatically assigned to GitHub issues created through this guide.
  • For the Actions & Automations option: you have access to create and configure AI agents in Port.
  • For the Workflow option: you have access to workflows in Port. Workflows are currently in closed beta and may undergo breaking changes and occasional downtime without prior notice.
Alternative integrations and coding agents

While this guide uses GitHub and Jira, you can adapt it for other Git providers (e.g. GitLab, Azure DevOps) and project management tools (e.g. Linear). You can also use other coding agents (e.g. Claude Code, Devin) instead of GitHub Copilot for similar automation.

Set up data model

We will configure the necessary blueprints to support our AI-enhanced coding workflow. This involves updating the Jira issue blueprint with necessary relations.

Update Jira issue blueprint

When you install Port's Jira integration, the Jira project and issue blueprints are created by default. However, we need to update the Jira issue blueprint to add the pull request relation and create a mirror property for the PR link.

  1. Go to the builder page of your portal.

  2. Find and select your existing Jira issue blueprint (e.g. jiraIssue).

  3. Click on {...} Edit JSON.

  4. Add the following relation to the relations section:

    Pull request relation (click to expand)
    "pull_request": {
    "target": "githubPullRequest",
    "required": false,
    "many": false
    }
  5. Add the following mirror property to the mirrorProperties section:

    Pull request link mirror property (click to expand)
    "pull_request_link": {
    "title": "Pull Request Link",
    "path": "pull_request.link"
    }
  6. Click Save to update the blueprint.

Update GitHub integration mapping

To track pull requests opened by Copilot that are meant to fix Jira issues, we need to update the GitHub integration mapping so that a pull request can be linked to the corresponding Jira issue using the Jira issue key in the PR title.

  1. Go to the builder page of your portal.

  2. Find and select your existing GitHub integration configuration.

  3. Click on {...} Edit JSON.

  4. Add the following mapping to the mappings section:

    Pull request mapping (click to expand)
    - kind: pull-request
    selector:
    query: ((.title // "") | test("[A-Z]+-[0-9]+")) and (.user.login == "Copilot")
    port:
    entity:
    mappings:
    identifier: (.title // "") | match("[A-Z]+-[0-9]+").string
    blueprint: '"jiraIssue"'
    properties: {}
    relations:
    pull_request: .id|tostring
  5. Click Save to update the integration configuration.

Set up external tools

We need Jira API access so that the workflow or automations can add comments to Jira issues.

Set up Jira API access

  1. Log in to your Jira instance.
  2. Generate an API token:
    • Go to Atlassian Account Settings.
    • Click Create API token. Ensure the token has permission to update issues and add comments.
    • Copy the generated token (you will need it for the Port secret).

Add Port secrets

To add secrets to your portal:

  1. Click ... in the top right corner of your Port application.

  2. Click Credentials.

  3. Click the Secrets tab.

  4. Click + Secret and add the following secrets:

    • GITHUB_TOKEN — A GitHub fine-grained personal access token with read and write permissions for Issues, Metadata, and Pull requests, and Actions (write) for workflow dispatch. Required for the Workflow option; the Actions & Automations option may need it if you use an action that creates GitHub issues via the API.
    • GITHUB_ORG — Your GitHub organization or username. Required for the Actions & Automations option when using the create_github_issue action.

Implementation in Port

Choose one implementation. The data model and external setup above are the same for both.

  • Workflow — One workflow runs when a Jira issue moves to In Progress with the required label. It calls Port AI for context, creates a GitHub issue, triggers the Copilot assignment workflow, and comments on the Jira issue with the GitHub link. No separate AI agent; the flow is deterministic and visible in the workflow editor.
  • Actions & Automations — You create an AI agent that generates GitHub issues from Jira tickets, and two automations: one that invokes the agent when a Jira ticket moves to In Progress with the copilot label, and one that adds the PR link to the Jira ticket when a related pull request is created.

Build the workflow

Use Port's workflow to run the full sequence: trigger on Jira update → enrich with AI context → create GitHub issue → trigger Copilot → comment on Jira. You can build it with the AI assistant or paste the JSON template.

  1. Go to the workflows page of your portal.

  2. Click + Workflow.

  3. In the dialog, click Skip to editor.

    Create new workflow dialog
  4. Copy and paste this JSON template directly into the workflow editor.

    Automatically resolve ticket workflow template (click to expand)
    {
    "identifier": "automatic_ticket_resolution_workflow",
    "title": "Autonomous Ticket Resolution With AI",
    "icon": "Jira",
    "description": "Automatically generate GitHub issues from Jira tickets with rich organizational context when tickets move to In Progress, assign to GitHub Copilot, and link PRs back to Jira",
    "allowAnyoneToViewRuns": true,
    "nodes": [
    {
    "identifier": "comment_on_jira_ai_failure",
    "title": "Comment on Jira – AI Context Failed",
    "icon": "Jira",
    "description": "Adds a comment to the Jira issue explaining that automated GitHub issue creation was skipped because AI context extraction failed, and suggests next steps.",
    "config": {
    "type": "WEBHOOK",
    "url": "https://<YOUR_JIRA_ORGANIZATION_URL>/rest/api/3/issue/{{ .outputs.trigger.jira_key }}/comment",
    "agent": false,
    "synchronized": true,
    "method": "POST",
    "headers": {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Authorization": "Basic {{ .secrets._JIRA_ATLASSIAN_USER_EMAIL + \":\" + .secrets._JIRA_ATLASSIAN_USER_TOKEN | @base64 }}"
    },
    "body": {
    "body": {
    "type": "doc",
    "content": [
    {
    "type": "paragraph",
    "content": [
    {
    "text": "⚠️ Automated GitHub issue creation was skipped because context enrichment failed.",
    "type": "text"
    }
    ]
    },
    {
    "type": "paragraph",
    "content": [
    {
    "text": "What this means:\n• The Jira ticket was detected correctly\n• The AI step did not return usable context\n• No GitHub issue was created to avoid low-quality or incomplete data",
    "type": "text"
    }
    ]
    },
    {
    "type": "paragraph",
    "content": [
    {
    "text": "Next steps:\n• You can retry the automation\n• Or manually create a GitHub issue if work should proceed immediately",
    "type": "text"
    }
    ]
    }
    ],
    "version": 1
    }
    }
    },
    "variables": {}
    },
    {
    "identifier": "create_github_issue",
    "title": "Create GitHub Issue",
    "icon": "Github",
    "description": "Creates a new GitHub issue using the Jira issue details and AI-generated context",
    "config": {
    "type": "WEBHOOK",
    "url": "https://api.github.com/repos/<GITHUB_ORG>/<GITHUB_REPO>/issues",
    "agent": false,
    "synchronized": true,
    "method": "POST",
    "headers": {
    "Accept": "application/vnd.github+json",
    "Authorization": "Bearer {{ .secrets.GITHUB_TOKEN }}",
    "X-GitHub-Api-Version": "2022-11-28"
    },
    "body": {
    "body": "{{ .outputs.extract_context_with_ai.ai_response }}",
    "title": "{{ .outputs.trigger.jira_key + \" - \" + .outputs.trigger.jira_title }}",
    "labels": [
    "auto_assign"
    ]
    }
    },
    "variables": {
    "issue_url": "{{ .response.data.html_url }}",
    "issue_number": "{{ .response.data.number }}"
    }
    },
    {
    "identifier": "extract_context_with_ai",
    "title": "Extract Context with Port AI",
    "icon": "AI",
    "description": "Invokes Port AI to enrich the Jira issue with contextual data from the Port catalog",
    "config": {
    "type": "AI",
    "userPrompt": "A Jira issue has moved to In Progress.\n\nIssue Details:\n- Key: {{ .outputs.trigger.jira_key }}\n- Title: {{ .outputs.trigger.jira_title }}\n- Type: {{ .outputs.trigger.jira_type }}\n- Description: {{ .outputs.trigger.jira_description }}\n\nRelated Jira Project:\n- Key: {{ .outputs.trigger.jira_project_key }}\n\nYour task:\nQuery the Port catalog using MCP tools (e.g list_entities) to find any related services or repositories connected to this Jira issue.\n\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)\n- Key dependencies (upstream/downstream services)\n\n### Relationship-heavy context (AGGREGATE, DO NOT LIST)\nFor the related service/repository, summarize:\n- PagerDuty incidents: total number of open incidents\n- Deployments: number of deployments, environments deployed to, most recent deployment timestamp (if available)\n- Security vulnerabilities: number of open vulnerabilities, breakdown by severity (e.g. critical / high / medium)\n\nDo NOT include: raw logs, \"None found\" bullet lists. Only mention a category if at least one related entity exists.\n\nThen prepare:\n1. A GitHub issue title that starts with the Jira key in this exact format: {{ .outputs.trigger.jira_key }} - <what needs to be done>\n2. A GitHub issue body that clearly summarizes the Jira issue in developer-friendly language, adds concise business-relevant Port context (ownership, risk, stability, deploy state), uses aggregated facts not exhaustive lists, avoids assumptions or inferred data, and is fully self-contained.",
    "systemPrompt": "You are a helpful assistant that extracts contextual information from the Port catalogue.",
    "tools": [
    "^(list|get|search|track|describe)_.*"
    ]
    },
    "variables": {
    "ai_error": "{{ .error }}",
    "ai_response": "{{ .response }}"
    }
    },
    {
    "identifier": "has_ai_context",
    "title": "Has AI Response",
    "icon": null,
    "description": "Checks whether the AI context extraction completed successfully and returned a non-empty response. Prevents downstream actions when AI invocation fails or returns no usable output.",
    "config": {
    "type": "CONDITION",
    "options": [
    {
    "identifier": "yes",
    "title": "AI context available",
    "expression": "(.outputs.extract_context_with_ai.ai_error == null and .outputs.extract_context_with_ai.ai_response != null)"
    },
    {
    "identifier": "no",
    "title": "AI failed or returned no context",
    "expression": ".outputs.extract_context_with_ai.ai_error != null"
    }
    ]
    },
    "variables": {}
    },
    {
    "identifier": "trigger",
    "title": "On Jira Ticket Updated",
    "icon": "Jira",
    "description": "Listens for Jira issue updates and triggers the workflow when a ticket transitions from 'To Do' to 'In Progress', is product-approved, and has an assignee.",
    "config": {
    "type": "EVENT_TRIGGER",
    "event": {
    "type": "ENTITY_UPDATED",
    "blueprintIdentifier": "jiraIssue"
    },
    "condition": {
    "type": "JQ",
    "expressions": [
    ".diff.before.properties.status == \"To Do\"",
    ".diff.after.properties.status == \"In Progress\"",
    "(.diff.after.properties.labels | index(\"copilot\")) != null"
    ],
    "combinator": "and"
    }
    },
    "variables": {
    "jira_key": "{{ .diff.after.identifier }}",
    "jira_url": "{{ .diff.after.properties.url }}",
    "jira_type": "{{ .diff.after.properties.issueType }}",
    "jira_title": "{{ .diff.after.title }}",
    "assignee_email": "{{ .diff.after.relations.assignee }}",
    "jira_description": "{{ .diff.after.properties.description }}",
    "jira_project_key": "{{ .diff.after.relations.project }}"
    }
    },
    {
    "identifier": "trigger_copilot_assignment",
    "title": "Trigger Copilot Assignment Workflow",
    "icon": "Github",
    "description": "Triggers a GitHub Actions workflow that assigns the newly created GitHub issue to GitHub Copilot, enabling AI-assisted implementation.",
    "config": {
    "type": "WEBHOOK",
    "url": "https://api.github.com/repos/<GITHUB_ORG>/<GITHUB_REPO>/actions/workflows/assign_to_copilot.yml/dispatches",
    "agent": false,
    "synchronized": true,
    "method": "POST",
    "headers": {
    "Accept": "application/vnd.github+json",
    "Authorization": "Bearer {{ .secrets.GITHUB_TOKEN }}",
    "X-GitHub-Api-Version": "2022-11-28"
    },
    "body": {
    "ref": "main",
    "inputs": {
    "issue_number": "{{.outputs.create_github_issue.issue_number | tostring}}",
    "repository_name": "<GITHUB_REPO>",
    "repository_owner": "<GITHUB_ORG>"
    }
    }
    },
    "variables": {}
    },
    {
    "identifier": "update_jira_with_github_link",
    "title": "Add Comment to Jira Issue",
    "icon": "Jira",
    "description": "Adds a comment to the original Jira ticket containing a direct link to the created GitHub issue, ensuring traceability between Jira and GitHub.",
    "config": {
    "type": "WEBHOOK",
    "url": "https://<YOUR_JIRA_ORGANIZATION_URL>/rest/api/3/issue/{{.outputs.trigger.jira_key}}/comment",
    "agent": false,
    "synchronized": true,
    "method": "POST",
    "headers": {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Authorization": "Basic {{ .secrets._JIRA_ATLASSIAN_USER_EMAIL + \":\" + .secrets._JIRA_ATLASSIAN_USER_TOKEN | @base64 }}"
    },
    "body": {
    "body": {
    "type": "doc",
    "content": [
    {
    "type": "paragraph",
    "content": [
    {
    "text": "✅ GitHub issue created and assigned to Copilot: ",
    "type": "text"
    },
    {
    "text": "{{ .outputs.create_github_issue.issue_url }}",
    "type": "text",
    "marks": [
    {
    "type": "link",
    "attrs": {
    "href": "{{ .outputs.create_github_issue.issue_url }}"
    }
    }
    ]
    }
    ]
    }
    ],
    "version": 1
    }
    }
    },
    "variables": {}
    }
    ],
    "connections": [
    {
    "description": "Triggered when a Jira issue meets the workflow criteria and begins AI-based context enrichment.",
    "sourceIdentifier": "trigger",
    "targetIdentifier": "extract_context_with_ai"
    },
    {
    "description": "Routes the AI invocation result into a conditional gate to determine whether downstream actions should proceed.",
    "sourceIdentifier": "extract_context_with_ai",
    "targetIdentifier": "has_ai_context"
    },
    {
    "description": "Continues workflow execution only when AI context extraction succeeds",
    "sourceIdentifier": "has_ai_context",
    "targetIdentifier": "create_github_issue",
    "sourceOptionIdentifier": "yes"
    },
    {
    "description": "Uses the newly created GitHub issue to trigger Copilot assignment.",
    "sourceIdentifier": "create_github_issue",
    "targetIdentifier": "trigger_copilot_assignment"
    },
    {
    "description": "Finalizes the workflow by linking the GitHub issue back to the originating Jira ticket.",
    "sourceIdentifier": "trigger_copilot_assignment",
    "targetIdentifier": "update_jira_with_github_link"
    },
    {
    "description": "Notifies Jira that AI context extraction failed and GitHub issue creation was intentionally skipped.",
    "sourceIdentifier": "has_ai_context",
    "targetIdentifier": "comment_on_jira_ai_failure",
    "sourceOptionIdentifier": "no"
    }
    ]
    }
  5. Click Publish in the top right corner of the editor. If you encounter validation errors, refer to the workflows troubleshooting page.

Configure the workflow

After publishing, replace placeholder values in the workflow nodes.

Specify Jira URL and auth

  • In the Comment on Jira – AI Context Failed (comment_on_jira_ai_failure) and Add Comment to Jira Issue (update_jira_with_github_link) nodes:
    • Replace <YOUR_JIRA_ORGANIZATION_URL> in the webhook URL with your Jira organization URL (e.g. example.atlassian.net).

Configure the GitHub integration

  • In the Create GitHub Issue (create_github_issue) node:
    • Replace <GITHUB_ORG> with your GitHub organization or username.
    • Replace <GITHUB_REPO> with your repository name.
  • In the Trigger Copilot Assignment Workflow (trigger_copilot_assignment) node:
    • Replace <GITHUB_ORG> and <GITHUB_REPO> in the webhook URL with the same values.
    • Update the repository_name and repository_owner inputs to match.

Test the implementation

After you complete either the Workflow or the Actions & Automations setup, use the steps below to verify that ticket resolution runs correctly.

Trigger a test Jira ticket update

  1. Go to your Jira instance and find a test ticket.
  2. Add the required label:
    • Workflow: add the product_approved label and ensure the ticket has an assignee.
    • Actions & Automations: add the copilot label.
  3. Move the ticket status from To Do to In Progress.

Verify GitHub issue creation

  1. Go to your GitHub repository.
  2. Verify that a new issue was created with the appropriate title (starting with the Jira key), description, and labels.
  3. Check that the issue has the auto_assign label.

Test pull request linking

  1. Verify that the GitHub issue is automatically assigned to Copilot.
  2. Confirm that a pull request is created (with the Jira ticket key in the title for the Actions & Automations flow).
  3. Check the Jira ticket for a comment: Workflow adds the GitHub issue link; Actions & Automations adds the PR link when the PR is linked to the Jira issue.
Test workflow result