gitでhookを使ってWebサイトの自動更新
以前のエントリでは、最終的に、テスト環境および本番環境で git pull することによって、それぞれを更新しています。
しかし、git には、push等が実行されると、その後に自動実行してくれるフックメカニズムが用意されています。
これを利用すれば、いちいちbareリポジトリにpush後、手動でgit pullすることなく、自動的に行なわせることができます。
下準備(テスト用と本番用でbranchを分ける)
これは必ずしも同じようにやる必要はありませんが、私の場合は、テスト環境用と本番環境用で、それぞれbranchを分けることにしています。
本番環境用を masterブランチ、テスト環境用を developブランチとします。
まずは、ブランチを作りましょう。
#localhost # 現在のブランチを確認する $ git branch -l * master $ git checkout -b develop $ git branch -l master * develop $ git push origin develop #server $ cd /var/dev ;#テスト環境 $ git checkout -b develop origin/develop
開発はdevelopブランチもしくは、developブランチから分岐したブランチで行ない、テスト環境でのチェック後、developブランチをmasterブランチへmergeします。
#localhost $ git branch -l master * develop $ edit;edit;edit; $ git commit -a; $ git push origin develop #server $ cd /var/dev ;#テスト環境 $ git pull origin develop ;#後述のフックを使用し不要になる操作 #本番サーバーでのテストが完了したら #localhost $ git cehckout master $ git merge develop $ git push origin master #server $ cd /var/www ;#本番環境 $ git pull origin master ;#後述のフックを使用し不要になる操作
これでふたつのブランチで運用することができました。
hookを使用する
hookは、bareリポジトリに設定します。
#server $ cd /repos/bs.git ;#bareリポジトリ $ cp -p hooks/post-update.sample post-update $ vi hooks/post-update # 追記 (cd /var/dev && git --git-dir=.git pull origin develop) (cd /var/www && git --git-dir=.git pull origin master)
これで終了です。
実際にpullされるかを試してみましょう。
#localhost $ git checkout develop $ edit;edit;edit; $ git commit -a $ git push origin develop # このときにテスト環境がdevelopブランチをpullしていることが確認できます。 $ git checkout master $ git merge develop $ git push origin master # このときに本番環境がmasterブランチをpullしていることが確認できます。 $ git checkout develop ;#開発は常にmaster以外のブランチで行なう
めでたく自動化できました。
一度設定すると、本番サーバーでの作業が激減しますね。
さくらインターネットで git push するとgit-receive-pack: Command not found. と言われる問題の応急処置
さくらインターネット(Sakura Internet)で、git push すると、git-receive-pack: Command not found.と表示されてうまくいかないという問題があります。
問題の原因としては、gitコマンドへのパスが通っていないためなのですが、その解決方法が分からずじまい。
この問題については、以下のようなサイトが参考になります。
git [てきとうにめも]
問題の原因が分かっても、どうにも対処できなかったので、pushする側で対処しました。
#localhost
$ cd
$ vi .gitconfig
# 以下を追加
[alias]
spush = push --receive-pack=/home/username/local/git/bin/git-receive-pack
sclone = clone --upload-pack=/home/username/local/git/bin/git-upload-pack
これで git spush origin master とすればreceive-packを指定したことになります。
#localhost $ git commit;git commit;git commit $ git spush origin master $ git spush --all $ git spush --tags
根本的解決が分かったらまたブログ書く。
gitでpushしたりpullしたり
なんかおかしいと思いつつも、決定的な情報がなかったために間違ったやり方をしていたのですが、ひょんなことから正しい情報をゲットしたので、私はこうやって使っていますという話を。
(もしかしたらまだまだ非効率なやりかたをしていると思うので是非ご指摘ください)
バージョン管理システム自体を知らなかった自分にも理解できるよう、かみ砕いた説明をしたいと思います。
基本的にgitは、sshが使えれば、導入をためらうことはありません。
サーバー間のやりとりはsshを使って行えますので、gitを導入するにあたって余計なポートをあけたりする必要はないです。
gitでは、今いるレポジトリ(ソースを入れてるディレクトリ)を特に「ローカルレポジトリ」と呼び、やりとりする相手方を「リモートレポジトリ」と呼びます。
普段開発している社内のPCを開発サーバー(開発環境)と呼び、Webサイトを公開しているサーバーにはテスト環境と本番環境が入っているとします。
それぞれ○○環境ごとに、CakePHPのappディレクトリがあると考えると良いですね。
ここで、開発サーバーも公開サーバーもコマンドラインによる操作ができ、公開サーバーは外部からSSHが利用できるものとします。(開発サーバーは外からsshでつながらなくて良いです)
開発サーバーをlocalhostと呼び、公開サーバーをexample.comと呼びます。
www.example.comで本番環境のサイトが表示され、dev.example.comにはアクセス制限をかけてテスト環境を表示していることにします。
appファイルはそれぞれ、/var/appと、/var/www/および/var/devにあることとします。
gitを利用する場合は、このほかに、もうひとつ、bareレポジトリという、共用のレポジトリを用意するのがコツです。
このレポジトリはどこからでもアクセスでき、ローカルで行った変更を、手軽に反映させることができるのです。
svnを利用している人には、逆に少し分かりづらいかもしれません。
svnにおいては、この共用レポジトリこそが唯一のレポジトリということになります。その他はチェックアウトしているだけで、それ自体はレポジトリとは呼びません。
しかし分散型のバージョン管理システムであるgitは、レポジトリから「clone」したその場所もまた、レポジトリなのです。
このことは、ローカルレポジトリの中だけで、バージョン管理ができるということを意味します。
そして必要に応じてのみ、共用レポジトリにその更新を伝えれば足り、すべてのバージョンをその都度(毎回)共用レポジトリに伝える必要がないため、ローカルレポジトリで作業する間は、極端な話インターネットにアクセスできなくても開発は可能です。(もちろんバージョン管理を行いながらです)
具体的な手順はより詳しい方の説明の方が良いと思いますのでそちらを参照してもらうとして、ここではCakePHPで実際どのような流れで開発がされるのかを説明していきます。
まず、共用レポジトリと、www.example.comとdev.example.comのふたつのレポジトリを作成しましょう。
(アプリケーションをbsとします)
# 準備として共用レポジトリ用のディレクトリを作成します $ mkdir /repos # 共用レポジトリ用のディレクトリを作成(共用の場合は.gitをつけるのが慣例です) $ mkdir /repos/bs.git $ cd /repos/bs.git # gitレポジトリ(共用 --bare)を作成 $ git clone --bare git://github.com/monsat/cakephp-plain-app.git #でCakePHP用の初期ファイルのセットが手に入ります。 # git init --bare # 空で作成する場合はcloneの代わりにこれ # テスト・本番用ディレクトリを作成 $ cd /var # 分かりやすく短いパスで説明しています $ git clone /repos/bs.git dev $ git clone /repos/bs.git www
次に開発環境のPCに、開発用のレポジトリを作成しましょう。
# localhost $ cd /var $ git clone ssh://example.com/repos/bs.git app
これで準備は整いました。
コマンドについては詳しく説明しませんが、cloneはレポジトリを複製するコマンドです。
いちからレポジトリを作成する場合は、ディレクトリの中で git init とすると、そのなかに .git という隠しディレクトリが作成されます。
(いつでもそれを削除することで通常のディレクトリになります。逆に言えば、この特別なディレクトリを誤って削除しないようにしましょう。変更履歴をすべて失いかねません)
それではアプリを開発してもらいますが、CakePHP特有の設定を。
gitでは、バージョン管理したくないファイルを .gitignore というファイルに記述することで設定することができます。
CakePHPの場合はtmpディレクトリ以下がそれにあたり、その場合には
tmp/**/*
と記述すると、tmp以下すべてとなります。
tmp以下には、ファイルのパスの情報も入っていますので、これらのファイルがテスト環境や本番環境にコピーされてしまうと、CakePHPは正しく動作しません。場合によってはただ真っ白なページが表示されるということがあります。
それでは開発をすすめていったとします。
(本当はbranchという考え方を理解する必要がありますがそれは省略)
開発の小さな区切りごとに commit という作業を行います。
このcommitがいわばマイルストーンとなり、commitした時点のレポジトリ内の状態に、いつでも戻せます。ファイルが更新される前とか、ディレクトリを作成する前、といった状態にです。
これがバージョン管理システムの肝でして、元に戻す命令を出すと、レポジトリ(ディレクトリ)の中は、あら不思議、一変するのです。元に戻した後に、最新の状態に復帰するのもコマンド一発ですので、またさらに元に戻すことができます。
しかしそれはあくまでcommitを単位として記録されていきますので、「ひとつの機能ごとに」こまめにコミットしていきましょう。
svnと違ってgitの良いところは、このコミットをするのはあくまでローカルレポジトリに閉じた話だということです。svnの場合はコミットごとに中央の(唯一の)レポジトリにアクセスすることになるため、今回の例でいえば、都度SSHによるアクセスが入ります。(公開サーバーへのアクセスはSSH経由です)
gitの場合はコミットはローカルレポジトリで行い、テスト環境や本番環境を変更するときだけ、共用レポジトリを利用する(=共用レポジトリにコミットの履歴を伝える)ことも可能です。
前述したインターネットにつながってなくても開発ができるという状態のことです。
コミットは以下のように行いますが、詳しくは例によって省略。
$ cd /var/app $ git add file_name # 新規作成したファイルがあれば実行。複数あれば git add . ですべて $ git commit -a
コミットの都度shaによる40桁のIDが生成されます。このIDは、元に戻ったりするときに使用されますが、一意に特定できれば先頭の数文字の指定で間に合います。(当初は一桁でもいけるはずです)
そして、公開サーバーにある共用レポジトリへコミットの履歴を反映させる手順です。
# localhost $ cd /var/app $ git push
cloneしてきたリモートレポジトリに反映をさせるのは、git push と引数を省略することができるのでらくちんです。
もし複数人の開発等で共用レポジトリが更新されている「可能性がある」のであれば、push の前に git pull を行います。賢いgitが、あなたと他人の更新がごっちゃにならないように、うまく融合(merge)してくれるでしょう。
あとは、テスト環境本番環境とも、それぞれ git pull するだけで、開発した内容をそれぞれに反映させることができます。
テスト環境を反映させ、公開サーバー上でもアプリに不具合がないことを充分にテストしてから、本番環境を更新しましょう。
# example.com # dev $ cd /var/dev $ git pull # テスト実行。問題なければ本番環境へ # www $ cd /var/www $ git pull
駆け足でしたが、以上です。
CakePHPにおける開発環境について
前回のIRC集会で話題になった開発環境について、記録としてポストしておきたいと思います。
以前は「FTPもしくはSCPでファイルをアップし動作確認」という面倒なことをやっていました。
しかし、仮想化ソフトを利用してマシン内にLinuxを入れてしまえばわざわざFTPすること無いよねと、至極当たり前のことに気づいたのです。
(もちろん物理的に開発用のLinuxがあれば仮想化も必要ありませんが)
基本的にウィンドウズ(XAMPP)で開発環境を構築したくはないという好き嫌いの話があって、Linuxは前提で。
さて、仮想化ソフトは何にしようかといろいろ調べ、どうやらVMwarePlayerというのが、使っているPCのスペックでも何とかなりそうだという結論に。
しかし「OSを何にするか」ではたと悩むことに。
というのも最近はあまりOSのインストールをしていなかったのと、そもそもVineLinuxくらいしかまともに触ったことがなかったので、安定しているという噂のCentOSでいけそうなのかどうかを、これまた半日がかりで調べました。
で、どうやらいけそうだと。
利用者も多そうで(ここ大事)ネットの情報が溢れてる。
というわけで、各所を見ながら、エイヤとインストール。
(この辺も後々のためにまとめておかなきゃ。後日)
当初はどうやってファイルを共有しようかともやもやしてましたが、何のことはないsambaで共有すれば良いのでした。vmwareの共有機能を使おうとしたのは何だったのか。。。
で、めでたくファイルの共有ができたので、普段使いのEclipseで新しくプロジェクトを作成します。
あとは、CentOSにgitをインストールし、gitでサーバーにアップできるようにして完了。
とにかくこのgitが超絶便利。
gitを使いたいというモチベーションがなかったら、VMwareでLinuxという環境はできていなかったほど、今の私には重要なソフトです。
環境構築後にTortoiseGitのバージョンがあがり使い勝手が良くなっていますが、そのときは使いづらかったのです。
svnには挫折した私も、この便利さ・快適さには勝てません。
CakePHPと一緒で、慣れるまでは覚えることが多くて苦労をしても、使い始めるともはや手放すことができません。
CakePHPも1.3はgitによって管理されています。
thechawというgitレポジトリもでき、各種Plugin等が公開されています。
zipでダウンロードして解凍して、、、なんて手間はなくなるし、バージョンアップしたらコマンド一発です。
でも、もっともっと便利な環境が、世の中にはあるのだろうなあ。それは多分半年後の話。