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

デプロイメントを配信する

Deployment REST APIを使用すると、サーバーおよびサードパーティアプリケーションとやり取りするカスタムツールを構築できます。

Deployment APIは、GitHub Enterprise Serverにホストされたプロジェクトが、あなたのサーバーで起動できるようにします。 Status APIと組み合わせれば、コードがデフォルトブランチに到着してからすぐにデプロイメントを調整できるようになります。

このAPIでは、ステータスAPIを使って、利用できる設定を示します。 このシナリオでは、以下を行います。

  • ププルリクエストをマージします。
  • CIが終了したら、それに応じてプルリクエストのステータスを設定します。
  • プルリクエストがマージされたら、サーバーでデプロイメントを実行します。

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

まだngrokをダウンロードしていない場合はダウンロードし、その使いかたを学びましょう。 これはローカル接続を公開するために非常に役立つツールだと思います。

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

サーバーを書く

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

require 'sinatra'
require 'json'

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

(シナトラの仕組みに詳しくない方は、Sinatraのガイドを読むことをお勧めします。)

このサーバーを起動してください。 デフォルトでは、Sinatraはポート4567で起動するため、このポートもリッスンを開始するようngrokを設定するとよいでしょう。

このサーバーが機能するには、webhookでリポジトリを設定する必要があります。 プルリクエストが作成やマージされるたびに、webhookが起動するよう設定すべきです。 なんでも好きにして構わないようなリポジトリを作成しましょう。 @octocat's Spoon/Knifeリポジトリなどはどうでしょうか。 その後、リポジトリ内に新しいwebhookを作成し、ngrokが提供したURLを指定し、コンテンツタイプとしてapplication/x-www-form-urlencodedを選択します。

新しいngrok URL

Update webhook(webhookの更新)をクリックしてください。 本文にWell, it worked!というレスポンスが表示されるはずです。 これでうまくいきました。 [Let me select individual events]をクリックし、以下を選択します。

  • デプロイメント
  • デプロイメントステータス
  • プルリクエスト

これらは、関係するアクションが発生するごとにGitHub Enterprise Serverがこのサーバーに送信するイベントです。 ここではプルリクエストがマージされたときの処理だけを処理するようサーバーを設定します。

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

  case request.env['HTTP_X_GITHUB_EVENT']
  when "pull_request"
    if @payload["action"] == "closed" && @payload["pull_request"]["merged"]
      puts "A pull request was merged! A deployment should start now..."
    end
  end
end

さて、ここで起こっていることを説明しましょう。 GitHub Enterprise Serverが送信するすべてのイベントには、X-GitHub-Event HTTPヘッダが添付されています。 ここではPRイベントのみに注目しましょう。 プルリクエストがマージされると (ステータスがclosedとなり、mergedtrueになると)、デプロイメントを開始します。

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

デプロイメントを扱う

サーバーの準備が整い、コードがレビューされ、プルリクエストがマージされたので、プロジェクトをデプロイしたいと思います。

まず、イベントリスナーを修正し、マージされたときにプルリクエストを処理して、デプロイメントの待機を開始することから始めましょう。

when "pull_request"
  if @payload["action"] == "closed" && @payload["pull_request"]["merged"]
    start_deployment(@payload["pull_request"])
  end
when "deployment"
  process_deployment(@payload)
when "deployment_status"
  update_deployment_status
end

プルリクエストからの情報に基づき、start_deploymentメソッドを書き込むことから始めます。

def start_deployment(pull_request)
  user = pull_request['user']['login']
  payload = JSON.generate(:environment => 'production', :deploy_user => user)
  @client.create_deployment(pull_request['head']['repo']['full_name'], pull_request['head']['sha'], {:payload => payload, :description => "Deploying my sweet branch"})
end

デプロイメントには、payloadおよびdescriptionの形式で、一部のメタデータを添付できます。 これらの値はオプションですが、ログの記録や情報の表示に役立ちます。

新しいデプロイメントが作成されると、まったく別のイベントがトリガーされます。 ですから、deploymentのために、イベントハンドラーのswitchに新たなcaseを用意します。 この情報を使用して、デプロイメントがトリガーされたときに通知を受け取ることができます。

デプロイメントにはかなり時間がかかる場合があるため、デプロイメントがいつ作成されたか、デプロイメントのステータスなどのさまざまなイベントをリッスンしたいと思います。

何かの作業をするデプロイメントをシミュレートし、その影響を出力として通知しましょう。 まず、process_deploymentメソッドを完成させます。

def process_deployment
  payload = JSON.parse(@payload['payload'])
  # you can send this information to your chat room, monitor, pager, etc.
  puts "Processing '#{@payload['description']}' for #{payload['deploy_user']} to #{payload['environment']}"
  sleep 2 # simulate work
  @client.create_deployment_status("repos/#{@payload['repository']['full_name']}/deployments/#{@payload['id']}", 'pending')
  sleep 2 # simulate work
  @client.create_deployment_status("repos/#{@payload['repository']['full_name']}/deployments/#{@payload['id']}", 'success')
end

最後に、ステータス情報の保存をコンソールの出力としてシミュレートします。

def update_deployment_status
  puts "Deployment status for #{@payload['id']} is #{@payload['state']}"
end

ここの処理を細かく説明しましょう。 新しいデプロイメントがstart_deploymentにより作成され、それがdeploymentイベントをトリガーします。 そこからprocess_deploymentを呼び出して、実行中の作業をシミュレートします。 この処理の間にcreate_deployment_statusも呼び出し、ステータスをpendingに切り替えることで受信側に状態を通知します。

デプロイメントが完了後、ステータスをsuccessに設定します。

おわりに

GitHubでは長年、デプロイメントを管理するためHeavenの特定のバージョンを使用してきました。 A common flow is essentially the same as the server we've built above:

  • Wait for a response on the state of the CI checks (success or failure)
  • If the required checks succeed, merge the pull request
  • Heaven takes the merged code, and deploys it to staging and production servers
  • その間にHeavenは、当社のチャットルームに居座っているHubotを通じて全員にビルドについて通知する

これで完了です。 この例を使用するために、独自のデプロイメントを構築する必要はありません。 いつでもGitHubインテグレーションに頼ることができます。

問題がまだ解決していませんか?