2010年9月22日水曜日

ストレージサーバ - その8 - SVNのコミットメール送信対応

ソースコード管理に関して、
誰かが変更を加えたときメールで通知してくれるとありがたいので対応します。
最初に以下のコマンドを実行し、nkf をインストールします。
# emerge 'nkf'
メールサーバには送信専用の"ssmtp"を利用していますが、
今のままだと受信拒否されるサーバがあるので変更を加えます。
# vi /etc/ssmtp/ssmtp.conf
で設定ファイルを開き、
FromLineOverride=YES
を追加します。
なお、メールを送信するときの送信元(Fromヘッダ)のドメイン部は、
"mailhub"で指定しているメールサーバ(インターネット側)のDNS登録内容(MXレコード等)と矛盾がないようにしなければなりません。
さもないとメールが受信拒否される可能性があります。
ソースコード管理サーバsvnで更新(コミット)の情報を生成したり、
それをまとめたRSSを生成したいので以下を実行します。
# cd /usr/local/bin
# touch svn_rss
# touch svn_rss_item
# touch svn_xml
# chmod 755 svn_rss
# chmod 755 svn_rss_item
# chmod 755 svn_xml
これらスクリプトのソースコードは最後に記述します。
ソースコード管理の各領域(ここでは'*'であらわす)において以下を実行します。
# cd /mnt/storage/svn/*/hooks
# touch post-commit
# chmod 755 post-commit
これらpost-commitのソースコードは最後に記述します。
ソースコード管理サーバsvnで、
更新(コミット)をメール通知させるには前節の作業と合わせて以下を実行する。
# cd /usr/local/bin/
# touch svnlog2txt.php
# touch svn_update_info
# touch svn_update_mail.php
# chmod 755 svnlog2txt.php
# chmod 755 svn_update_info
# chmod 755 svn_update_mail.php
ソースコード管理の各領域(ここでは'*'であらわす)において、
"/mnt/storage/svn/*/hooks/post-commit"の最後に以下の行を追加して完了です。
svn_update_info "$REPOS" "$REV" "$web" | svn_update_mail.php "$repname" "$REV" $group
最後にスクリプトの内容を記述します。
# more /usr/local/bin/svn_rss
#!/bin/sh

if [ "X$1Y" = "XY" ];
then
        echo "set first argument as <repository path>." 1>&2
        exit 1
fi
if [ "X$2Y" = "XY" ];
then
        r=`svnlook youngest "$1"`
else
        r="$2"
fi
if [ "X$3Y" = "XY" ];
then
        count=0;
else
        count=$(($3-1));
fi

repname=`echo "$1" | sed -e 's/.*\/\([^\/].*\)/\1/'|awk -F/ '{print $1}'`

echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
echo "<rss version=\"2.0\">"
echo "<channel>"
echo "<title>svn [$repname] on hoge</title>"
if [ "X$4Y" != "XY" ];
then
        echo "<link>$4</link>"
fi
echo "<language>ja</language>"
d=`date "+%a, %d %b %Y %H:%M:%S %z"`
echo "<pubDate>$d</pubDate>"
echo "<description>the committing information of [$repname].</description>"

for rev in `seq $r -1 $(($r-$count)) | sed -e '/^0$/,$d'`;
do
if [ "X$4Y" = "XY" ];
then
        svn_rss_item "$1" "$rev"
else
        svn_rss_item "$1" "$rev" "$4"
fi
done

echo "</channel>"
echo "</rss>"

# more /usr/local/bin/svn_rss_item
#!/bin/sh

if [ "X$1Y" = "XY" ];
then
        echo "set first argument as <repository path>." 1>&2
        exit 1
fi
if [ "X$2Y" = "XY" ];
then
        r=`svnlook youngest "$1"`
else
        r="$2"
fi

d=`svnlook date -r "$r" "$1" 2> /dev/null` || exit 1
d=`echo "$d" | sed -e 's/^[^ ]* \([^ ]* [^ ]*\) (\(.*\))$/\2 \1/' 2> /dev/null`
a=`svnlook author -r "$r" "$1" 2> /dev/null` || exit 1
echo "<item>"
echo "<title>Revision $r</title>"
echo "<pubDate>$d</pubDate>"
echo "<author>$a</author>"

if [ "X$3Y" != "XY" ];
then
        echo "<link>$3/$r.xml</link>"
fi

echo "<description><![CDATA["
svnlook log -r "$r" "$1" 2> /dev/null | svnlog2txt.php 2> /dev/null
echo "----------------------------------------"
svnlook changed -r "$r" "$1" 2> /dev/null
echo "]]></description>"
echo "</item>"

# more /usr/local/bin/svn_xml
#!/bin/sh

if [ "X$1Y" = "XY" ];
then
        echo "set first argument as <repository path>." 1>&2
        exit 1
fi
if [ "X$2Y" = "XY" ];
then
        r=`svnlook youngest "$1"`
else
        r="$2"
fi

repname=`echo "$1" | sed -e 's/.*\/\([^\/].*\)/\1/'|awk -F/ '{print $1}'`

