Protected branches を使ったデプロイ自動化の始め方

初めまして、エンジニアチームの @app2641 です。
去年の夏に grooves へ入社しました。
今回は旬の新人がブログを書かせて頂きます。

さて、突然ですが皆さんはアプリケーションのデプロイをどのような方法で行っていますか?
Forkwell では master ブランチにプルリクがマージされたら capistrano を使って丹精込めて手作業でデプロイを行うということをやっていました。
ステージング環境で動作確認する際にも似たような方法を取っていて、正直なところこのデプロイ方法はだるいなあと感じていました。
僕のように日々ぽやーと作業している人間にとってはデプロイ先を間違えそうになったり、マージだけしておいてデプロイは明日になってからやろうとか考えて翌日すっかり忘れていたりなど散々なことになります。
そんな事態を避けるためにはどうすればいいか。
そうです、自動化すればいいんです!
機械で出来ることは機械に押し付けよう!

今回は Forkwell でデプロイを自動化した話をしたいと思います。

Wercker からデプロイ出来るようにする

Forkwell では CI に Wercker を使用しています。
Wercker はプライベートリポジトリであっても無料で利用出来て大変便利です。
便利なので今すぐに使いましょう。さあさあ。

wercker.com

wercker.yml の設定

まずは設定ファイルである wercker.yml にデプロイの方法を記述していきます。

deploy:
  steps:
    - script:
      name: mkdir -p $HOME/.ssh
      code: mkdir -p $HOME/.ssh
    - add-ssh-key:
        keyname: FORKWELL_SSH_KEY
    - create-file:
      name: deploy.sh
      filename: $HOME/deploy.sh
      overwrite: true
      content: |-
        set -e
        cd forkwell
        git pull origin master
        bundle install
        bundle exec cap production deploy
    - script:
      name: deploy to production
      code: ssh -o StrictHostKeyChecking=no $FORKWELL_USER@$FORKWELL_IP 'bash -s' < $HOME/deploy.sh

なんとなくやっていることは分かると思います。
Forkwell では踏み台サーバを経由してデプロイを行っているので、一度踏み台サーバへ接続し、そこから capistrano で本番環境へデプロイしています。
サーバを経由せずにデプロイしたいのであれば、

- cap:
  stage: production

と記述するだけで production へデプロイ出来ます。
create-filecap といった項目は steps と呼ばれるファンクションで他にも様々なものがあります。
詳しくは Wercker の ドキュメント を読むと理解が深まるでしょう。

Deploy target と変数の設定

ところで先ほどの wercker.yml の中で FORKWELL_SSH_KEY だとか FORKWELL_USER といった変数があったことに気付いたでしょうか。
Wercker では直接設定ファイルに書きたくない内容を変数として登録しておくことが出来ます。
SSH 鍵だとか AWS のキーなどは Wercker 側に登録しておくのがベターです。

また、テストが通るたび自由にデプロイされてはかなわないのでデプロイするブランチを限定する必要もあります。
そういった細かな設定は Wercker 側で行います。

SSH 鍵の生成

我々のようにどこぞのサーバに SSH してデプロイしたいのであればまずは SSH 鍵を生成しなくてはなりません。
まずは設定画面で SSH keys ページを開きます。
Generate new key pair ボタンから SSH 鍵を生成します。
f:id:app2641:20160301162022p:plain

こんな感じで鍵が生成されます。
生成した鍵は忘れずにデプロイ先のサーバへ登録しておきましょう。
f:id:app2641:20160301162150p:plain

Deploy target の設定

次に Targets ページを開いてデプロイの設定を行います。
Add deploy target というところのドロップダウンメニューから custom deploy を選択します。
f:id:app2641:20160301162221p:plain

適当な名前とデプロイを動かしたいブランチ名を入力して保存すればよいです。
f:id:app2641:20160301162243p:plain

続いて変数の設定です。
変数はテキスト系のものと SSH 鍵と二種類あります。

テキストの場合。
f:id:app2641:20160301162257p:plain

SSH 鍵の場合。
この例でいうと、 SOMETHING_PUBLIC という変数で公開鍵、SOMETHING_PRIVATE で秘密鍵を扱えるようになります。
f:id:app2641:20160301162309p:plain

これで master ブランチのテストが通ったあと自動でデプロイされるようになりました。
なんとも簡単です。

master ブランチへのマージ制約

自動デプロイの運用になると当たり前ですがテストが通ったあとすぐにデプロイが始まってしまいます。
つまりは non fast-forward マージの master ブランチを動作確認せずにデプロイすることがまま有りえるということです。
テストが通っているとはいえマージ後のブランチで動作確認しておかないと夜もおちおち眠れません。
git-flow なんかだと feature ブランチと master ブランチのあいだに develop ブランチを作って運用するのが筋ですが、プルリクを作る回数が増えて手間なので出来ればやりたくありません。
そこで我々のチームは GitHub が提供している protected branches の機能を使うことにしました。
protected branches を使えばテストが通っていないブランチや non fast-forward のブランチはマージ出来なくなります。
non fast-forward を禁止して fast-forward 出来る feature ブランチを動作確認しておけば安心してマージ出来るね、ということです。

設定はチェックボックスをチェックするだけの簡単なクリック業です。
f:id:app2641:20160301162323p:plain

これでテストが通っていても non fast-forward のブランチはマージ出来なくなりました。
しかも GitHub は便利なものでウェブ上で master ブランチを feature ブランチにマージする機能を提供しています。
プルリク画面で Update branch ボタンを押すと勝手にマージ出来る状態にしてくれます。すごいよすごいよー。
f:id:app2641:20160301162335p:plain

余談ではありますが、我々のチームでは GitHub の Deployments API を使ってステージングで動作確認をしたかどうかがプルリク画面で分かるようになっています。
あ、こいつ動作確認してねえなっていうのが分かるので素敵です。

f:id:app2641:20160301162343p:plain

まとめ

そういうわけでようやっと自動でデプロイする仕組みが出来上がりました。
Forkwell では Wercker を使っていますが CircleCI や TravisCI でも同様のことが簡単に出来るはずです。
自動化出来ることはどんどん機械に任せて、人間はコードを書くことに集中したいですね。
がんばっていきましょうー。
それではまた。