最近ちょっと開発環境を見直していて、その中の一つとして git hooks によるデプロイを導入したので紹介してみたいと思います。
もともとバージョン管理には Subversion を使っていて、今回 git に移行したタイミングで、 git-hooks デプロイを導入しました。
svn から git への移行については今回割愛しますが、 git push origin master
とやると自動的に本番にデプロイする方法は、
個人で借りてるサーバでも利用している方法だったので、是非ともやりたかったことの一つ。
git hooks
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
git には hooks という、updateやreceiveした後など、いくつかのタイミングをフックしてスクリプトを実行出来る仕組みがあります。 svn でもフックスクリプトは使えますが、こちらはコミットに対してフックする感じで、 git の方がタイミングが豊富という印象があります。
これの何が嬉しいかというと、例えば、チームでコード品質やコード規約を守るために、コミットする前にコミットしようとしているコードを必ず validation してNGならコミット中止、 コミット後に diff を通知する、push 受けた際にテストを走らす、などなどをするのに便利です。
今回は push があった際に更新しようとしているブランチごとに実行される post-update
を使ってデプロイ作業の自動化を行いました。
デプロイの仕組み
(あ、Gitlab使ってます…)
今回やりたかったこととして、
- プッシュしたタイミングでtest、staging、本番、の各サーバに即時にソースを反映させたい
- ブランチ毎にWebサーバを切り替えたい
があります。
一つ目について、
今まで svn 時代には、
①ローカルから中央リポジトリにコミット
②test、stagingサーバにあるワーキングリポジトリ側で中央リポジトリの変更を受け取る(cron に3分毎に svn up
するようにセットしていた)
③stagingサーバに ssh で入ってstagingから手で本番へ反映
のようなフローでデプロイを行なっていましたが、これは git hooks (post-update
)を使って自動化することで解決しました。
2つ目について、
post-update
はタイミング的に post-receive
と似ているのですが、複数のブランチへのプッシュがあったときに post-receive
が実行されるのが一度だけなのに対して、
post-update
はブランチ単位でそれぞれ一度ずつ実行されるという特徴があります。
そして第一引数にブランチ名を受け取るのですが、ブランチ名は post-update
の中でこんな風に取得することが出来ます。
1 2 3 4 |
|
あとは $BRANCH
毎に処理の振り分けをします。
1 2 3 4 5 6 7 8 9 10 11 |
|
最終的には rsync + ssh
でWebサーバへ送りたい、ので一度 $TMPDIR
に checkout してます。
1
|
|
checkout したディレクトリに移動して rsync + ssh
。
1 2 |
|
この方法だと、それぞれの各確認用サーバでは常に最後に push されたブランチが当該Webサーバに反映されていることになります。
アイデア次第でまだまだ面倒な作業を自動化出来そうですが、まだ git による運用自体に慣れてないこともあり、しばらくこれでまわしてみて、 今後運用の中で、また何か改善点など出てきたら共有していきたいと思います。
tips
tips というかGitlabを使っていてハマった点なのですが、post-updateスクリプトで tmpdir に git checkout したあと、
勝手にディレクトリが770
、ファイルが660
というパーミッションになってしまって困った、ということがありました。
post-updateに書いてある内容を手で実行してみてもそんなことにはならず、なんだ?という感じだったのですが、
home/git/.gitolite.rc
にこんな記述があり、
1 2 3 4 5 |
|
ユーザがログイン後に実行されるコマンド/home/git/gitolite/src/gitolite-shell
内で、
1 2 3 4 5 6 |
|
のように指定されているのでした。なのでUMASK => 0002
にしてディレクトリが775
、ファイルが664
となるようにして対応しました。
…と書いたのですが、Gitlab5.0からはgitoliteは使用しないようなので、 気にしなくていいかもしれません。ぐぬぬ。