第 11 章

API 与集成

REST、GraphQL、webhook——把 GitHub 与任何外部系统打通

gh 是别人的封装,API 是你自己造工具的原料

gh 不够用了

你想做的事,没有现成命令

想做机器人

新开 issue 时自动打标签、有人 star 时发条通知、每天统计贡献图。gh 没有这些功能。

想接外部系统

把 PR 状态同步到飞书群、issue 关闭时更新 Notion 看板。GitHub 和这些工具之间没有现成桥梁。

想自定义查询

「过去一年谁提交最多」「哪些 issue 超过 30 天没动」——网页搜不出来,gh 也不好查。需要原始数据自己算。

本章打开 GitHub 的底层:REST/GraphQL API 让你读写任意仓库数据,webhook 让 GitHub 主动通知你事件,GitHub App 让你构建正式集成。
这是 gh 背后的真身,也是你造工具的原料。

开始之前

适合谁

  • 会基本编程(Python/JS),想自动化 GitHub
  • 好奇 gh 背后是怎么工作的
  • 想做个小机器人或集成

你将学会

  • 用 REST API 查询和操作仓库
  • 用 GraphQL 精准取数据
  • 理解 token scope 和认证
  • 区分 OAuth App 和 GitHub App
  • 用 webhook 响应事件

本章暂不覆盖

  • GitHub Enterprise API
  • 复杂机器人框架(Probot 深度)
  • OAuth 完整流程实现

两套 API

GitHub 提供 REST 和 GraphQL 两套接口

REST APIGraphQL API
风格 资源导向 URL 查询语言,按需取字段
易学 简单直观 有学习曲线
查询效率 可能多次请求 一次取所需,省请求
适合 简单操作、curl 实测 复杂关联查询
新手从 REST 入手。它是 URL + HTTP 方法,curl 一行就能测。GraphQL 更强大但门槛高,等你熟了 REST 再进阶。

REST 基础

每个资源有自己的 URL,用 HTTP 方法操作

GET    /repos/用户名/仓库名          # 获取仓库信息
POST   /repos/用户名/仓库名/issues    # 创建 issue
PATCH  /repos/用户名/仓库名/issues/12 # 修改 issue 12(改标题/状态等)
GET    /repos/用户名/仓库名/issues/12 # 获取单条 issue
注意:issue 没有 DELETE 方法。GitHub 不允许删除 issue,只能 PATCH 把状态改成 closed 来关闭。

基础 URL

https://api.github.com

所有请求以此为前缀。

HTTP 方法对应操作

  • GET:读取
  • POST:创建
  • PATCH/PUT:更新
  • DELETE:删除

第一次调用

用 curl 查询公开仓库信息,连认证都不用

$ curl https://api.github.com/repos/octocat/Hello-World

{
  "id": 1296269,
  "name": "Hello-World",
  "full_name": "octocat/Hello-World",
  "owner": {
    "login": "octocat",
    ...
  },
  "stargazers_count": 1000+,
  "open_issues_count": 100,
  ...
}
读取公开数据不需要认证。但有速率限制:未认证每小时 60 次请求。认证后提升到 5000 次/小时——所以实际开发都要带 token。

带认证的调用

用 PAT 认证后,能读私有仓库、能写操作

# 带 token 的请求(注意 Authorization 头)
$ curl -H "Authorization: Bearer 你的TOKEN" \
       https://api.github.com/user

# 查看当前认证用户信息
{
  "login": "你的用户名",
  "name": "...",
  "public_repos": 10,
  ...
}

认证方式

  • Authorization: Bearer TOKEN(推荐)
  • URL 参数 ?access_token=TOKEN(已废弃,不安全)
  • 建议用环境变量存 token,别写死
别在命令行明文写 token。会被 shell 历史记录。用 $GITHUB_TOKEN 环境变量,curl 里写 -H "Authorization: Bearer $GITHUB_TOKEN"。

用 API 创建 issue

POST 请求带 JSON body——能写就能自动化

$ curl -X POST \
    -H "Authorization: Bearer $TOKEN" \
    -H "Accept: application/vnd.github+json" \
    https://api.github.com/repos/你/仓库/issues \
    -d '{"title":"通过 API 创建","body":"测试","labels":["bug"]}'

# 返回创建好的 issue(含编号、URL 等)
这就是 gh issue create 背后的真相。gh 帮你封装了 HTTP 请求、JSON 构造、错误处理。
直接调 API 更灵活——你可以批量创建、从外部数据源导入、和别的系统联动。

速率限制

API 有调用频率上限,防止滥用

认证状态每小时限制
未认证 60 次
带 token(普通用户) 5000 次
GitHub App 更高(按安装算)

