GitHub REST API活用パターン

何ができるか

GitHub REST API は、Web画面でできることのほとんどをプログラムから行えるようにした [[REST API]] です。

curl -H "Authorization: Bearer $TOKEN" \
     -H "Accept: application/vnd.github+json" \
     "https://api.github.com/repos/owner/repo/commits?per_page=100"

実務でよく使う用途は次の3つです。

  • 状態の収集 — コミット・PR・Issue を集めて集計する(活動量の可視化、棚卸し)
  • 自動化 — Issue の起票、ラベル付け、PRの作成やマージ
  • 監視 — 一定期間コミットが無いリポジトリの検出など、定期的な確認

ページングが最初の壁

一覧を返すエンドポイントは、既定で30件しか返しません。per_page=100 にしても100件が上限です。

残りがあるかどうかは、レスポンスの Link ヘッダを見て判断します。 配列の長さが per_page と同じかどうかで判定する実装は、ちょうど割り切れたときに1ページ読み落とします。

Link: <https://api.github.com/...&page=2>; rel="next", <...&page=9>; rel="last"

rel="next" が無くなるまで辿るのが正しい実装です。「取れた件数が想定より少ない」という不具合の多くは、ページングの打ち切りが原因です。

レートリミット

認証上限
未認証60 リクエスト/時
個人アクセストークン5,000 リクエスト/時
GitHub Appインストール数に応じて増える

さらに REST と GraphQL は別勘定で、検索エンドポイントにはより厳しい別枠があります。

残量はレスポンスヘッダで分かります。

x-ratelimit-remaining: 4832
x-ratelimit-reset: 1755500000     # UNIX時刻

枯渇したときに短い間隔で再試行するのは無駄です。 リセット時刻まで待つのが正しい対処になります。[[レートリミット]] の一般論と同じく、上限に当たってからではなく当たらない設計にするのが本題です。

  • 一覧の取得は per_page=100 で回数を減らす
  • 変更が無ければ再取得しない(If-None-Match で 304 が返ると消費されません)
  • 差分だけを取る(since パラメータなど)

イベントを取るか、通知を受けるか

「あるリポジトリで何かが起きたら反応したい」という要件には2つの方法があります。

ポーリング(REST)[[Webhook]]
仕組み定期的に問い合わせる起きたときに送られてくる
遅延間隔ぶん遅れるほぼ即時
レート消費するしない
受け口不要公開URLが要る

イベント一覧のAPIは保持期間と件数に上限があり、古いものは取れません。監視間隔がその範囲を超えると取りこぼします。常時受け取りたいなら Webhook、定期的な棚卸しなら REST、という使い分けになります。

実装の作法

  • Accept ヘッダで版を明示する — 応答の形が変わる更新に備えます([[APIバージョニング]])
  • 公式クライアントを使う — octokit などはページングとリトライを内蔵しています。自作すると上の落とし穴を全部踏みます
  • トークンの権限を絞る — 読み取りだけで足りる用途に書き込み権限を与えません
  • [[CI/CD]] のワークフローから呼ぶときは既定のトークンを使う — ワークフローに渡されるトークンは、そのリポジトリに限定されています

関連技術とのつながり

  • [[REST API]] — 設計の土台。ページングと認証の作法は他のAPIにも通じる
  • [[レートリミット]] — 上限に当たらない設計が本題
  • [[Webhook]] — 即時性が要るときの受け取り方
  • [[CI/CD]] — ワークフロー内からAPIを呼び、収集や自動化を定期実行する
  • [[APIバージョニング]] — 応答の形が変わる更新への備え
  • [[GitHub App]] — 個人トークンに頼らず、アプリ名義の短命トークンで API を呼ぶ仕組み
Q: 一覧APIで全件を取得する正しい判定方法はどれ?
- [ ] 返ってきた配列の長さが `per_page` より少なければ最後と判断する
- [x] レスポンスの `Link` ヘッダに `rel="next"` が無くなるまで辿る
- [ ] 常に10ページまで取得する
解説: 件数がちょうど割り切れたときに1ページ読み落とします。件数での判定は避けます。

Q: レートリミットが枯渇したときの正しい対処はどれ?
- [ ] 30秒間隔で再試行を続ける
- [x] `x-ratelimit-reset` の時刻まで待つ
- [ ] 未認証のリクエストに切り替える
解説: 未認証は60/時とさらに厳しくなります。短い間隔の再試行は無駄です。

Q: リポジトリの変化へ即時に反応したいときに向くのはどれ?
- [ ] イベント一覧APIを短い間隔でポーリングする
- [x] Webhookで通知を受け取る
- [ ] 検索APIを使う
解説: イベント一覧は保持期間と件数に上限があり、間隔が広いと取りこぼします。Webhookはレートも消費しません。