The GitHub Blog 前天 00:04
Exploring GitHub CLI: How to interact with GitHub’s GraphQL API endpoint
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了如何利用GitHub CLI(命令行界面)与GitHub的GraphQL API进行交互,以更有效地查询和修改GitHub数据。文章首先解释了GraphQL的基本概念,包括查询和变更,以及它相对于REST API的优势。接着,详细阐述了如何使用gh api graphql命令进行GraphQL查询和变更,包括身份验证、语法、结果过滤和分页。最后,文章还讨论了选择GraphQL API还是REST API的考量因素。

💡 **什么是GraphQL?** GraphQL是一种用于API的查询语言,允许客户端精确请求所需数据,与REST API相比,减少了网络开销,提高了应用性能,简化了客户端逻辑。它支持两种主要操作:查询(读取数据)和变更(修改数据)。

🔑 **GitHub中的GraphQL应用:** GitHub自2016年开始使用GraphQL,以解决RESTful API的局限性。通过GraphQL,开发者可以用一个查询获取仓库的议题、标签、负责人和评论,避免了REST API中多个嵌套调用的需求。一些GitHub数据和操作只能通过GraphQL API访问。

🚀 **使用GitHub CLI进行GraphQL查询:** GitHub CLI简化了GraphQL的查询和变更过程,它自动处理身份验证,提供简洁的语法,支持本地开发,并内置JSON处理和分页支持。使用`gh api graphql`命令,可以轻松地进行查询和变更操作,例如获取仓库信息或创建新的议题。

⚙️ **GraphQL与REST API的选择:** 在选择使用REST API还是GraphQL API时,需要考虑速率限制和数据获取需求。对于关系型对象,GraphQL通常更有效;对于单一类型的大量数据或单个数据点,REST API可能更合适。GitHub CLI支持使用JQ进行结果过滤,方便提取所需数据。

🔄 **处理分页:** GitHub的GraphQL API对每页结果有限制,因此需要使用分页来检索更大的数据集。GraphQL使用游标(cursor)来处理分页,以便在结果中导航。

You might have heard of the GitHub CLI and all of the awesome things you can do with it. However, one of its hidden superpowers is the ability to execute complex queries and mutations through GitHub’s GraphQL API. This post will walk you through what GitHub’s GraphQL API endpoint is and how to query it with the GitHub CLI.

What is GraphQL?

Let’s start with the basics: GraphQL is a query language for APIs and a runtime for executing those queries against your data. Unlike traditional REST APIs that provide fixed data structures from predefined endpoints, GraphQL allows clients to request exactly the data they need in a single request. This single-request approach reduces network overhead, speeds up application performance, and simplifies client-side logic by eliminating the need to reconcile multiple API responses—a capability that has been openly available since the specification was open sourced in 2015.

GraphQL operations come in two primary types: queries and mutations. Queries are read-only operations that retrieve data without making any changes—similar to GET requests in REST. Mutations, on the other hand, are used to modify server-side data (create, update, or delete)—comparable to POST, PATCH, PUT, and DELETE in REST APIs. This clear separation between reading and writing operations makes GraphQL interactions predictable while maintaining the flexibility to precisely specify what data should be returned after a change is made.

How is GraphQL used at GitHub?

GitHub implemented GraphQL in 2016 to address limitations of RESTful APIs. This adoption has significantly enhanced the developer experience when working with GitHub data. With the GraphQL endpoint, you can retrieve a repository’s issues, its labels, assignees, and comments with a single GraphQL query. Using our REST APIs, this would have otherwise taken several sets of nested calls.

Some GitHub data and operations are only accessible through the GraphQL API (such as discussions, projects, and some enterprise settings), others exclusively through REST APIs (such as querying actions workflows, runners, or logs), and some using either endpoint (such as repositories, issues, pull requests, and user information). GitHub’s GraphQL endpoint is accessible at api.github.com/graphql and you can explore the full schema in our GraphQL documentation or through the interactive GraphQL Explorer.

A key consideration when choosing between the REST API and the GraphQL API is how the rate limits are calculated. As a quick summary for how this is implemented:

Each GraphQL query costs at least one point, but the cost increases based on the complexity of your query (number of nodes requested, connections traversed, etc.). The GraphQL API provides a rateLimit field you can include in your queries to check your current limit status.

For scenarios where you need to fetch related data that would otherwise require multiple REST calls, GraphQL is often more rate limit friendly because:

However, poorly optimized GraphQL queries that request large amounts of nested data could potentially use up your rate limit faster than equivalent REST requests—and quickly run into secondary rate limit issues.

A quick rule of thumb on deciding between which to use:

Sometimes there isn’t a right or wrong answer; so as long as the object exists, try one out!