查看剩余额度

$ curl -H "Authorization: Bearer $TOKEN" \
    https://api.github.com/rate_limit

返回 remaining / reset 等字段。

脚本里记得处理 403(超限)——sleep 等 reset 时间再重试。

分页

返回多的接口会分页,默认一页 30 条

# 指定每页数量和页码
$ curl -H "Authorization: Bearer $TOKEN" \
    "https://api.github.com/repos/你/仓库/issues?per_page=100&page=1"

# Link 响应头告诉你有没有下一页
Link: <...&page=2>; rel="next", <...&page=5>; rel="last"
per_page 最大 100。想取全部就循环 page=1,2,3... 直到某页为空或没 next 链接。这是写 GitHub 数据采集脚本的基本套路。

GraphQL 登场

用一条查询精确取你想要的字段——不过度、不不足

$ curl -X POST -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"query":"{ viewer { login bio repositories(privacy: PUBLIC) { totalCount } } }"}' \
    https://api.github.com/graphql

{
  "data": {
    "viewer": {
      "login": "你的用户名",
      "bio": "...",
      "repositories": {
        "totalCount": 10
      }
    }
  }
}
对比 REST:REST 取整个 user 对象(你只用了 3 个字段);GraphQL 只返回你声明的字段。
更大的优势是关联数据一次取:「我的前 10 个仓库的最近 5 个 PR」——REST 要 N+1 次请求,GraphQL 一次搞定。

GraphQL 实战

一次查询取多层数据——REST 要发很多请求

query {
  viewer {
    login
    repositories(first: 5, orderBy: {field: UPDATED_AT}) {
      nodes {
        name
        issues(states: [OPEN], first: 3) {
          totalCount
          nodes { number title }
        }
      }
    }
  }
}

这条查询做了什么

取当前用户 → 最近更新的 5 个仓库 → 每个仓库前 3 个 open issue(含编号标题)和 issue 总数。

用 REST 至少 6 次请求,GraphQL 一次返回。

适合仪表盘、统计页面这类需要聚合数据的场景。

GraphiQL 探索器

可视化写 GraphQL 的官方工具——带自动补全

在哪

docs.github.com/graphql → 点「GitHub GraphQL Explorer」→ 用 GitHub 登录。

能做什么

  • 左侧写查询,右侧实时看结果
  • 有字段自动补全和文档
  • 报错提示明确(哪个字段拼错)
  • 写好后复制到代码里
写 GraphQL 别凭记忆。用 Explorer 边查文档边写,比硬记 schema 高效得多。复杂的查询先在 Explorer 跑通再进代码。

token 权限

scope 决定你的 token 能调哪些 API

scope能做什么
(无 scope) 读公开数据、读自己信息
repo 读写仓库(公开+私有)
read:user 读用户资料
user:email 读邮箱
workflow 改 GitHub Actions workflow

调 API 报 403 时,先检查 token 有没有对应 scope。第 10 章讲过的最小权限原则这里同样适用。

两种 App

OAuth App 和 GitHub App——给第三方做集成时的身份

OAuth AppGitHub App
权限粒度 用户级(拿用户全部权限) 细粒度(按仓库、按操作)
认证对象 代表用户 独立身份
webhook 需手动配 原生支持
适合 简单工具 正式集成、机器人
新项目优先 GitHub App。它更安全(细粒度权限)、更现代、GitHub 官方主推。OAuth App 是老方案,简单但权限过粗。

octokit SDK

GitHub 官方多语言 SDK,不用手写 HTTP

// JavaScript: @octokit/rest
import { Octokit } from "@octokit/rest";

const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });

// 列出你的仓库
const { data } = await octokit.rest.repos.listForAuthenticatedUser();
console.log(data.map(r => r.full_name));

// 创建 issue
await octokit.rest.issues.create({
  owner: '你', repo: '项目',
  title: '通过 SDK 创建',
});

各语言 SDK

  • JS/TS:@octokit/rest、@octokit/graphql
  • Python:PyGithub(社区)、githubkit
  • Go:google/go-github

Python 实战

用 PyGithub 统计仓库贡献者

from github import Github
import os

g = Github(os.environ["GITHUB_TOKEN"])
repo = g.get_repo("你/项目")

# 统计每个贡献者的 commit 数
contributors = repo.get_contributors()
for c in contributors[:5]:
    print(f"{c.login}: {c.contributions} 次提交")

# 列出超过 30 天没动的 issue
import datetime
since = datetime.datetime.now() - datetime.timedelta(days=30)
old_issues = [i for i in repo.get_issues(state="open")
              if i.updated_at < since]
