GeekFactory

int128.hatenablog.com

Jenkinsでジョブの結果を集計する

Jenkinsはジョブを実行するだけでなく、結果を集計する機能にも優れています。Jenkinsには標準でJUnitの結果を集計する機能が付いており、これを応用すると、複数サーバで実行したジョブの結果を分かりやすく表示するといったことが簡単にできます。

複数サーバで同じジョブを実行するには Multi-configuration Project を使います。ジョブの設定で、実行したいサーバにチェックを入れると、同じスクリプトが指定したサーバで実行されます。そして、後処理に「JUnitテスト結果の集計」を追加すれば結果を集計することも可能です。

例として、各サーバの設定ファイルをdiffでチェックするジョブを考えてみましょう*1

リポジトリからお手本を取得した後、お手本とサーバの設定ファイルを比較するスクリプトを実行します。こんな感じ。

find . -type f | cut -d/ -f2- | while read path; do
 diff -u "$path" "/$path"
done

一方で、「JUnitテスト結果の集計」に与えるXMLは下記のような形式で十分です。本物のJUnitはもっと装飾の多いXMLを出力しますが、Jenkinsにはこれだけで十分です。

<testsuite>
 <testcase classname='server1' name='etc/resolv.conf' />
 <testcase classname='server2' name='etc/httpd/conf/httpd.conf'>
  <failure><![CDATA[
--- etc/httpd/conf/httpd.conf 2013-09-01 15:01:35.000000000 +0900
+++ /etc/httpd/conf/httpd.conf 2013-01-01 14:03:02.000000000 +0900
...
]]></failure>
 </testcase>
</testsuite>

スクリプトで結果のXMLを書き出すようにします。

#!/bin/bash
exec > >(tee result.xml)

echo '<testsuite>'
find . -type f | cut -d/ -f2- | while read path; do
 result=$(diff -u "$path" "/$path" 2>&1)
 code=$?

 # コマンドの実行結果をJUnit XMLに書き出す
 if [ $code -eq 0 ]
  then echo "<testcase classname='$HOSTNAME' name='$path' />"
  else echo "<testcase classname='$HOSTNAME' name='$path'><failure><![CDATA[$result]]></failure></testcase>"
 fi
done
echo '</testsuite>'

最後に、後処理の「JUnitテスト結果の集計」で result.xml を取り込むようにします。

これでジョブを実行すると、複数サーバで実行したコマンドの結果が集約されます。あの見慣れたJUnit結果の画面が表示されます。本稿ではdiffの例で試してみましたが、他のコマンドでもこのパターンが使えると思います。

*1:設定ファイルのチェックならもっと良い手段があると思いますが、とりあえず例で。