{"meta":{"title":"CIサーバーの構築","intro":"Status APIで独自のCIシステムを構築しましょう。","product":"REST API","breadcrumbs":[{"href":"/ja/rest","title":"REST API"},{"href":"/ja/rest/guides","title":"ガイド"},{"href":"/ja/rest/guides/building-a-ci-server","title":"CIサーバーの構築"}],"documentType":"article"},"body":"# CIサーバーの構築\n\nStatus APIで独自のCIシステムを構築しましょう。\n\nREST API を使用してコミットをテスト サービスと結び付け、作成したすべてのプッシュを GitHub プル要求でテストして表すことができます。 関連するエンドポイントの詳細については、「[コミットのステータス用の REST API エンドポイント](/ja/rest/commits/statuses)」を参照してください。\n\nこのガイドでは、そのAPIを使って、利用可能なセットアップを示します。\nこのシナリオでは、以下を行います。\n\n* プルリクエストが作成されたとき、CIスイートを実行します (CIステータスを「保留中」に設定します)。\n* CIが終了したら、それに応じてプルリクエストのステータスを設定します。\n\nこのCIシステムとホストサーバーは、想像上のものです。 Travis でも、Jenkins でも、何でも構いません。 このガイドのポイントは、通信を管理するサーバーを設定し、構成することにあります。\n\nまだ行っていない場合は `ngrok` を[ダウンロードし](https://ngrok.com/)、その[使い方](https://ngrok.com/docs/getting-started/)をご確認ください。 これは、ローカル アプリケーションをインターネットに公開するために非常に便利なツールであることがわかりました。\n\n> \\[!NOTE]\n> または、Webhook 転送を使って、Webhook を受信するようにローカル環境を設定することもできます。 詳しくは、「[GitHub CLI を使用して Webhook をテスト用に転送する](/ja/webhooks/testing-and-troubleshooting-webhooks/using-the-github-cli-to-forward-webhooks-for-testing)」をご覧ください。\n\n注: このプロジェクトの完全なソース コードは、[platform-samples リポジトリから](https://github.com/github/platform-samples/tree/master/api/ruby/building-a-ci-server)ダウンロードできます。\n\n## サーバーを書く\n\nローカル接続が機能していることを証明するための、簡単なSinatraアプリケーションを書きます。\nまずはこれから始めましょう。\n\n```ruby\nrequire 'sinatra'\nrequire 'json'\n\npost '/event_handler' do\n  payload = JSON.parse(params[:payload])\n  \"Well, it worked!\"\nend\n```\n\n(Sinatra のしくみに詳しくない場合は、[Sinatra ガイド](http://www.sinatrarb.com/)を読むことをお勧めします。)\n\nこのサーバーを起動してください。 既定では、Sinatra はポート `4567` で起動するため、`ngrok` もそのポートで待ち受けるように構成してください。\n\nこのサーバーが機能するには、webhookでリポジトリを設定する必要があります。 プルリクエストが作成やマージされるたびに、webhookが起動するよう設定すべきです。\n\n思う存分試せるリポジトリを作成してみましょう。 <c1><c0 /> の Spoon/Knife リポジトリはいかがでしょうか。\n\nその後、お使いのリポジトリ内に新しい Webhook を作成し、`ngrok` で提供された URL を指定し、コンテンツ タイプとして `application/x-www-form-urlencoded` を選びます。\n\n**\\[Webhook の更新]** をクリックします。\n`Well, it worked!` の本文応答が表示されます。\nすばらしい。\n**\\[個々のイベントの選択]** をクリックし、以下を選びます。\n\n* 状態\n* プルリクエスト\n\nこれらは、関連するアクションが発生するたびにサーバーに送信 GitHub イベントです。 ここで pull request のシナリオ \\_だけ\\_を処理するようサーバーを更新しましょう。\n\n```ruby\npost '/event_handler' do\n  @payload = JSON.parse(params[:payload])\n\n  case request.env['HTTP_X_GITHUB_EVENT']\n  when \"pull_request\"\n    if @payload[\"action\"] == \"opened\"\n      process_pull_request(@payload[\"pull_request\"])\n    end\n  end\nend\n\nhelpers do\n  def process_pull_request(pull_request)\n    puts \"It's #{pull_request['title']}\"\n  end\nend\n```\n\n何が起こっているのでしょうか。\nGitHubが送信するすべてのイベントには、`X-GitHub-Event` HTTP ヘッダーが添付されています。 ここではPRイベントのみに注目しましょう。 そこから、情報のペイロードを処理して、タイトルフィールドを返します。 理想的なシナリオにおいては、pull request が開かれたときだけではなく、更新されるたびにサーバーが関与します。 それにより、すべての新しいプッシュがCIテストを通過することが確実になります。\nしかしこのデモでは、開かれたときについてのみ気にすることにしましょう。\n\nこの概念実証を試すため、テスト リポジトリのブランチで何か変更を行い、pull request を開きます。 そうすると、サーバーはそれに応じてレスポンスを返すはずです。\n\n## ステータスを管理する\n\nサーバーの環境を整えたところで、最初の要件、つまり CI 状態の設定 (と更新) を始める準備が整いました。 いつでもサーバーを更新するときに、 **\\[再配信]** をクリックして同じペイロードを送信できることに留意してください。 変更を行うたびに新しい pull request を作成する必要はありません。\n\nGitHub API と対話するため、[Octokit.rb](https://github.com/octokit/octokit.rb) を使用して対話を管理します。 そのクライアントを[a personal access token](/ja/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)で構成します。\n\n```ruby\n# !!! DO NOT EVER USE HARD-CODED VALUES IN A REAL APP !!!\n# Instead, set and test environment variables, like below\nACCESS_TOKEN = ENV['MY_PERSONAL_TOKEN']\n\nbefore do\n  @client ||= Octokit::Client.new(:access_token => ACCESS_TOKEN)\nend\n```\n\nその後、CI で処理していることを明確にするために、 GitHub の pull request を更新するだけで済みます。\n\n```ruby\ndef process_pull_request(pull_request)\n  puts \"Processing pull request...\"\n  @client.create_status(pull_request['base']['repo']['full_name'], pull_request['head']['sha'], 'pending')\nend\n```\n\nここでは3つの基本的なことを行っています。\n\n* リポジトリのフル ネームを検索する\n* Pull request の最後の SHA を検索する\n* 状態を \"pending\" に設定する\n\nこれで完了です。 これで、テスト スイートを実行するために必要なあらゆるプロセスを実行できます。 コードを Jenkins に渡すことも、API 経由で [Travis](https://api.travis-ci.com/docs/) のような別の Web サービスを呼び出すこともできます。 その後は、状態をもう一度更新するようにしてください。 この例では、単に `\"success\"` に設定します。\n\n```ruby\ndef process_pull_request(pull_request)\n  @client.create_status(pull_request['base']['repo']['full_name'], pull_request['head']['sha'], 'pending')\n  sleep 2 # do busy work...\n  @client.create_status(pull_request['base']['repo']['full_name'], pull_request['head']['sha'], 'success')\n  puts \"Pull request processed!\"\nend\n```\n\n## まとめ\n\nGitHubでは、[Janky](https://github.com/github/janky) のバージョンを使用して、長年にわたって CI を管理してきました。\nその基本的なフローは、上記で構築してきたサーバーと本質的にまったく同じです。\nGitHubでは、次の手順を実行します。\n\n* プルリクエストが作成または更新されたときにJenkinsに送信する (Janky経由)\n* CIのステータスについてのレスポンスを待つ\n* コードが緑色なら、プルリクエストにマージする\n\nこれら全ての通信は、チャットルームに集約されます。 この例を使うために、独自の CI 設定をビルドする必要はありません。\n\n[GitHub統合](https://github.com/integrations)に常に依存できます。"}