PlaggerでCommit2Mail on Subversion
ここ数日Plaggerで遊んでいました。
あれだけ担当内でRuby使えと言ってまわったのにPerlかよ!という突っ込みはさておき。
Plaggerが何か知らない人はhttp://tokyo.yapcasia.org/wiki/plugin/attachments/SlidesList/Plagger.pdfを読むと良いです。
うちの担当ではSVNを利用してますが、そのサーバーがファイアウォールで守られたマシン室に設置してあります。
これはこれでセキュリティが守られるのでいいんですが、マシン室から対外アクセスできないので、同時に利用しているTracのmail notification機能(SVNにコミットしたらメールしてくれる機能。なんでSVNじゃなくてTracについてるかは謎。)が使えないことになります。SMTPサーバがマシン室とは違う場所に置いてあるから。
でもこの機能がないとすごーく不便なので、どうしようか考えてました。
で、最近トラックバック先(MASATOの開発日記: http://www.sutosoft.com/room/archives/000252.html)で素晴らしいスクリプトを見つけたので
というのをやってみることにしました。
こういう環境ってよくあるのではないかと思いますので、作業メモを書いておきます。
ただしすっっっっっごい面倒くさかったので一部うろ覚えです。
自席マシンにPlaggerをインストールする、のまえにインターネットアクセスできるようにする。
Plaggerのインストールは各所で言われているようにすごくめんどくさいです。
自席マシンのOSはFedora Core 3なので
http://www.ark-web.jp/sandbox/wiki/index.php?plagger%2Finstall#kb0c360f
を参考にしようとしましたが、cpanをインストールするときに、「そもそもインターネットアクセスの設定をしてなかった」ということに気づきました。
といっても社内ネットワークには接続されているので、あとはプロキシ認証を通すだけです。
http://bbs.fedora.jp/read.php?FID=9&TID=3295
によると
$ export http_proxy=http://user:pass@XXXX.XXXX.XXXX.XXXX:port/
とするそうです。認証つきプロキシの設定に関する情報が他に見つからなかったので助かりました。
ただし、yumは内部でFTP使ってるかもしれないので
$ export http_proxy http://user:pass@proxy.xxxx.jp:8080/ $ export ftp_proxy http://user:pass@proxy.xxxx.jp:8080/ $ export HTTP_PROXY http://user:pass@proxy.xxxx.jp:8080/ $ export FTP_PROXY http://user:pass@proxy.xxxx.jp:8080/
としておくのが無難です。
環境変数名の大文字小文字はコマンドによって区別するのとしないのがあるらしいので、どっちもやっておくのがよいです。
なお、同掲示板にシェルスクリプトを作っておく方法が用意されていますが、IDとパスワードがモロばれになるのでやめておいたほうがよいです。
exportしたあとは
$ history -c
でちゃんとコマンド履歴を消しておきます。
でもログアウトするとこの環境変数設定が無効になるのでかなり面倒です…
http://www.ark-web.jp/sandbox/wiki/index.php?plagger%2Finstall#kb0c360f
を参考にyumります。
yum install gnupg yum install ncftp yum install unzip yum install gcc yum install make yum install libxml2-devel yum install libxml-devel yum install expat-devel yum install openssl-devel
で、
yum install perl-Plagger
したんですが無いといわれる始末。
しょうがないので、CPAN経由でインストールすることにします。(つづく)
補足
http://blog.woremacx.com/2006/03/plagger_yum.html
という記事がありまして、非常に間単にPlaggerがインストールできると評判なのですが、Fedora Core 3では無理みたいです。
というのもリンク先で参照しているファイルがなくなっているので、URL削っていったら
http://pub.woremacx.com/worepo/
にFC6のリンクが…
それでも無理やり
$ wget http://pub.woremacx.com/worepo/worepo-release-6.rpm $ rpm -ivh worepo-release-6.rpm
とかやったら、yumするときにhttp://pub.woremacx.com/worepo/をyumのサイトリストにしてしまい、(しかも「サイトになにもないよー」という感じのエラーメッセージがでて)yumでなにもできなくなりました。
CPANインストールのときにもミラーサイト(http: -- that host a CPAN mirror.の後に番号で示すやつ)が一切リストアップされなくて原因がわからなかったのですが、これっぽいです。
もしくはCPANのurllistのせい。
/etc/yum.repos.d
にwo.repoファイルがあって、おそらくそれを参照していることはわかりました。
直し方はrpmファイルをwgetしてきて、
$ rpm -Uvh worepo-release-6.rpm
とすればよいです。(http://経由でもいいのかな?)
次のcpanインストールとか並行してやっていたので、問題が絡み合って原因がわけわかんなくなるところでした…危なかった。
自席マシンにPlaggerを入れる、の前にcpanを使えるようにする。
CPANでPlaggerがインストールできると簡単なので、cpan(cpan専用のyumみたいなもの)をインストールします。
$ perl -MCPAN -e 'CPAN::Shell->install(CPAN::Shell->r)'
でいけるみたいですが、当然のごとくエラーでます。
bat 'urllist'といわれているので、ググると
http://www.drk7.jp/MT/archives/000885.html
によさげな記事がありました。
CPANもyumと同じくサイトリストがあって、それを参照するそうです。
cpan> o conf
とすると、CPANの環境変数が一覧ででるので確認すると、プロキシとurlリストがおかしいです。
yumと違ってproxy_user、proxy_passがあるので、ユーザIDとパスワードはこちらに書いておくようです。
cpan cpan> o conf http_proxy http://プロキシ名:ポート番号 cpan> o conf ftp_proxy http://プロキシ名:ポート番号 cpan> o conf proxy_user ユーザ名 cpan> o conf proxy_pass パスワード cpan> o conf urllist push http://どっか/ cpan> o conf commit
とすればよいようです。urllistは3つくらい登録しておきました。
最後にコミットしないと反映されないので気をつけます。
$ perl -MCPAN -e 'CPAN::Shell->install(CPAN::Shell->r)'
とやりましたが最初はurllistが悪かった(設定してなかった)ので、
エラーしまくりました。
何回かトライして*1みてインストールできたので、
cpan> install Plagger
しましたがエラー。
依存パッケージがあるみたいです…
何回やっても駄目です。
ということで、
cpan> force install Plagger
フォースインストールしてしまいました。まどーせperl使ってないですし。
地道に解決しようとしないところがシステム運用には向いてないと思います。
そしたら、
$ plagger
してみます。plagger特有のエラーがでたらOK。
Plaggerの設定
Plaggerの三大罠を解決しておきます。
1. のEncodeモジュールはやらなくても大丈夫だったけど
assetと改行はやらないと動かないので気をつけましょう。
http://subtech.g.hatena.ne.jp/otsune/20060828/PlaggerTrap
そしてassetsの罠を回避するためにhttp://search.cpan.org/~miyagawa/Plagger-0.7.17/lib/Plagger.pm*2からファイルを落としてきます。LinuxにFTPして(Linuxで直接wgetしてもいいけど)
$ tar xvzf Plagger-0.7.9.tar.gz
で解凍したらassetsフォルダをコピーします。(とりあえずここでは/usr/etc/plagger/assetsにコピーしました)
で、yamlを書くと。yamlのデフォルトの場所は/usr/bin/config.yamlです。
global: assets_path: /usr/etc/plagger/assets timezone: Asia/Tokyo log: lovel: info plugins: - module: Subscription::Config config: feed: - url: http://SVNのホスト名/適当なパス/commit.rdf - module: Filter::Rule rule: module: Deduped - module: Filter::EntryFullText rule: module: Deduped - module: Publish::Gmail config: mailto: 送り先メールアドレス mailfrom: mail@example.co.jp mailroute: via: smtp host: SMTPサーバの名前
最後に改行を忘れずに。
なお、Filter::Rule, Filter::EntryFullTextは、同じエントリを取得しないためのフィルタです。
http://emasaka.blog65.fc2.com/blog-entry-156.html
plaggerはデーモンではないので、かならず重複エントリを取ってきてしまいますから、メール通知する場合は、これをはさまないと使いづらいです。
SubversionサーバにXML::RSSをインストールする
SubversionサーバにXML::RSSを入れます。
外にアクセスできないので、手動でCPANからとってきます。割りと面倒でした。
ここを参考にしてインストールしました。
http://www.nurs.or.jp/~sug/homep/rss/rss2.htm
上記サイトだとXML::RSSとXML**Parserだけで良いと書いてありますが、実際は10コくらい入れました。
perl -MXML::RSS -e ' print $XML::RSS::Version'
とかやるとエラーメッセージがでるので、足りないモジュールをインストールします。
CPANモジュールのインストールは簡単ですね。
Subversionサーバにcommit-rss.plを設置する。
コミットされたメッセージをRDF(RSS)に変換するためにトラックバック先のスクリプトを設置します。
apacheユーザが入れない場所においちゃうと駄目なので注意です。
/path/to/svn/hooks/post-commitに、以下のように追記します。
REPOS="$1" REV="$2" # feed rss export LANG=ja_JP.utf8 export LC_ALL=ja_JP.utf8 export LANGUAGE=ja_JP.utf8 PERL_BADLANG=0; export PERL_BADLANG touch /tmp/log.txt ( pushd . cd トラックバック先のスクリプトが置いてある場所 perl commit-rss.pl \ $REPOS \ $REV \ "Commit RSS Feed" \ http://path/to/repository/ \ 20 \ RSSを出力したいパス(apacheで動かしているなら外部公開できる場所) popd ) > /tmp/log.txt 2>&1
$REPOSと$REVはpost-commitに与えられる第一引数と第二引数です。
最初エラーがでるので、エラーメッセージをどっかに保存しとくのが良いです。ここでは/tmp/log.txtに保存してます。
あと、export文は試行錯誤の名残です。なくても動くかもしれません。環境によって変わるので色々いじるのがよいかと。
さらに、touchはしなくてよいかと思います。
で、肝心のスクリプトですが、そのままでは動きませんでした。
書き換え箇所は以下の2点です。
1点目:SVNサーバのデフォルトエンコードを変更(元スクリプトはWindows前提なので)
< my $host_encode = 'sjis' ; > my $host_encode = 'euc' ;
2点目:エンコーディング箇所を変更
ちょっと長いので変更後のみ示します。
# log はエンコードされている(LANGに依存) # my $logmessage = '?\229?\191?\152?\227?\130?\140?\227?\129?\166?\227?\129?\132?\227?\129?\159?\227?\128?\130' ; $logmessage =~ s/\?\\([0-9]..)/pack('C', $1)/eg ; # "?\000" のエンコードを 戻す utf8::decode($logmessage); print utf8::is_utf8($logmessage) ? 'utf' : 'not utf'; # unix # Jcode::convert(\$logmessage, $encode, $host_encode ) if ($encode ne $host_encode); # 目的の文字コードへ変換 # windows ? 内部で特殊な変換がかかっているぽい # Jcode::convert(\$logmessage, $encode, 'utf8' ) if ($encode ne 'utf8'); # 目的の文字コードへ変換
おそらくperlのバージョンが関係していますが、Perl5.8以降はutf8に対して特別な処理が掛かっているようです。
このへんhttp://www.rwds.net/kuroita/program/Perl_unicode.htmlとかこのへんhttp://www.hikoboshi.org/perl/doc/encode.htmlを参考にさせていただきました。
色々試していたところ、use utf8プラグマなどつけるとログメッセージをスクリプト上に固定リテラルで書いたときはうまくいくのですが、引数として与えられたのを処理するにはutf8::decode()して「utf8フラグ」をつけなければならないようです。
(decodeでフラグが付くのは妙な感じですが)
で、Jcodeでのエンコードはしませんでした。
昔はjcode.plを使ってたような気がしますが時代が変わったんですね。
というかperlは言語処理用の言語のくせしてマルチバイト関連でわかりづらいところが多すぎです。これの解明に時間が掛かりまくりました。
なお、調査される際は、コミットメッセージを「あ」だけにしておくとよいと思います。
utf-8では日本語文字は3バイトになるので、どうなっているかわかりやすいです。
さらにOSの環境変数との絡みでもエラーがでまして、失敗すると先ほどの/tmp/log.txtに
svnlook: error: cannot set LC_ALL locale svnlook: error: environment variable LANG is ja_JP.sjis svnlook: error: please check that your locale name is correct
などでます。
post-commitのほうでいろいろexportしてみてください。
ということで後は運用するだけです。
1週間くらいはベータテストしてみようかと思います。
*1:M/MI/MIYAGAWA/Plagger-0.7.17.tar.gzが壊れているからremoveするのをお勧めするよとかいうエラー
*2:http://search.cpan.org/~miyagawa/Plagger-0.7.9/lib/Plagger.pmと書いていましたが、誤りです。otsuneさんご指摘ありがとうございます。