How to Get All Issues Linked to a Pull Request
Tags: github, graphql
Published: 2022-07-31 04:01:37

## Intro
The Github API provides a lot of fluidity in being able to access and mutate data within git programmatically. Github provides developers with both a traditional [REST API](https://octokit.github.io/rest.js/v18/) and a more modern [GraphQL API](https://github.com/octokit/graphql.js) to interact with. However because of the increased flexibility of GraphQL APIs, there is some functionality that is available in GraphQL that is not available in REST. 

So today, we'll explore how to use Github's GraphQL API to find all issues linked to a pull request. 

**Note:** This tutorial will be using node. Scroll to bottom for a TLDR;

## Prerequisites
1. Have a personal access token created in Github. This a personal oAuth token that Github uses to verify what user you are and if you have permissions to access the data that you're requesting. If you do not have one, you can create one using the documentation [here](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token). Make sure to create the token with the following permissions: `repo`, `workflow`, `user`
2. Have a basic understanding of how GraphQL queries work. We'll go over the structure of the specific query needed in this article, but it helps to have that knowledge upfront 


## The Query


```
query getLinkedIssues(
  $repository: String!,
  $organizationOrOwner: String!,
  $prNumber: Int!,
  $maxIssues: Int!,
) {
  repository(number: $prNumber) {
    closingIssuesReference(first: $maxIssues) {
      nodes {
        number
        body
        title
      }
    }
  }
}
```

A breakdown of the query 
```
query getLinkedIssues( 
  /*
    These are the params (or data points) needed to run the query
    Params with a bang operator (!) are required

    It includes: 
     - repository: name of the repository you're accessing
     - owner: name of the owner of the repository
     - prNumber: the number of the pull request who's issues you need 
     - maxIssues: the maximum number of issues that you would like returned
  */
  $repository: String!,
  $owner: String!,
  $prNumber: Int!,
  $maxIssues: Int!,
) {
  repository(number: $prNumber) {

    // All issues referenced in the PR with a closing prefix
    // Examples here: https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue
    closingIssuesReference(first: $maxIssues) {

      // Nodes represent the individual issues 
      nodes {

        // The data we want returned for each issue
        // Check out the Github GraphQL Explorer for a full list
        // https://docs.github.com/en/graphql/overview/explorer
        number
        body
        title
      }
    }
  }
}
```
# Making the Request
There are [a few libraries](https://docs.github.com/en/rest/overview/libraries) you can use to interact with the Github API client that give you the ability to interact with Github's GraphQL client. For the purpose of this tutorial we'll provide one example using octokit's node-based client. 

If you'd like more control on the type of data you return back, feel free to check out [Github's GraphQL Explorer](https://docs.github.com/en/graphql/overview/explorer). It's a great playground that allows you to practice (and execute) queries so you can get a feel of the full API. 
```javascript

import { graphql } from "@octokit/graphql";

const linkedIssuesQuery = `
query getLinkedIssues(
  $repository: String!,
  $owner: String!,
  $prNumber: Int!,
  $maxIssues: Int!,
) {
  repository(number: $prNumber) {
    closingIssuesReference(first: $maxIssues) {
      nodes {
        number
        body
        title
      }
    }
  }
}
`

/* NOTE: 
This function needs your personal access token
in order to authorize and execute the query. 

DO NOT COPY AND PASTE YOUR TOKEN DIRECTLY. 

Instead, I recommend keeping the token in a 
.env file and not committing it to your source code
*/

const getIssueData = async (myToken) => {
  const issueData = await graphql({
    query: linkedIssuesQuery,
    repository: [INSERT_REPO_NAME_HERE],
    owner:[INSERT_OWNER_HERE],
    prNumber: [INSERT_PR_NUMBER_HERE],
    maxIssues: [INSERT_MAX_ISSUES_HERE],
    headers: {
      // Include a space after the word bearer
      authorization: "bearer " + myToken,
    },
  });
}
```

## TLDR;
```
query getLinkedIssues(
  $repository: String!,
  $organizationOrOwner: String!,
  $prNumber: Int!,
  $maxIssues: Int!,
) {
  repository(number: $prNumber) {
    closingIssuesReference(first: $maxIssues) {
      nodes {
        number
        body
        title
      }
    }
  }
}
```