Atlassian BambooでGoのカバレッジを表示してみた

はじめに

みなさんはCIツールに何を導入されていますか?

現在、アイスタイルではかねてから利用しているJenkinsの他に、Atlassian Bambooを一部のプロジェクトで利用し始めております。

そんなBambooなのですが、Go言語の自動テスト及びカバレッジが表示できるようにしてみようとしたところ、色々とハマりどころがありましたので備忘録も兼ねて紹介したいと思います。

なお、Bambooについて特に詳しいわけでもなんでもありませんので、有識者の皆様に、至らぬ点は教えていただけるとありがたいと思います。

テスト対象

今回はテスト対象として、すでにテストとカバレッジがそれぞれTravis CICOVERALLで担保されている弊社製のライブラリ、gomniを使いたいと思います。ちなみに、gomniは弊社でのGoプロダクト開発においてよく使われる共通関数を集めたライブラリです。

Bamboo上で設定していく

今回はBamboo自体の細かな説明は省略しますが、Bambooでビルドするにあたっては、

  • Plan(ビルドプロセス)
  • Project(Planを束ねたもの)

といったものを作る必要があります。
今回はプロジェクトとして色々試せるように用意したサンドボックスプロジェクトに、「テストとカバレッジレポート」というPlanを作成して作業していきます。

事前インストール

Bambooがインストールされているサーバーに事前に以下のものをインストールしておきます

cobertura-clover-transformがなぜ必要なのかは後ほど

ソースコードのチェックアウトタスクを修正

Planを作成するタイミングで、ソースコードのチェックアウトを行うタスクはPlanに追加されていると思いますので、選択し一部の設定の修正を行います。

弊社ではGoプロダクトのビルドを行うにあたって、GOPATHは各Projectのワーキングディレクトリ直下にgo/srcを作成して設定していますので、ここでCheckout Directoryの欄にgo/src/github.com/istyle-inc/gomniと入力しています。
お使いの環境でGOPATHを別なディレクトリにしたい場合は、そこに合わせて設定してあげてください。

テストとカバレッジレポートを作成するスクリプトタスクを追加

ソースコードのチェックアウト先を適切に設定したところで、テスト実行とカバレッジレポートの作成をするためにスクリプト実行のタスクを追加します。

ちなみに、Bamboo用のGo言語に関するプラグインを検索すると

github.com/edwinakatosh/go-bamboo-plugin というのが出てくるのですが、以下の事由から社内のGoプロジェクトのビルド環境に合致しないため今回は使用しません。

  • 依存関係解決を行うタスクが追加できるが、Godepのみの対応となっている
  • GOPATHでなくGOROOTを必須パラメータとしている

さて、スクリプト実行タスクを追加したら以下のようなスクリプトを挿入します

export GOPATH=${bamboo.build.working.directory}/go
export PATH=${PATH}:${GOPATH}/bin

go get github.com/modocache/gover
go get github.com/t-yuki/gocover-cobertura

cd ${GOPATH}/src/github.com/istyle-inc/gomni
glide install
rm -f *.cover.coverprofile

go test -v -covermode=count -coverprofile=numerics_float32.cover.coverprofile github.com/istyle-inc/gomni/numerics/float32
go test -v -covermode=count -coverprofile=numerics_float64.cover.coverprofile github.com/istyle-inc/gomni/numerics/float64
go test -v -covermode=count -coverprofile=numerics_int.cover.coverprofile github.com/istyle-inc/gomni/numerics/int
go test -v -covermode=count -coverprofile=numerics_int16.cover.coverprofile github.com/istyle-inc/gomni/numerics/int16
go test -v -covermode=count -coverprofile=numerics_int32.cover.coverprofile github.com/istyle-inc/gomni/numerics/int32
go test -v -covermode=count -coverprofile=numerics_int64.cover.coverprofile github.com/istyle-inc/gomni/numerics/int64
go test -v -covermode=count -coverprofile=numerics_int8.cover.coverprofile github.com/istyle-inc/gomni/numerics/int8
go test -v -covermode=count -coverprofile=numerics_uint16.cover.coverprofile github.com/istyle-inc/gomni/numerics/uint16
go test -v -covermode=count -coverprofile=numerics_uint32.cover.coverprofile github.com/istyle-inc/gomni/numerics/uint32
go test -v -covermode=count -coverprofile=numerics_uint64.cover.coverprofile github.com/istyle-inc/gomni/numerics/uint64
go test -v -covermode=count -coverprofile=numerics_uint8.cover.coverprofile github.com/istyle-inc/gomni/numerics/uint8
go test -v -covermode=count -coverprofile=strings.cover.coverprofile github.com/istyle-inc/gomni/strings
go test -v -covermode=count -coverprofile=times.cover.coverprofile github.com/istyle-inc/gomni/times
go test -v -covermode=count -coverprofile=types.cover.coverprofile github.com/istyle-inc/gomni/types

gover

gocover-cobertura < gover.coverprofile > cobertura.xml
cobertura-clover-transform cobertura.xml > clover.xml