print(f"有 {len(old_issues)} 个 issue 超过 30 天没更新")
这种统计 gh 做不到。API + 编程语言让你自由处理数据——做报告、生成仪表盘、自动化维护任务。
跑一遍发现没动过的 issue,是开源项目维护的常见脚本。

webhook

GitHub 主动 POST 通知你「发生了事件」——反向 API

图:webhook 工作原理
API 是你主动问 GitHub,webhook 是 GitHub 主动告诉你。做实时响应(新 issue 立刻通知、PR 被合并自动部署)必须用 webhook。轮询 API 又慢又浪费额度。

配置 webhook

告诉 GitHub「发生 X 事件时,POST 到这个 URL」

在哪配

仓库 → Settings → Webhooks → Add webhook。

关键设置

  • Payload URL:你的服务器接收地址
  • Content type:选 application/json
  • Secret:用于验证请求确实来自 GitHub
  • Events:勾选要监听的事件(push、issues、pull_request 等)
必须验证 secret。任何能访问你 URL 的人都能伪造 POST。GitHub 用你设的 secret 签名,你的服务器要校验签名才处理——否则会被骗。

webhook 负载

GitHub POST 过来的 JSON——含事件全部信息

// issues 事件的 payload(节选)
{
  "action": "opened",
  "issue": {
    "number": 42,
    "title": "登录失灵",
    "body": "点击登录没反应...",
    "user": { "login": "reporter" },
    "labels": []
  },
  "repository": {
    "full_name": "你/项目"
  }
}

怎么用

服务器收到后,根据 action 和内容做处理:

  • 新 issue 标题含「bug」→ 自动加 bug label
  • 新 PR → 发飞书通知
  • push 到 main → 触发部署

实战:自动打标签

新 issue 根据标题自动分类——webhook + API 组合

# Flask 接收 webhook
from flask import Flask, request
app = Flask(__name__)

@app.route("/webhook", methods=["POST"])
def webhook():
    data = request.json
    if data["action"] == "opened":
        title = data["issue"]["title"].lower()
        labels = []
        if "bug" in title or "失灵" in title:
            labels.append("bug")
        if "文档" in title or "doc" in title:
            labels.append("documentation")
        if labels:
            repo = data["repository"]["full_name"]
            num = data["issue"]["number"]
            # 调 API 加 label
            add_labels(repo, num, labels)
    return "", 200

三种自动化

什么时候用 Actions、webhook、外部脚本调 API

方案适合举例
GitHub Actions 仓库内的、事件触发的 push 时测试、定时检查
webhook + 自建服务 跨系统集成、实时 同步到飞书、通知 IM
脚本调 API 一次性、批处理 统计贡献、批量改 label

很多场景三者都能做。优先级:能用 Actions 就用 Actions(免服务器),要跨系统才上 webhook。

Probot 框架

基于 Node.js 的 GitHub App 框架——少写样板代码

它封装了什么

  • webhook 接收和签名验证
  • GitHub App 认证(自动拿 token)
  • API 调用(octokit 集成)
  • 常用模板(欢迎新贡献者、自动关闭陈旧 PR)

适合

想正经做一个机器人/集成。比起自己从零写 webhook 服务,Probot 省去重复劳动。
现成应用市场:probot.github.io/apps。

这是进阶选项。本章教的 API + webhook 基础是 Probot 的前提。先用 curl / Python 跑通小例子,再考虑用框架。

动手试一试

用 API 写一个自己的小工具

你的任务

任务:用 API 做一个能查询并展示你仓库数据的脚本。

要求(任选一个):

  1. 统计你所有仓库的 star 总数和按语言分布
  2. 列出某个仓库最近 10 个 open issue 的标题
  3. 用 GraphQL 一次查出你最近 5 个仓库的 PR 数量

通用要求:

  • token 从环境变量读,不写死
  • 处理分页(如果需要)
  • 输出格式化的结果

提示

  1. 先用 curl 在命令行验证查询对不对,再写代码
  2. 遇到 403 检查 token scope 或是否超限
第 11 章

小结

你已经能读写 GitHub 的任意数据,并让它主动通知你

本章要点

  • REST API 简单直观,GraphQL 高效精准
  • PAT 认证 + scope 控制权限
  • GitHub App(细粒度)优于 OAuth App(粗粒度)
  • webhook 让 GitHub 主动通知,适合实时集成
  • octokit SDK 各语言都有,省去手写 HTTP
下一步:第 12 章 GitHub AI 与云端 —— Copilot 辅助写代码、Codespaces 云端开发、Gist 分享片段,跟上 2026 年的实际工作方式。