Why use GitHub CLI for GraphQL?

While many developers start with GitHub’s GraphQL Explorer on the web, curl, or other API querying tools, there’s a more streamlined approach: using built-in GraphQL support in the GitHub CLI. Before diving into the how-to, let’s understand why GitHub CLI is often my go-to tool for GraphQL queries and mutations:

    Authentication is handled automatically: No need to manage personal access tokens manually.Streamlined syntax: Simpler than crafting curl commands.Local development friendly: Run queries and mutations right from your terminal.JSON processing: Built-in options for filtering and formatting results.Pagination support: Ability to work with cursor-based pagination in GraphQL responses.Consistent experience: Same tool you’re likely using for other GitHub tasks.

How to get started with gh api graphql

First, ensure you have GitHub CLI installed and authenticated with gh auth login. The basic syntax for making a GraphQL query with gh api graphql is:

gh api graphql -H X-Github-Next-Global-ID:1 -f query='  query {    viewer {      login      name      bio    }  }'

This simple query returns your GitHub username, the name you have defined in your profile, and your bio. The -f flag defines form variables, with query= being the GraphQL query itself.

Here’s our example output:

{  "data": {    "viewer": {      "login": "joshjohanning",      "name": "Josh Johanning",      "bio": "DevOps Architect | GitHub"    }  }}

Running queries and mutations

Basic query example

Let’s try something more practical—fetching information about a repository. To get started, we’ll use the following query:

gh api graphql -H X-Github-Next-Global-ID:1 -f query='  query($owner:String!, $repo:String!) {    repository(owner:$owner, name:$repo) {      name      description      id      stargazerCount      forkCount      issues(states:OPEN) {        totalCount      }    }  }' -F owner=octocat -F repo=Hello-World

The -F flag sets variable values that are referenced in the query with $variable.

Here’s our example output:

{  "data": {    "repository": {      "name": "Hello-World",      "description": "My first repository on GitHub!",      "id": "R_kgDOABPHjQ",      "stargazerCount": 2894,      "forkCount": 2843,      "issues": {        "totalCount": 1055      }    }  }}
💡 Tip: The -H X-Github-Next-Global-ID:1 parameter sets an HTTP header that instructs GitHub’s GraphQL API to use the new global node ID format rather than the legacy format. While your query will function without this header, including it prevents deprecation warnings when referencing node IDs (such as when passing repository.ID in subsequent operations). GitHub recommends adopting this format for all new integrations to ensure long-term compatibility.

Running mutations

Mutations work similarly. Here’s how to create a new issue:

gh api graphql -H X-Github-Next-Global-ID:1 -f query='  mutation($repositoryId:ID!, $title:String!, $body:String) {    createIssue(input:{repositoryId:$repositoryId, title:$title, body:$body}) {      issue {        url        number        title        body        state      }    }  }' -F repositoryId="R_kgDOABPHjQ" -F title="Creating issue with GraphQL" -F body="Issue body created via GraphQL\!"

Make sure to update the repositoryId parameter with the actual repository’s GraphQL ID (an example of returning a repository’s ID is shown in the basic query above!).

Here’s our example output:

{  "data": {    "createIssue": {      "issue": {        "url": "https://github.com/octocat/Hello-World/issues/3706",        "number": 3706,        "title": "Creating issue with GraphQL",        "body": "Issue body created via GraphQL!",        "state": "OPEN"      }    }  }}

Filtering GraphQL results

GitHub CLI supports JQ-style filtering for extracting specific parts of the response, which is invaluable when you need to parse just the repository names or URLs from a query for use in automation scripts. Here is an example of using the --jq flag:

gh api graphql -H X-Github-Next-Global-ID:1 -f query='  query($owner:String!, $repo:String!) {    repository(owner:$owner, name:$repo) {      issues(first:3, states:OPEN) {        nodes {          number          title          url        }      }    }  }' -F owner=octocat -F repo=Hello-World --jq '.data.repository.issues.nodes[]'

The --jq flag accepts JQ expressions to process JSON output. This query returns just the array of issues, without the surrounding GraphQL response structure.

Here’s our example output:

{  "number": 26,  "title": "test issue",  "url": "https://github.com/octocat/Hello-World/issues/26"}{  "number": 27,  "title": "just for test",  "url": "https://github.com/octocat/Hello-World/issues/27"}{  "number": 28,  "title": "Test",  "url": "https://github.com/octocat/Hello-World/issues/28"}

We could have modified the --jq flag to just return the issue URLs, like so:

gh api graphql -H X-Github-Next-Global-ID:1 -f query='  query($owner:String!, $repo:String!) {    repository(owner:$owner, name:$repo) {      issues(first:3, states:OPEN) {        nodes {          number          title          url        }      }    }  }' -F owner=octocat -F repo=Hello-World --jq '.data.repository.issues.nodes[].url'