rm -rf ${bamboo.build.working.directory}/target
mkdir -p ${bamboo.build.working.directory}/target/site/clover
go tool cover -html=gover.coverprofile -o ${bamboo.build.working.directory}/target/site/clover/index.html
cp clover.xml ${bamboo.build.working.directory}/target/site/clover/clover.xml

スクリプトを解説

1,2行目はGOPATHやPATHを設定しています。
4,5行目

go get github.com/modocache/gover
go get github.com/t-yuki/gocover-cobertura

github.com/modocache/gover は拡張子.coverprofileのファイルをすべて集約して一つのファイルに吐き出すツール、github.com/t-yuki/gocover-coberturaはgoのカバレッジプロファイルをcoberturaが読み取れる形式に変換してくれるツールです。事前にインストールしておいたcobertura-clover-transformと組み合わせるために利用します。

7-9行目

cd ${GOPATH}/src/github.com/istyle-inc/gomni
glide install
rm -f *.cover.coverprofile

依存関係の解決と、カバレッジプロファイルを前回のものが残っているケースや、誤ってコミットされてしまっている可能性を考慮し、念のため削除します。

11-24行目ではライブラリ内の各パッケージについてテストを実行しています。ご存知かと思いますが、カバレッジを出力する場合に複数のパッケージをワンライナーでテストしようとするとエラーが出力されてしまうので、それぞれ別なレポートファイルに出力するよう記述していきます。

26-29行目

gover
gocover-cobertura < gover.coverprofile > cobertura.xml
cobertura-clover-transform cobertura.xml > clover.xml

先程のgover, gocover-cobertura, cobertura-clover-transformを実行しています。

※ gocover-cobertura -> cobertura-clover-transformとする理由

Bambooには、Goのカバレッジプロファイルにきれいに対応されているカバレッジレポートツールがまだ無いので、Bambooに標準搭載されているCloverを使ってなんとか対応しようと思いましたが、Cloverに対応するカバレッジプロファイルを出力するツールも特にない(個人的に開発中ではありますが)状況でした。
ひとまず、goprofile -> cobertura用のXML -> Clover用のXMLという経路で変換することで確認までこぎつけています。

最後に31-34行目

rm -rf ${bamboo.build.working.directory}/target
mkdir -p ${bamboo.build.working.directory}/target/site/clover
go tool cover -html=gover.coverprofile -o ${bamboo.build.working.directory}/target/site/clover/index.html
cp clover.xml ${bamboo.build.working.directory}/target/site/clover/clover.xml

ここでは最終的にCloverのレポートを使ってカバレッジを表示させたいので、ワーキングディレクトリの下に

target/site/clover

ディレクトリを作成し、その配下に

  • clover用のXML(clover.xml)
  • coverツールを利用して出力できるHTMLファイル(index.html)

を配置しています。このディレクトリがtarget/site/cloverである理由は後述します。

Jobの設定でCloverを有効にする

ここまで来たらもう一息です。
Jobの設定画面の右側にあるMiscellaneousタブの設定をします。

この画面で以下の設定を行います。

  • Use Clover to collect Code Coverage for this build.のチェックボックスをON
  • IntegrationOptionsの項目にある、Clover is already integrated into this build and a clover.xml file will be produced.ラジオボタンを選択
  • Clover XML Locationの欄にtarget/site/clover/clover.xmlを入力

保存したらいよいよ実行です。

Run planをクリックしましょう!

結果を確認する

正常にスクリプトが実行されたら、Planのトップページを表示しましょう。
CloverというタブがPlan summaryのタブがあるエリアの右側にあると思いますので、そこをクリックしてください。

無事カバレッジ率が表示されています。

続いて、画面中ほどにClover Report (System) HTMLというリンクが表示されていると思いますのでクリックしてみましょう。

無事カバレッジ表示のHTMLまで表示されていると思います。

レポート出力先をtarget/site/cloverにする理由

先程レポートファイルの出力先をtarget/site/cloverにする旨を記載しましたが、これはカバレッジのHTMLファイルを出力するのに必要な手順でした。
カバレッジの%表示については、先の手順にてJobのMiscellaneousページで設定したClover XML Locationが参照されるのでどこに出力しても問題なく表示されますが、HTMLについてはこのtarget/site/clover配下のディレクトリを参照しに行っているようで、実際のところClover XML Locationに設定するパスはファイルさえ正常に出力されさえすれば任意の場所を指定してかまわないのですが、HTML表示までしたいという場合はtarget/site/cloverディレクトリが必要になるということでこのようにしています。

なお、target/site/clover配下を再帰的に参照しに行っているようなので、配下にディレクトリを作成してもかまわないのですが、index.htmlとして作成しておかないと、最初から表示されるようにはならないということだけ注意していただければと思います。

終わりに

いかがでしたでしょうか?
個人的にドキュメントや前例を検索してみた限りの感想を申し上げると、皆さんがGoでの開発プロジェクトをBambooでインテグレーションすることはほぼ無いかもしれませんが、利用することになったときに参考になれば幸いです。

ここまでご覧いただきありがとうございました!