Skip to main content

Enterprise Server 3.20 は、現在リリース候補として使用できます。

CIサーバーの構築

Status APIで独自のCIシステムを構築しましょう。

この記事で

REST API を使って、コミットとテスト サービスを結びつけます。こうすると、実行するすべてのプッシュをテストし、GitHub の pull request で表すことができるようになります。 関連するエンドポイントの詳細については、「コミットのステータス用の REST API エンドポイント」を参照してください。

このガイドでは、そのAPIを使って、利用可能なセットアップを示します。 このシナリオでは、以下を行います。

  • プルリクエストが作成されたとき、CIスイートを実行します (CIステータスを「保留中」に設定します)。
  • CIが終了したら、それに応じてプルリクエストのステータスを設定します。

このCIシステムとホストサーバーは、想像上のものです。 Travis でも、Jenkins でも、何でも構いません。 このガイドのポイントは、通信を管理するサーバーを設定し、構成することにあります。

まだ行っていない場合は ngrokダウンロードし、その使い方をご確認ください。 これは、ローカル アプリケーションをインターネットに公開するために非常に便利なツールであることがわかりました。

注: このプロジェクトの完全なソース コードは、platform-samples リポジトリからダウンロードできます。

サーバーを書く

ローカル接続が機能していることを証明するための、簡単なSinatraアプリケーションを書きます。 まずはこれから始めましょう。

require 'sinatra'
require 'json'

post '/event_handler' do
  payload = JSON.parse(params[:payload])
  "Well, it worked!"
end

(Sinatra のしくみに詳しくない場合は、Sinatra ガイドを読むことをお勧めします。)

このサーバーを起動してください。 既定では、Sinatra はポート 4567 で起動するため、ngrok もそのポートで待ち受けるように構成してください。

このサーバーが機能するには、webhookでリポジトリを設定する必要があります。 プルリクエストが作成やマージされるたびに、webhookが起動するよう設定すべきです。

思う存分試せるリポジトリを作成してみましょう。 の Spoon/Knife リポジトリはいかがでしょうか。

その後、お使いのリポジトリ内に新しい Webhook を作成し、ngrok で提供された URL を指定し、コンテンツ タイプとして application/x-www-form-urlencoded を選びます。

          **[Webhook の更新]** をクリックします。 
          `Well, it worked!` の本文応答が表示されます。

すばらしい。 [個々のイベントの選択] をクリックし、以下を選びます。

  • 状態
  • プルリクエスト

これらは、関係するアクションが発生するたびに GitHub によってこのサーバーに送信されるイベントです。 ここで pull request のシナリオ _だけ_を処理するようサーバーを更新しましょう。

post '/event_handler' do
  @payload = JSON.parse(params[:payload])

  case request.env['HTTP_X_GITHUB_EVENT']
  when "pull_request"
    if @payload["action"] == "opened"
      process_pull_request(@payload["pull_request"])
    end
  end
end

helpers do
  def process_pull_request(pull_request)
    puts "It's #{pull_request['title']}"
  end
end

何が起こっているのでしょうか。 GitHub が送信するすべてのイベントには、HTTP ヘッダーがX-GitHub-Eventとして添付されています。 ここではPRイベントのみに注目しましょう。 そこから、情報のペイロードを処理して、タイトルフィールドを返します。 理想的なシナリオにおいては、pull request が開かれたときだけではなく、更新されるたびにサーバーが関与します。 それにより、すべての新しいプッシュがCIテストを通過することが確実になります。 しかしこのデモでは、開かれたときについてのみ気にすることにしましょう。

この概念実証を試すため、テスト リポジトリのブランチで何か変更を行い、pull request を開きます。 そうすると、サーバーはそれに応じてレスポンスを返すはずです。

ステータスを管理する

サーバーの環境を整えたところで、最初の要件、つまり CI 状態の設定 (と更新) を始める準備が整いました。 いつでもサーバーを更新するときに、 [再配信] をクリックして同じペイロードを送信できることに留意してください。 変更を行うたびに新しい pull request を作成する必要はありません。

ここでは GitHub API を操作しているため、Octokit.rb を使って操作を管理します。 そのクライアントを personal access token で構成します。

# !!! DO NOT EVER USE HARD-CODED VALUES IN A REAL APP !!!
# Instead, set and test environment variables, like below
ACCESS_TOKEN = ENV['MY_PERSONAL_TOKEN']

before do
  @client ||= Octokit::Client.new(:access_token => ACCESS_TOKEN)
end

その後、CI で処理していることを明確にするため、GitHub の pull request を更新するだけでよいのです。

def process_pull_request(pull_request)
  puts "Processing pull request..."
  @client.create_status(pull_request['base']['repo']['full_name'], pull_request['head']['sha'], 'pending')
end

ここでは3つの基本的なことを行っています。

  • リポジトリのフル ネームを検索する
  • Pull request の最後の SHA を検索する
  • 状態を "pending" に設定する

これで完了です。 これで、テスト スイートを実行するために必要なあらゆるプロセスを実行できます。 コードを Jenkins に渡すことも、API 経由で Travis のような別の Web サービスを呼び出すこともできます。 その後は、状態をもう一度更新するようにしてください。 この例では、単に "success" に設定します。

def process_pull_request(pull_request)
  @client.create_status(pull_request['base']['repo']['full_name'], pull_request['head']['sha'], 'pending')
  sleep 2 # do busy work...
  @client.create_status(pull_request['base']['repo']['full_name'], pull_request['head']['sha'], 'success')
  puts "Pull request processed!"
end

まとめ

GitHubでは、Janky のバージョンを使用して、長年にわたって CI を管理してきました。 その基本的なフローは、上記で構築してきたサーバーと本質的にまったく同じです。 GitHubでは、次の手順を実行します。

  • プルリクエストが作成または更新されたときにJenkinsに送信する (Janky経由)
  • CIのステータスについてのレスポンスを待つ
  • コードが緑色なら、プルリクエストにマージする

これら全ての通信は、チャットルームに集約されます。 この例を使うために、独自の CI 設定をビルドする必要はありません。

          [GitHub統合](https://github.com/integrations)に常に依存できます。