Here’s our example output:

https://github.com/octocat/Hello-World/issues/26https://github.com/octocat/Hello-World/issues/27https://github.com/octocat/Hello-World/issues/28

Handling pagination

GitHub’s GraphQL API limits results to a maximum of 100 items per page, which means you’ll need pagination to retrieve larger datasets.

Pagination in GraphQL works by returning a “cursor” with each page of results, which acts as a pointer to where the next set of results should begin. When you request the next page, you provide this cursor to indicate where to start.

The easiest way to handle this pagination in the GitHub CLI is with the --paginate flag, which automatically collects all pages of results for you by managing these cursors behind the scenes. Here’s what that looks like in a query:

gh api graphql --paginate -H X-Github-Next-Global-ID:1 -f query='  query($owner:String!, $repo:String!, $endCursor:String) {    repository(owner:$owner, name:$repo) {      issues(first:100, after:$endCursor, states:OPEN, orderBy:{field:CREATED_AT, direction:DESC}) {        pageInfo {          hasNextPage          endCursor        }        nodes {          number          title          createdAt        }      }    }  }' -F owner=octocat -F repo=Hello-World

The pageInfo object with its hasNextPage and endCursor fields is essential for pagination. When you use the --paginate flag, GitHub CLI automatically uses these fields to fetch all available pages for your query, combining the results into a single response.

Here’s our example output:

{  "data": {    "repository": {      "issues": {        "pageInfo": {          "hasNextPage": true,          "endCursor": "Y3Vyc29yOnYyOpK5MjAyNC0xMi0zMFQxNDo0ODo0NC0wNjowMM6kunD3"        },        "nodes": [          {            "number": 3708,            "title": "Creating issue with GraphQL once more",            "createdAt": "2025-04-02T18:15:11Z",            "author": {              "login": "joshjohanning"            }          },          {            "number": 3707,            "title": "Creating issue with GraphQL again",            "createdAt": "2025-04-02T18:15:02Z",            "author": {              "login": "joshjohanning"            }          },          {            "number": 3706,            "title": "Creating issue with GraphQL",            "createdAt": "2025-04-02T18:14:37Z",            "author": {              "login": "joshjohanning"            }          },          … and so on        ]      }    }  }}

This approach works great for moderate amounts of data, but keep in mind that GitHub’s GraphQL API has rate limits, so extremely large queries might need to implement delays between requests.

💡 Important limitation: The --paginate flag can only handle pagination for a single connection at a time. For example, when listing repository issues as shown above, it can paginate through all issues, but cannot simultaneously paginate through each issue’s comments. For nested pagination, you’ll need to implement custom logic.

Building complex scripts: Chaining GraphQL queries together

When working with GitHub’s GraphQL API, you often need to connect multiple queries to accomplish a complex task. Let’s look at how to chain GraphQL calls together using the GitHub CLI:

ISSUE_ID=$(gh api graphql -H X-Github-Next-Global-ID:1 -f query='  query($owner: String!, $repo: String!, $issue_number: Int!) {    repository(owner: $owner, name: $repo) {      issue(number: $issue_number) {        id      }    }  }' -F owner=joshjohanning -F repo=graphql-fun -F issue_number=1 --jq '.data.repository.issue.id') gh api graphql -H GraphQL-Features:sub_issues -H X-Github-Next-Global-ID:1 -f query='query($issueId: ID!) {  node(id: $issueId) {    ... on Issue {      subIssuesSummary {        total        completed        percentCompleted      }    }  }}' -F issueId="$ISSUE_ID"

Here’s what this shell script is doing:

    The first query captures an issue’s ID using the repository name and issue numberThe --jq flag extracts just the ID value and stores it in a variableThe second query passes this ID to retrieve a summary of sub-issues

Here’s our example output:

{  "data": {    "node": {      "subIssuesSummary": {        "total": 3,        "completed": 1,        "percentCompleted": 33      }    }  }}

Take this with you

The gh api graphql command provides a convenient way to interact with GitHub’s GraphQL API directly from your terminal. It eliminates the need for token management, simplifies query syntax and formatting, and handles basic pagination that would otherwise be complex to implement. Whether you’re running complex queries or simple mutations, this approach offers a streamlined developer experience.

Next time you need to interact with GitHub’s GraphQL API, skip the GraphQL Explorer on the web and try the GitHub CLI approach. It might just become your preferred method for working with GitHub’s powerful GraphQL API capabilities.

The post Exploring GitHub CLI: How to interact with GitHub’s GraphQL API endpoint appeared first on The GitHub Blog.

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

GitHub GraphQL CLI API
相关文章