GitHub 時代のデプロイ戦略

少し前までアプリケーションのデプロイと言えば capistrano などをコマンドラインから叩いてデプロイ、みたいなことをやっていたが、最近は少し様子が違うのでそのやり方、KAIZEN platform Inc. での事例を紹介する。

GitHub のイベントを契機に CI as a Service にデプロイを担当させる

GitHub で Pull Request を送って開発するのが前提になっているのは以前にも紹介した。

最近は Travis CI や CircleCI などに代表される CI (Continuous Integration) as a Service があって、CI も自分たちで環境を構築しなくてもクラウドに任せることができる。KAIZEN では CircleCI を積極的に使っている。

これらの CI as a Service は基本的に GitHub と連携することが前提になってて、Github に差分を push するとそれを契機にインテグレーションテストを実行してくれたりする。

で、CI という文脈でいくとこの自動テストの実行が主なユースケースとして想像されやすいのだけど、CI as a Service にはそのテストの実行が終わったあとのデリバリーの機能もある。

Deployment - Travis CI なんかを見るとよくわるのだけど、master に push したらそれをきっかけに Heroku にデプロイを行うとか、そういうことができる。

CircleCI のデプロイオプション

この CI as a Serivice のデプロイオプションは結構色々細かく設定できて、例えば「deployment/production という名前のブランチに変更が push されたらこれを実行する」なんて設定ができる。

設定はレポジトリに置いた circle.yml ファイルに記述する。例えば以下のような感じ。

deployment:
  production:
    branch: deployment/production
    commands:
      - ./script/assets_precompile.sh:
      - bundle exec cap production deploy:migrations:
          
  edge:
    branch: deployment/edge
    commands:
      - ./script/assets_precompile.sh:
      - bundle exec cap edge deploy:migrations:

これでリモートの deployment/production ブランチにコードを push するとそれを契機に production へデプロイが行われるし、deployment/edge なら edge へ、てな感じになる。

実際のデプロイは、(まだ Mutable Infrastructure なので) capistrano を実行している。

CircleCI にデプロイを実施させると、テストを実行してその結果が緑だったらデプロイさせるというようなこととか、デプロイのログが共有しやすくなるとか、キャンセルが簡単とかいろんなメリットを享受できる。

Pull Request でデプロイする

「ほうほう、なるほど。じゃあデプロイしたいときは master から deployment/production へ merge して、git push するのか」というところだけど、ここでもう一個工夫する。

デプロイしたくなったら、master から deployment/production へ Pull Request を作るんである。

この Pull Request を merge すると、CircleCI がそれを検知して結果的に CircleCI 上でデプロイが走る。キャンセルしたいときは merge しないで close する。

なんで直接 push せずにわざわざ Pull Request にするかは、上の画面を見ればだいたいおわかりのとおり

  • デプロイの見える化
  • 何がデプロイされるかのコミットログの可視化

など本当にいろんな利点がある。

production デプロイの際には、この Pull Request のスレッドを使って QA の最終確認をしたりする。コミュニケーションが Pull Request 上に集約されることになるし、デプロイ直前の hotfix が行われたコミットなんかも全て見えるようになる。

今思うと、手元でエイヤで cap deploy の時は、このあたりのワークフローが全部暗黙知化していた。アプリケーションへの変更を Pull Request ベースにして色んなものが見えるようになるのと同じで、デプロイもまた Pull Request で改善できるところがたくさんある。

hubot へデプロイをお願いする

仕上げは、この Pull Request を作る方法である。つい先日までは Pull Request を GitHub 上でマニュアルで作っていたが、ここまできたら GitHub API を使って Pull Request 作成は自動化してしまえばい。

そして、日頃 HipChat を使ってるのだから、チャット上で hubot にデプロイをお願いしたら Pull Request を作ってくれる、とすれば「デプロイ始めまーす」みたいな宣言いらずで一石二鳥である。

というわけで作った。

hubot にお願いするとデプロイ用 Pull Requet が作られて、CircleCI がデプロイしてくれる、そんなワークフローができあがった。万歳。

GitHub や * as a Service を前提にしたワークフローの時代

GitHub や CircleCI のようなサービスがあるという前提でワークフローを構築していくとこんな感じで工夫次第でいろいろ面白くできる。Web サービスと Web サービスを繋げて、さらにそこに自分たちの開発フローを組み込んで一つのフローとして完成すると、なかなかに爽快である。

この辺の開発は、もうこういったWebサービスのような、一見するとプログラム部品としては見えないようなものものも、開発のための一つのプログラマブルな部品であると認識できるかどうか、ライブラリやフレームワークと同じ類のものであるとフラットに見れるかどうかそういう感覚が要求されるように思う。

それは Web 2.0 で Web API だなんだと言われてきたころからあったことなのだけれども、その感覚が、フロントエンドだけではなくて、こうして開発プロセスのワークフローの組み上げににも適用できるようになったというのが、自分としては昨今この領域が面白く感じる理由のひとつでもある。

逆に言えば、こういう領域に開発リソースをうまく継続的に投資できるかどうかということが今後の開発組織のあり方として重要な要素だと思っていて、KAIZEN では会社が立ち上がった当初から CTO と話して "Developer Productivity" という、この手の仕事をミッションにしたチームを構成するようにしてきて、その形が固まってきたところ。それがこういう形で面白い成果に繋がっている、と思っている。