- Published on
Playing Around With Githubs GraphQL API
- Authors
- Name
- Yair Mark
- @yairmark
Tips on Building Your GitHub GraphQL Query
I wanted to get some data from Github and found that the recommended way to do this nowadays is using their v4 API which is a GraphQL endpoint. There is a setup process to get an app token but to play around with the API you do not need to do this.
Instead head to the Github V4 explorer here and click Sign in with GitHub
. Once you have granted access you are returned to the GraphQL explorer.
A number of things I picked up which make exploring GraphQL APIs super easy are:
- Getting Query Completion/Suggestions: ctrl+space
- This is the easiest way to see what is available in the API
- ctrl+space in the parameter section for a property to see what parameters it takes.
- ctrl+space in the angle brackets section to see the values it can return
- Viewing the Docs for a Query Element: ctrl+click a value to see the docs for it
- Error warnings: The explorer tells you about errors immediately. For example if you need to provide parameters for a query the explorer tells you. If you have to provide fields for an element again the query explorer tells you with an error.
- Prettify: The Prettify button helps plenty in formatting your query nicely
- Beware this will remove your comments
- Not everything can be worked out: Google anything else you are not sure about
- For example getting the number of commits for a repo is not trivial via the api you do this using (note
num_commits:
is an alias as described below):
- For example getting the number of commits for a repo is not trivial via the api you do this using (note
num_commits: ref(qualifiedName: "master") {
target {
... on Commit {
history {
totalCount
}
}
}
}
- Use the network panel: If you are not sure how this query will translate to a cURL request or whatever webservice client you are using then do the following:
- Put you query in the explorer
- Open the network panel in your browser:
Cmd/Ctrl+Shift+I
- Go to the network tab
- Click the run button
- Look at the response body and headers
- Note: you will need the following also when doing this via a client and not the explorer:
- You need to
POST
to thehttps://api.github.com/graphql
endpoint - You need to have an
Authorization: bearer yourAppToken
header (google how to setup a Github app to create your token)
- You need to
Useful GraphQL Features
A number of GraphQL features helped me build up my queries more easily and also make them more readable and maintainable:
- Templates AKA Fragments: You use this if you have a huge query you want to repeat but with different parameters:
- This avoids repetition and also makes your code more maintainable as you only need to update common sections in one place
- Arguments: Some but not all queries can and sometimes require parameters. These are like arguments to a method in a JavaScript function that you are calling.
- Aliases: This allows you to name queries to whatever you want. This makes your query more readable and is actually required if you want to hit the same field again with different parameters
- For example for a repo if I wanted to get total issues, open issues and closed issues I need to hit the same query with different parameters meaning I have to alias this. This is done as below:
total_issues: issues(states: [OPEN, CLOSED]) {
totalCount
}
open_issues: issues(states: [OPEN]) {
totalCount
}
closed_issues: issues(states: [CLOSED]) {
totalCount
}
GraphQL File Extension: If you want to save your query to a file the recommended extension (which Facebook themselves use) is
.graphql
as can be seen here.Comments: You comment using a
#
at the beginning of a line:
# this is a comment
Example Query
I built a query to get some of the basic stats for one or more different repos. In the below example I am comparing the React and Angular frameworks.
fragment code_repo_details on Repository {
num_commits: ref(qualifiedName: "master") {
target {
... on Commit {
history {
totalCount
}
}
}
}
createdAt
forkCount
total_issues: issues(states: [OPEN, CLOSED]) {
totalCount
}
open_issues: issues(states: [OPEN]) {
totalCount
}
closed_issues: issues(states: [CLOSED]) {
totalCount
}
stars: stargazers {
totalCount
}
milestones {
totalCount
}
total_prs: pullRequests(states: [OPEN, CLOSED, MERGED]) {
totalCount
}
open_prs: pullRequests(states: [OPEN]) {
totalCount
}
closed_prs: pullRequests(states: [CLOSED]) {
totalCount
}
merged_prs: pullRequests(states: [MERGED]) {
totalCount
}
updatedAt
watchers {
totalCount
}
}
{
# this repo's URL is: https://github.com/facebook/react
# owner = main user in repo which can be seen in a repo's URL as follows
# https://github.com/thisIsWhereTheOwnerIs/thisIsTheRepoName
react: repository(name: "react", owner: "facebook") {
...code_repo_details
}
# this repo's URL is: https://github.com/angular/angular
angular: repository(name: "angular", owner: "angular") {
...code_repo_details
}
}
As of the time of writing this article this outputs the following JSON:
{
"data": {
"react": {
"num_commits": {
"target": {
"history": {
"totalCount": 10559
}
}
},
"createdAt": "2013-05-24T16:15:54Z",
"forkCount": 21405,
"total_issues": {
"totalCount": 6786
},
"open_issues": {
"totalCount": 397
},
"closed_issues": {
"totalCount": 6389
},
"stars": {
"totalCount": 118003
},
"milestones": {
"totalCount": 39
},
"total_prs": {
"totalCount": 7534
},
"open_prs": {
"totalCount": 128
},
"closed_prs": {
"totalCount": 2159
},
"merged_prs": {
"totalCount": 5247
},
"updatedAt": "2018-12-20T13:48:34Z",
"watchers": {
"totalCount": 6592
}
},
"angular": {
"num_commits": {
"target": {
"history": {
"totalCount": 12368
}
}
},
"createdAt": "2014-09-18T16:12:01Z",
"forkCount": 11231,
"total_issues": {
"totalCount": 16806
},
"open_issues": {
"totalCount": 2226
},
"closed_issues": {
"totalCount": 14580
},
"stars": {
"totalCount": 43678
},
"milestones": {
"totalCount": 61
},
"total_prs": {
"totalCount": 10887
},
"open_prs": {
"totalCount": 394
},
"closed_prs": {
"totalCount": 7603
},
"merged_prs": {
"totalCount": 2890
},
"updatedAt": "2018-12-20T13:43:46Z",
"watchers": {
"totalCount": 3309
}
}
}
}