エラーのあるファイルはコミットしない(git編)
あんま知られてないけど,PHP界隈でも
っていう,アドベントカレンダーやってたみたいです.ぜんぜんしりませんでしたそしてちらっと読んだけどあまりおもしろくn(r
で,その中にちょっと面白げな記事を見つけたので,紹介.
git の pre-commit hook を使って,エラーチェック
だいたいはテスト走らせてコミットとか,実行させてからコミットとかするけど,ちょっとしたところの修正だから確認もせずにコミットしてしかもよりによってそれがエラー起こしてたりとか,まぁ,たまにありますよね.
そのために,コミット直前の pre-commit にフックして,PHP Lintを走らせ,その結果次第でコミットをなかったことにしちゃったりしませんか,という趣旨の話.
で,具体的には,
- コミットされたファイルのPHPの文法チェックしたりする実行ファイルを用意
- プロジェクトの,.git/hooks/pre-commit で実行させる
の2つの準備が必要でする.
コミットされたファイルの文法チェック
これは,Web Advent 2008 / Don’t Commit That Error をそのまま使ってしまいます.
#!/usr/bin/php <?php $output = array(); $return = 0; exec('git rev-parse --verify HEAD 2> /dev/null', $output, $return); $against = $return == 0 ? 'HEAD' : '4b825dc642cb6eb9a060e54bf8d69288fbee4904'; exec("git diff-index --cached --name-only {$against}", $output); $filename_pattern = '/\.php$/'; $exit_status = 0; foreach ($output as $file) { if (!preg_match($filename_pattern, $file)) { // don't check files that aren't PHP continue; } $lint_output = array(); exec("php -l " . escapeshellarg($file), $lint_output, $return); if ($return == 0) { continue; } echo implode("\n", $lint_output), "\n"; $exit_status = 1; } exit($exit_status);
ちなみに,これを,プロジェクトの .git/hooks/pre-commit にそのまま貼り付けて 「chmod -x pre-commit」 とかしてもOK.
でも,git init したときにすでに pre-commit の中にシェルスクリプト(とPerlのコード)がかかれてたりして,よくわからないからこれ全部PHPにしちゃうのもなんかな,と思ったので,今回は ~/.git/hooks/pre-commit として作成して,実行権限を付加.
プロジェクトの,.git/hooks/pre-commit を編集
を編集して,こちらも実行権限を付加.
ファイルの先頭(shebangのあと)に,
~/.git/hooks/pre-commit if test $? -ne 0 then exit 1 fi
を追加.
そうすると
実行時にsyntaxエラーがあると
% git commit -m " hook test" PHP Parse error: syntax error, unexpected $end, expecting ',' or ';' in hoge.php on line 12 Parse error: syntax error, unexpected $end, expecting ',' or ';' in hoge.php on line 12 Errors parsing hoge.php
とか表示されてコミットされない.
ついでにメッセージにChangesetのURLも含めるようにしてみた
githubのお遊びついでに、forkしてみた。
オリジナルのバージョンだと、チケットclose時のコメントに、チケットIDしか表示してくれないから、それだとChangesetへ飛びにくいので、ChangesetのURLを含めるようにしてみた。
てなわけで、Subversionもつかってて、チケットはTracで管理してて、でもGithubもたまに使いたいよ!って人は*1、ChangesetのURLも表示される
を使ってみるのもいいかもしれませんよ!
にしても
gitの(っていうかgithubの)forkって楽チンだなあ。すげえ。。
subversionと概念が違うっていうのがようやくわかった気がする。
*1:結構しぼってんなw
Github のコミットにHookしてTracのチケットをクローズしたり
最近Githubをようやく使い始めたsotarokです。
普段は、Subversionを使っているし、nequalの開発も主にSubversionを使っていて、BTSというかTODO管理というかにTracを使ってる。で、Tracの便利なところはSubversionと連携してくれるから、コミットログに「fixed #123」とか書けばチケットの#123をクローズしてくれたりするところなんだけど、Githubにソースを移行して相変わらずチケット管理をTracに任せているとこのHookが使えなくて不便。
そんなわけでGithubのコミット(push)にHookしてTracのチケット更新できるようにする。
GithubPluginをインストール
コレ。
gitからもってきてsetup.py。
% git clone git://github.com/davglass/github-trac.git % cd github-trac
simplejsonが入ってない場合は、easy_installで入れてから。入ってるならいらないけど。
% easy_install simplejson % sudo python setup.py install
trac.ini いじる
[components] github.* = enabled [github] apitoken = tekitounamojiretsu
apitoken のとこは適当な文字列入れる。
で、Apache再起動などさせると(mod_pythonで動かしてる場合)、管理コンソールのプラグインってとこに、
な感じの表示が。
Service Hooks に URLを設定
これはGithub側の設定。リポジトリの、Admin->Service Hooksに色々ある。
で、最初はTracのほうに入れるのかとおもって試してたけどうまくいかないから(後述)、davglass/github-trac · GitHub の説明に書いてある通り、一番上の Post-Receive URLs に、
http://trac.nequal.jp/github/tekitounamojiretsu
みたいなカンジで、tracのURL+ /github/ + apitokenに設定した文字列、を入力。
実際にコミットする
git commit -a -m "fixed #123" とかして、 git push origin master などしてgithubにpushしたタイミングで、Hookが動きますめでたしめでたし。
pullとかは試してないなあ。きっとなるんじゃないかな(てきと
Service HooksのTracんとこに入力したときはデータが来てないぽい
一応調べてみたんですが。GithubPlugin-0.4-py2.4.egg の github/github.py に
def processCommitHook(self, req): self.env.log.debug("processCommitHook") status = self.closestatus if not status: status = 'closed' data = req.args.get('payload') self.env.log.debug("data: %s" % data) # これ足した if data: jsondata = simplejson.loads(data) for i in jsondata['commits']: self.env.log.debug("status: %s" % status) self.hook.process(i, status) if self.autofetch: repo = Git(self.repo) try: repo.execute(['git', 'fetch']) except: self.env.log.debug("git fetch failed!")
で、Tracのログをdebugに設定して動かしてみてたら、Post-Receive URLsに入れたほうでHookが動いたときは、JSONで色々情報が渡されてるけど、TracのほうにURLとTokenを入力しても、それはどうやらきてなかった。だから当然Hookは動かないんだけど。でもちゃんと tracurl/github/token文字列 ってURLにアクセスはきてるんだけどね。
なんでだろ?このTracって何に使うんだろう? github 側の対応ミスとか?どなたか知ってたら教えてください。
まぁいいやとりあえずPost-Receive URLsで運用しちゃお。
というかんじでした。