Skip to content

Instantly share code, notes, and snippets.

@eugenet8k
Last active October 30, 2025 13:59
Show Gist options
  • Select an option

  • Save eugenet8k/1295e86de9497542930828f2bf791cdc to your computer and use it in GitHub Desktop.

Select an option

Save eugenet8k/1295e86de9497542930828f2bf791cdc to your computer and use it in GitHub Desktop.
Simple guide for virtual engineer JIRA + GitHub

Cloud Jira and GitHub.com offer some integration, but it's not complete to accomplish a simple goal of creating a virtual software engineer.

We want an AI agent like entity that you can assign the work and get PR as result without subscribing to 3rd party solution. We want to use essential tools available to average org.

This is achieved by a clever configuration of JIRA and Github to pass the signal with the tools they offer now. The strategy is simple:

[Assign Jira to Copilot user] --> [Jira send signal to GitHub (create branch with jira id)] --> [GitHub action listens branch creation] --> [Create GitHub Issue with body "Address Jira AA-123" and assign it to GitHub Copilot] --> [GitHub Copilot works on task, creates PR] --> [You review PR and merge it] --> [GitHub app notifies Jira the work is done] --> [Close Jira ticket]

Steps:

  1. Create a user in Jira, let's say [email protected], configure it to have member level permission to a particular Jira Space (Project). This is to prevent hypothetical corp data drain if Jira token permission is abused.

  2. Log in into Jira with this user and create API token for MCP access. https://id.atlassian.com/manage-profile/security/api-tokens

  3. Install official GitHub app into your Jira

  4. In Github.com install official Atlassian app into your org and allow access to target repos

  5. In Github.com enable Copilot Coding Agent

  6. Configure Jira MCP for GitHub Copilot at https://github.com/my-crop/my-repo/settings/copilot/coding_agent

{
  "mcpServers": {
    "atlassian-mcp": {
      "type": "local",
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "JIRA_URL=http://mycorp.jira.com",
        "-e",
        "[email protected]",
        "-e",
        "JIRA_API_TOKEN=ATATT....",
        "ghcr.io/sooperset/mcp-atlassian:0.11.9"
      ],
      "tools": ["jira_get_issue", "jira_search", "jira_download_attachments", "jira_add_comment"]
    }
  }
}

At the moment of writing this gist, GitHub bug prevented access to Secrets for storing Jira token, so it's inserted as is. Although it should have been an var referring to your org GitHub Secrets.

It's recommended to pin to a particular version of mcp-atlassian docker container. It's a community addon, that you give your corp JIRA access. This is risk. Pinning to a version (ideally review the source code) reduces that chance that some latest update with vulnerability gets access to your corp data without your conscent.

  1. In GitHub.com create your personal PAT token with certain permissions as per https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/create-a-pr#creating-and-assigning-a-new-issue, store it in org Secrets. It must be personal token because Copilot agent is billed based on personal Copilot license.

  2. In Github.com create a workflow that tracks the branch creation. At the moment, the only official operation Jira can do with GitHub is creating a Git branch. We use this tool to pass the signal.

.github/workflows/copilot-address-jira.yml

name: Create Copilot Issue from Jira Branch

'on':
  create:
    branches:
      - 'to-copilot/address-jira-**'

jobs:
  create-copilot-issue:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      issues: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Extract Jira ID from branch name
        id: extract_jira
        run: |
          BRANCH_NAME="${{ github.ref_name }}"
          JIRA_ID=$(echo "$BRANCH_NAME" | sed -n 's/^to-copilot\/address-jira-\(.*\)$/\1/p')
          echo "jira_id=$JIRA_ID" >> $GITHUB_OUTPUT
          echo "Extracted Jira ID: $JIRA_ID"

      - name: Delete signal branch
        run: |
          git push origin --delete "${{ github.ref_name }}"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Create Copilot issue
        uses: ../actions/create-copilot-issue
        with:
          gh-token: ${{ secrets.MY_COPILOT_PAT_TOKEN }}
          issue-title: "Address Jira ${{ steps.extract_jira.outputs.jira_id }}"
          issue-body: "Review and address Jira ticket ${{ steps.extract_jira.outputs.jira_id }}"

.github/actions/create-copilot-issue.yml

name: 'Create Copilot Issue'
description: 'Create a GitHub issue assigned to Copilot with provided instructions'

inputs:
  gh-token:
    description: 'GitHub token for authentication'
    required: true
  issue-title:
    description: 'Title of the GitHub issue to create'
    required: true
  issue-body:
    description: 'Body content of the GitHub issue to create'
    required: true

runs:
  using: "composite"
  steps:
    - name: Create GitHub issue
      shell: bash
      env:
        GH_TOKEN: ${{ inputs.gh-token }}
      run: |
        COPILOT_USER_ID=$(gh api graphql -f query='
          query {
            repository(owner: "${{ github.repository_owner }}", name: "${{ github.event.repository.name }}") {
              suggestedActors(capabilities: [CAN_BE_ASSIGNED], first: 100) {
                nodes {
                  login
                  ... on Bot { id }
                }
              }
            }
          }
        ' --jq '.data.repository.suggestedActors.nodes[] | select(.login == "copilot-swe-agent") | .id')

        if [ -z "$COPILOT_USER_ID" ]; then
          echo "Error: Copilot agent not found/enabled."
          exit 1
        fi

        gh api graphql -f query='
          mutation($repositoryId: ID!, $title: String!, $body: String!, $assigneeIds: [ID!]!) {
            createIssue(input: {
              repositoryId: $repositoryId
              title: $title
              body: $body
              assigneeIds: $assigneeIds
            }) {
              issue {
                number
                url
              }
            }
          }
        ' \
        -f repositoryId="$(gh api repos/${{ github.repository }} --jq '.node_id')" \
        -f title="${{ inputs.issue-title }}" \
        -f body="${{ inputs.issue-body }}" \
        -F assigneeIds[]="$COPILOT_USER_ID"
  1. In Jira create automation for when a ticket is assigned to Copilot user, to create a branch to-copilot/address-jira-AA-12345 in the target repo
Screenshot 2025-10-30 at 6 53 55 AM
  1. Endlessly invest in copilot instructions and repo source code quality to increase the chances of coding agent success.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment