Skip to main content
ドキュメントには� �繁に更新が� えられ、その都度公開されています。本ページの翻訳はま� 未完成な部分があることをご了承く� さい。最新の情� �については、英語のドキュメンテーションをご参照く� さい。本ページの翻訳に問題がある� �合はこちらまでご連絡く� さい。

このバージョンの GitHub Enterprise はこの日付をもって終了となりました: 2022-06-03. 重大なセキュリティの問題に対してであっても、パッチリリースは作成されません。 パフォーマンスの向上、セキュリティの改善、新機能のためには、最新バージョンのGitHub Enterpriseにアップグレードしてく� さい。 アップグレードに関する支援については、GitHub Enterprise supportに連絡してく� さい。

インテグレーターのためのベストプラクティス

信� �性を持ってGitHub Enterprise Server APIとやりとりをするアプリケーションを構築し、ユーザに最善の体験を提供してく� さい。

GitHubプラットフォー� との統合に興味はありますか。 同じことを思っている仲間がいますよ。 このガイドは、ユーザに最高のエクスペリエンスを提供し、かつAPIと確実にやり取りするアプリを構築するために役立ちます。

GitHubから配信されるペイロードの機密を確保する

GitHubから送信されたペイロードの機密を確保することは非常に重要です。 ペイロードでパスワードなどの個人情� �が送信されることはないものの、いかなる情� �であれ漏洩することは好ましくありません。 コミッターのメールアドレスやプライベートリポジトリの名前などは、機密性が求められる� �合があります。

いくつかのステップを踏むことで、GitHubから配信されるペイロードを安全に受信できます。

  1. 受信サーバーは必ずHTTPS接続にしてく� さい。 デフォルトでは、GitHubはペイロードを配信する際にSSL証明書を検証します。
  2. ペイロードがGitHubから配信されていることを確実に保証するため、シークレットトークンを提供します。 シークレットトークンを強制することにより、サーバーが受信するあらゆるデータが確実にGitHubから来ていることを保証できます。 サービスのユーザごとに異なるシークレットトークンを提供するのが理想的です。 そうすれば、1つのトークンが侵害されても、他のユーザは影響を受けません。

同期作業より非同期作業を優先する

GitHubは、webhookペイロードを受信後30秒以内にインテグレーションが応答することを求めています。 サービスの応答時間がそれ以上になると、GitHubは接続を中止し、ペイロードは失われます。

サービスの完了時間を予測することは不可能なので、「実際の作業」のすべてはバックグラウンドジョブで実行すべきです。 バックグラウンドジョブのキューや処理を扱えるライブラリには、Resque (Ruby用)、RQ (Python用)、RabbitMQなどがあります。

バックグラウンドジョブが実行中でも、GitHubはサーバが30秒以内で応答することを求めていることに注意してく� さい。 サーバは何らかの応答を送信することにより、ペイロードの受信を確認する必要があります。 サービスがペイロードについての確認を可能な限り速やかに行うことは非常に重要です。そうすることにより、サーバがリクエストを継続するかどうか正確に� �告できます。

GitHubへの応答時に適切なHTTPステータスコードを使用する

各webhookには、デプロイメントが成功したかどうかを列挙する独自の「最近のデリバリ」セクションがあります。

[Recent Deliveries] ビュー

ユーザへの通知には、適切なHTTPステータスコードを使用するべきです。 (デフォルトでないブランチから配信されたペイロードなど) 処理できないペイロードの受信を知らせるため、201202といったコードを使用できます。 500のエラーコードは、致命的な障害に用いましょう。

ユーザにできる� け多くの情� �を提供する

ユーザはGitHubに返信したサーバーの応答を調べることができます。 メッセージは明確で参考になるものとしてく� さい。

ペイロードレスポンスの表示

APIが送信するあらゆるAPIに従う

GitHubは、リダイレクトのステータスコードを提供することにより、リソースがいつ移動したかを明示します。 このリダイレクトに従ってく� さい。 すべてのリダイレクト応答は、Locationヘッダに、移動する新しいURIを設定します。 リダイレクトを受け取ったら、削除する可能性がある非推奨のパスをリクエストしている� �合、新しいURIにしたがってコードを更新するようお勧めします。

アプリケーションをリダイレクトに従うよう設計する際に気をつけるべきHTTPステータスコードのリストをご用意しています。

手動でURLをパースしない

APIレスポンスには、URLの形でデータが含まれていることがよくあります。 たとえば、リポジトリをリクエストするときは、リポジトリをクローンするために使用できるURLの付いたclone_urlというキーを送信します。

アプリケーションの安定性を保つため、このデータをパースしようとしたり、先のURLの形式を予想して作成しようとしたりしないでく� さい。 URLを変更した� �合、アプリケーションが壊れるおそれがあります。

たとえば、ページネーションされた結果を扱う際は、末尾に?page=<number>を付けてURLを構築したいと思うことがあります。 この誘惑に� けてはなりません。 ページネーションに関するガイドには、ページネーションされた結果を安全に扱うための信� �できるヒントがいくつか掲載されています。

イベントの処理前にイベントのタイプとアクションを確認する

webhookのイベントタイプは複数あり、各イベントは複数のアクションを持つことができます。 GitHubの機能セットが増えるにつれて、新しいイベントタイプを追� したり、既存のイベントタイプに新しいアクションを追� したりすることがあります。 Webhookの処理を行う前に、イベントのタイプとアクションをアプリケーションが明示的に確認するようにしてく� さい。 X-GitHub-Eventリクエストヘッダは、受信したイベントの種類を知り、それを適切に処理するために利用できます。 同様に、ペイロードにはトップレベルのactionキーがあり、関連オブジェクトに対して実行されたアクションを知るために利用できます。

たとえば、GitHubのwebhookを [Send me everything] に設定している� �合、新しいイベントのタイプやアクションが追� されると、アプリケーションはそれらの受信を開始します。 ですから、あらゆる類のcatch-all else構文は使用をお勧めしません。 たとえば、次のコード例をご覧く� さい。

# Recommended: explicitly check each event type
def receive
  event_type = request.headers["X-GitHub-Event"]
  payload    = JSON.parse(request.body)

  case event_type
  when "repository"
    process_repository(payload)
  when "issues"
    process_issue(payload)
  when "pull_request"
    process_pull_requests(payload)
  else
    puts "Oooh, something new from GitHub: #{event_type}"
  end
end

このコード例では、repositoryまたはissuesイベントを受信すると、process_repositoryおよびprocess_issuesメソッドが正しく呼び出されます。 しかし、他のイベントタイプでは、process_pull_requestsが呼び出されることになります。 新しいイベントタイプが追� されると、誤った動作を引き起こすことになり、新たなイベントタイプはpull_requestイベントと同じ方法で処理されることになるでしょう。

代わりに、イベントのタイプを明示的に確認し、それに応じて処理するようお勧めします。 次のコード例では、pull_requestイベントを明示的に確認し、else節は新しいイベントタイプを受信したことを単に記録しています。

# Recommended: explicitly check each event type
def receive
  event_type = request.headers["X-GitHub-Event"]
  payload    = JSON.parse(request.body)

  case event_type
  when "repository"
    process_repository(payload)
  when "issues"
    process_issue(payload)
  when "pull_request"
    process_pull_requests(payload)
  else
    puts "Oooh, something new from GitHub: #{event_type}"
  end
end

各イベントも複数のアクションを持つことができるため、アクションも同様に確認することをお勧めします。 たとえば、IssuesEventではいくつかのアクションが可能です。 例としては、Issueが作成されたときのopened、Issueがクローズしたときのclosed、Issueが誰かに割り当てられたときのassignedが挙げられます。

イベントタイプを追� するのと同じように、既存のイベントに新しいアクションを追� できます。 ですから、イベントのアクションを確認する� �合も>あらゆる類のcatch-all else構文は使用をお勧めしません。 代わりに、イベントタイプの例と同様、イベントのアクションも明示的に確認するようお勧めします。 この例は、上記のイベントタイプで示したものと非常に似通ったものです。

# Recommended: explicitly check each action
def process_issue(payload)
  case payload["action"]
  when "opened"
    process_issue_opened(payload)
  when "assigned"
    process_issue_assigned(payload)
  when "closed"
    process_issue_closed(payload)
  else
    puts "Oooh, something new from GitHub: #{payload["action"]}"
  end
end

この例では、始めにclosedアクションを確認してから、process_closedメソッドを呼びます。 未確認のアクションは、今後の参考のために記録されます。

APIエラーの扱い

あなたのコードが決してバグを発生させなかったとしても、APIにアクセスしようとするとき立て続けにエラーが発生することがるかもしれません。

繰り返し表示される4xx5xxのステータスコードを無視せずに、APIと正しくやり取りしていることを確認してく� さい。 たとえば、エンドポイントが文字列を要求しているのに数値を渡している� �合、5xx検証エラーが発生し、呼び出しは成功しません。 同様に、許可されていないエンドポイントまたはは存在しないエンドポイントにアクセスしようとすると、4xxエラーが発生します。

繰り返し発生する検証エラーを意図的に無視すると、不正利用によりアプリケーションが停止されることがあります。