d=`svnlook date -r "$r" "$1" 2> /dev/null` || exit 1
d=`echo "$d" | sed -e 's/^[^ ]* \([^ ]* [^ ]*\) (\(.*\))$/\2 \1/' 2> /dev/null`
a=`svnlook author -r "$r" "$1" 2> /dev/null` || exit 1
echo "<?xml version=\"1.0\" encoding=\"Shift_JIS\"?>"
echo "<item>"
echo "<title>svn [$repname] revision $r</title>"
echo "<pubDate>$d</pubDate>"
echo "<author>$a</author>"
echo "<description><![CDATA["
svnlook log -r "$r" "$1" 2> /dev/null | svnlog2txt.php 2> /dev/null | nkf -Ws
echo "]]></description>"
echo "<files>"
svnlook changed -r "$r" "$1" 2> /dev/null | sed -e 's/^\([^ ]*\) *\(.*\)$/<file
status="\1">\2<\/file>/'
echo "</files>"
echo "<diff><![CDATA["
svnlook diff -r "$r" "$1" 2> /dev/null
echo "]]></diff>"
echo "</item>"

# more /mnt/storage/svn/*/hooks/post-commit
#!/bin/sh
REPOS="$1"
REV="$2"
web="<生成するドキュメント類の置き場所(ディレクトリ)のURL>"
htdocs="<生成するドキュメント類の置き場所(ディレクトリ)のパス>"
group="<ユーザ管理に利用するldapのouの名前>"
repname=`echo "$REPOS" | sed -e 's/.*\/\([^\/].*\)/\1/'|awk -F/ '{print $1}'`
svn_rss "$REPOS" "$REV" 20 "$web" > $htdocs/news.rss
svn_xml "$REPOS" "$REV" > $htdocs/$REV.xml

# more /usr/local/bin/svnlog2txt.php
#!/usr/bin/php
<?
        while(!feof(STDIN)){
                $in="#".fgets(STDIN);
                $i=1;
                $out="";
                while(1){
                        $j=strpos($in,'?\\',$i);
                        if($j==FALSE){
                                $out.=substr($in,$i);
                                break;
                        }
                        $out.=substr($in,$i,$j-$i);
                        $val=substr($in,$j+2,3);
                        $out.=sprintf("%c",intval($val)&0xff);
                        $i=$j+5;
                }
                fputs(STDOUT,$out);
        }
?>
# more /usr/local/bin/svn_update_info
#!/bin/sh
if [ "X$1Y" = "XY" ];
then
        echo "set first argument as <repository path>." 1>&2
        exit 1
fi
if [ "X$2Y" = "XY" ];
then
        r=`svnlook youngest "$1"`
else
        r="$2"
fi

if [ "X$3Y" != "XY" ];
then
        echo "feed : $3/news.rss"
        echo "detail : $3/$r.xml"
fi

d=`svnlook date -r "$r" "$1" 2> /dev/null` || exit 1
d=`echo "$d" | sed -e 's/^[^ ]* \([^ ]* [^ ]*\) (\(.*\))$/\2 \1/' 2> /dev/nul`
a=`svnlook author -r "$r" "$1" 2> /dev/null | nkf -Wj` || exit 1
echo "date : $d"
echo "author : $a"
echo
echo "changed files :"
svnlook changed -r "$r" "$1" 2> /dev/null | nkf -Wj
echo
echo "log :"
svnlook log -r "$r" "$1" 2> /dev/null | svnlog2txt.php  2> /dev/null | nkf -Wj

# more /usr/local/bin/svn_update_mail.php
#!/usr/bin/php

<?
$title="svn [".$argv[1].":".$argv[2]."]";
$body="svn [".$argv[1]."] is updated to revison #".$argv[2].".\r\n\r\n";
$from="From: hoge@hoge.com\r\nContent-Type: text/plain; charset=\"ISO-2022-JP\"\r\nContent-Transfer-Encoding: 7bit";

$out="";
while(!feof(STDIN)){
        $in=fgets(STDIN);
        $out.=$in;
        $out.="\r\n";
}
$body.=$out;

$ldap=ldap_connect("hoge");
if(!$ldap){
        echo "Could not connect to ldap server.<br/>";
        exit;
}
if(!ldap_bind($ldap,"cn=root,o=hoge,c=com","<パスワード>")){
        echo "Could not bind to ldap server.<br/>";
        exit;
}

if($arvg[3]=="")
        $env_group="test";
else
        $env_group=$arvg[3];

$entries=ldap_search($ldap,"ou=".$env_group.",o=hoge,c=com","(objectclass=organizationalPerson)",array("cn","mail"));
for($entry=ldap_first_entry($ldap,$entries);$entry!=false;$entry=ldap_next_entry($ldap,$entry)){
        $value=ldap_get_attributes($ldap,$entry);
        if($value["mail"][0]!="")
                mail($value["mail"][0],$title,$body,$from);
}

ldap_unbind($ldap);
?>

0 件のコメント:

コメントを投稿