#概要
「masterをプッシュで本番反映」をやっている記事はいくつかあったものの、ブランチごとに自動でステージング(テスト環境)が作られるような仕組みは見当たらなかったので書いてみる。
マージ未定の実験的なブランチをWeb上で確認したり、ローカル環境のないディレクターやデザイナーに作業ブランチの内容を確認してもらう際に役に立つはず。
Gitフック経由のサイト更新はFTPもサーバーへのログインも必要なく、ただpushするだけなので非常に便利だと思う。
※以下、ある程度のサーバーサイドの知識を要する説明になっているので注意
##最終的に実装する機能
-
masterをリモートリポジトリにpushすると、masterの内容が本番サイトである
http://プロジェクト名.com/
に取り込まれる。 -
hogeというブランチを切ってプッシュすると、
http://hoge.プロジェクト名.com/
というhogeブランチの内容が反映されたステージングができあがる。 -
hogeブランチを削除するとステージングも消える。
これらを、gitのサーバーサイドフック(シェルスクリプト)+Apacheの設定で実装する。
他に何かのサービスを利用したりインストールしたりは特にない。
##前提条件
- 対象サーバーにgitリポジトリと本番環境・ステージングが同居している ※1
- 「*.プロジェクト名.com」のDNSレコードが対象サーバーに向いている
※1 git hubなど外部のリポジトリを利用している場合、各サービスのwebフックなどを利用し、本稿で作るgitフックをHTTP経由で発火させる必要がある。
##完成後のディレクトリ構成
var
└www
├git
│ ├プロジェクトA.git ←リモートリポジトリたち
│ └プロジェクトB.git
│
└html
├プロジェクトA
│ ├master ←プロジェクトA.gitのmasterブランチをクローンしたもの
│ └develop ←プロジェクトA.gitのdevelopブランチをクローンしたもの
│
└プロジェクトB
├master
├develop
└etc...
masterやdevelopに各ブランチのソースが入りweb公開される。
#実装
##下準備
以下についての手順は省略する。
- サーバーにApacheとgitをインストールする。
- サーバーにgitリポジトリを作成し、ローカルから利用できるようにする。
-
/var/www/html
にプロジェクトディレクトリを作成する。※2 -
プロジェクト名.com
と*.プロジェクト名.com
のDNSレコードをサーバーに向ける。
※2 この配下のmasterやdevelopといったディレクトリは勝手に生成されるので作成不要
##手順1:Apacheを設定
「ブランチ名.プロジェクト名.com」でアクセスされた際に「/var/www/html/プロジェクト名/ブランチ名」を参照するように設定する。
また、ブランチ名を省略して、「プロジェクト名.com」でアクセスされた場合はmasterをみるようにする。
VirtualDocumentRootを使うので、mod_vhost_aliasが無効になっている場合有効にしておく。
LoadModule vhost_alias_module modules/mod_vhost_alias.so
# 場所は環境によって異なる
バーチャルホストの設定ファイルを開き、以下の設定を追加する。
http://ブランチ名.プロジェクト名.com
のようにプロジェクト専用のドメインを取得している場合、
<VirtualHost *:80>
ServerName プロジェクト名.com
ServerAlias *.プロジェクト名.com
VirtualDocumentRoot "/var/www/html/プロジェクト名/%1"
</VirtualHost>
<VirtualHost *:80>
ServerName プロジェクト名.com
ServerAlias プロジェクト名.com
DocumentRoot "/var/www/html/プロジェクト名/master"
</VirtualHost>
http://ブランチ名.プロジェクト名.ドメイン名.com
のように、サブドメインへ複数のプロジェクト名を動的に設定したい場合、
<VirtualHost *:80>
ServerName ドメイン名.com
ServerAlias *.*.ドメイン.com
VirtualDocumentRoot "/var/www/html/%2/%1"
</VirtualHost>
<VirtualHost *:80>
ServerName ドメイン名.com
ServerAlias *.ドメイン.com
VirtualDocumentRoot "/var/www/html/%2/master"
</VirtualHost>
記述後、apacheを再起動する。
##手順2:gitのサーバーサイドフックを記述
サーバーサイドフックは、リモートリポジトリへのプッシュをトリガーに発火する処理。
今回は、/var/www/git/プロジェクト名.git/hooks/内にpost-updateというファイルを作成する。
post-updateはプッシュされた際にブランチごとに発火する。その際「refs/heads/master」のような引数が設定される。
今回シェルスクリプトでやること、
- 引数を元に、git rev-parseでプッシュされたブランチ名を取得する
- git rev-parseに失敗(結果と引数がイコール)した場合ブランチ削除とみなす
3-A. ブランチ削除の場合、対応するステージングを削除
3-B. ブランチに対するステージングが存在しないならクローンして作成
3-C. 既に存在する場合はクローン済みのステージングをプル
#!/bin/bash
repo=/var/www/git/プロジェクト名.git
dir=/var/www/html/プロジェクト名/
name=$(git rev-parse --symbolic --abbrev-ref $1)
# delete chk
delete=0
if [ $name = $1 ]; then
name=${name#refs/heads/}
delete=1;
fi
# pull or clone or delete
if [[ $name =~ ^[a-z0-9-]+$ ]]; then
if [ $delete = 1 ] && [ $name != master ]; then
echo $dir$nameを削除
rm -rf $dir$name
elif [ -e $dir$name ]; then
echo $dir$nameをプル
cd $dir$name
git --git-dir=.git pull
else
echo $dir$nameをクローン
cd $dir
git clone -b $name $repo $name
fi
fi
※ハイフン以外の記号や大文字が含まれるブランチは無視する
(つまりステージング不要なブランチは「feature/hoge」のような名前にすればよい)
※rm -rf
している箇所もあるので実装は慎重かつ自己責任で。
フックには実行権限を付与する。
$ sudo chmod +x /var/www/git/プロジェクトA.git/hooks/post-update
##手順3:パーミッションの設定
プッシュするユーザーが「git配下の書き込み権限」と「html配下の書き込み権限」を持っている必要がある。
###gitリモートリポジトリをhttps経由で利用する場合:
プッシュもフックの実行もapacheが行うことになるので、各ディレクトリの所有者をapacheにしておけばよい。
$ sudo chown apache:apache -R /var/www/git
$ sudo chown apache:apache -R /var/www/html
###gitリモートリポジトリをSSH経由で利用する場合:
ログインユーザーがプッシュやフックを実行することになる。
好みにもよるが、例えば各ディレクトリの所有ユーザーとグループをapacheに設定しておいて、プッシュするユーザーをapacheグループに追加するなど。
$ sudo chown apache:apache -R /var/www/git
$ sudo chown apache:apache -R /var/www/html
$ sudo chmod g+w -R /var/www/git
$ sudo chmod g+w -R /var/www/html
$ sudo usermod -aG apache ユーザー名
##確認
プッシュ後、設定したURLでそのブランチの内容が閲覧できることを確認する。
ステージング削除の際は下記コマンドでリモートブランチを削除する必要がある。
$ git push origin :ブランチ名
# ブランチ名の前のコロンを忘れずに
恐らく、SourceTreeなどのgitクライアント経由でリモートブランチを削除しても、ステージングは削除されないので注意。