「CI判定スクリプトなんて、GitHub の情報をちょっと取ってくるだけの簡単な処理だろう」——そう思ってサクッと実装を始めたら、認証・エラー処理・ページネーション・レート制限という沼が口を開けてた、みたいなこと、ありませんか?
gh CLI と REST API を直に叩く方法、どちらも実装可能です。でも設計段階で選択を誤ると、後からページネーションが必要になったり、本番でレート制限に引っかかったりしてえらい目に遭います。
実装段階で両方試して判明した、実際の落とし穴と選び方のポイントをまとめました。
前提条件
以下の例を実行する際は、次を参考にしてください:
- gh CLI を使う場合 —
ghがインストール済みで、gh auth loginで認証済みであることを想定しています - REST API(curl)を使う場合 — プライベートリポにアクセスする際は
export GH_TOKEN=your_github_tokenでトークンを設定してください
機能比較表
| 観点 | gh CLI | REST API(curl等) |
|---|---|---|
| 認証方式 | ~/.config/gh、keyring、env 変数など複合対応 | env 変数(GH_TOKEN等)のみ |
| プライベートリポ対応 | ✓ keyring から認証情報を読み込める | ✓ env 設定時のみ(落とし穴あり) |
| エラー応答の意味 | 401 / 403 / 404 を区別可能 | 認証なしでは 404(「リソースなし」と「認証エラー」が区別不可) |
| ページネーション | 自動処理(--paginate フラグ)、複数ページも一度に取得可 | 手動実装(Link ヘッダーの解析等) |
| レート制限 | 認証時:5000 req/h、未認証時:60 req/h | 同上 |
| レート制限の判定 | gh api rate_limit で残数を確認可能 | 手動で HTTP ヘッダ解析(X-RateLimit-*) |
| スクリプト内呼び出し | CI/制限環境では設定ファイル読み込み時に注意が必要(例:Docker、GitHub Actions サンドボックス) | env 変数のみで動作、設定ファイル読み込みに依存しない |
| 学習コスト | 低い(CLI ヘルプが充実) | 中~高い(HTTP 仕様知識・JSON パース必要) |
実例から学んだ落とし穴
1. 認証エラーが「リソース不在」に偽装する問題
REST API の場合:
プライベートリポジトリの PR 情報を取得しようとすると、認証情報がないと HTTP 404 で返ってきます。
curl -s https://api.github.com/repos/owner/private-repo/pulls/123
# => HTTP 404: Not Found
問題: 「この PR が存在しない」のか「認証がない」のか、レスポンスコードだけでは区別できません(GitHub は仕様上、権限のないリソースの存在を秘匿する)。つまり、本当は PR があって、アクセス権がないだけなのに、通常の 404 と区別がつかない。これ、スクリプトのエラーハンドリングを完全に台無しにします。
gh CLI の場合:
gh api repos/owner/private-repo/pulls/123 --repo owner/private-repo
# 認証が成功するか、明確なエラーメッセージで失敗する
gh は ~/.config/gh や keyring から認証情報を自動的に探索して使用するため、こうした曖昧さが生まれません。
教訓: REST API でプライベートリポに対応するなら、常に環境変数の存在チェックと認証状態の事前確認を入れるべき。
2. ページネーション時のデータ欠落(サイレント)
REST API で複数ページのデータを取得する場合:
GitHub API は 1 レスポンスに最大 100 件までしか含めません。例えば check-runs 取得で 150 個のチェックがあると:
curl -s "https://api.github.com/commits/{sha}/check-runs" \
-H "Accept: application/vnd.github.v3+json"
# => { "total_count": 150, "check_runs": [ /* 100 件のみ */ ] }
問題: total_count は 150 なのに、実際には最初の 100 件のみ返ってきます。エラーが出たわけではない、警告も出ない。ただ、そこに次ページが存在していることすら気づかずに、2 ページ目のデータが完全に失われる。デバッグに苦しむことになります(「あれ、このチェック実行されてるはずなのに取得できない」状態)。Link ヘッダーで次ページの URL を確認し、明示的に追加リクエストが必要。
gh CLI の場合:
gh api repos/owner/repo/commits/{sha}/check-runs \
--paginate \
--jq '.check_runs[]'
--paginate フラグで自動的に全ページを取得。100 件単位でループを回す複雑さがゼロです(バグの温床を最初から排除)。
教訣: REST API を使う場合、ページネーション処理が本当に必要な仕様か確認し、手動実装ならテストに全ページ検証を必須にしましょう。「今は 50 件だから大丈夫」という判断は、3 ヶ月後のデータ増加で悲劇になります。
3. レート制限が「予告なく」パイプラインを止める
REST API のレート制限対応:
未認証で 60 req/hour という厳しい上限があります。1 ステップで 3 回 API 呼び出しする処理(PR メタ → head SHA → check-runs)を 10 回ループするだけで、上限を超える可能性も。
# 1 invocation で最大 210 回のリクエスト(3 call × polling 7 回)
# 未認証時は 60 req/hour なので、1 回のパイプラン実行で枯渇
対策として、各レスポンスの X-RateLimit-Remaining を確認して状態を把握する必要がありますが、手動で HTTP ヘッダを解析してリトライロジックを書くのは煩雑。実装を忘れると、本番で突然「API の応答がなくなった。何故?」という悪夢を見ることになります。
gh CLI の場合:
gh api repos/owner/repo/pulls/123/reviews --paginate
# 残り回数は `gh api rate_limit` で確認できる
認証を設定すれば上限が 5000 req/hour に上がり、レート制限に達すること自体がほぼなくなります。
教訣: CI で REST API を使う場合は、環境変数で認証トークンを供給し、本番環境では必ず限度テストを実施しましょう。
選択ツリー
gh CLI を選ぶべき場合
- プライベートリポジトリ にアクセスする
- 認証の複雑さを最小化したい → keyring 自動検出(面倒な env 変数チェックを減らせる)
- 複数ページのデータ取得 が必要(手動ループの実装を避けたい)
- レート制限の自動管理 を期待したい(本番で夜中に起こされるのを避ける)
- CI ステップ数が多く、呼び出し数が不明確 な場合(あとから「あ、ページネーション必要だ」で修正するコストを避ける)
REST API(curl等)を選ぶべき場合
- サードパーティのスクリプト実行環境で
ghがインストール不可 な場合 - 環境変数のみで認証を完結させたい(CI/制限環境でローカル設定ファイルへのアクセスが制限される場合など)
- レスポンス JSON を細かく解析・加工する ので、curl で標準出力を直に jq に渡したい(パイプの自由度が欲しい)
- CI ステップ内の他ツール群と統一 したい(「全部 curl で揃えるぞ」という決意がある場合)
実装時のチェックリスト
CI 判定スクリプトをデプロイする前に、以下を確認してください:
- 認証方式の明確化 — 環境変数名・keyring パス・fallback 挙動を document
- プライベートリポ対応テスト — 本来ならアクセスでき、かつアクセスできないリソースで 404 vs 403 を区別
- ページネーション検証 — 100 件超のテストデータで全件取得を確認
- レート制限テスト — 本番想定の呼び出し数で上限に達しないか確認、fallback 処理を組み込む
- エラーハンドリング — タイムアウト・503 などの transient エラーと 404 の区別、リトライ戦略
- ログ出力 — 本番問題時に追跡可能な形で API 呼び出しを記録(ただし token は隠す)
まとめ
gh CLI と REST API のどちらが「正解」というわけではなく、CI 環境・認証戦略・ページネーション要件で判断 が必要です。
快適さを取るなら gh CLI、制約下での自由度を取るなら REST APIという選別が目安。ただし、実装後に「あ、ページネーション必要だ」「レート制限に引っかかった」という発見は、修正コストが莫大です。いったん REST API で実装しても、後からページネーションが必要になったり、認証に悩まされたりすることが多いため、設計段階でここまでの比較表を一度確認しておくことをおすすめします。
「デプロイしてみればわかる」というアプローチは、本番パイプラインが「あ、API が返ってこない」という悪夢を見るまでの時間と比例します。どちらを選んだにせよ、本番前に「実際に困る条件」(複数ページ、レート制限、プライベートリポ)でテストすることが最も大事です。
AIエージェントにCI判定スクリプトを書かせる機会が増えている分、こうした認証・ページネーションの落とし穴もエージェント任せの実装にそのまま紛れ込みやすい。設計段階からの見積もりや自動化ワークフロー全体の相談ならAI実装支援も選択肢の一つになる。


