Scala/sbt+Jenkinsで継続インテグレーション環境を構築する (+specs2+scalariform+scalastyle+scct)

JenkinsでScala(で標準的なsbt)のCI環境を構築する。参考にしたページは、

* https://github.com/sbt/sbt-scalariform
* http://www.scalastyle.org/sbt.html
* https://github.com/SCCT/scct
* http://etorreborre.github.io/specs2/
* http://d.hatena.ne.jp/xuwei/20130930/1380511344

scctは元々0.2-snapshotを公開していたサイトではすでに古くなっていてforkバージョンを使用している。

ファイルを準備する
---------------

### project/plugins.sbt

``` scala
addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.2.1")

addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.3.2")

resolvers += "sonatype-releases" at "https://oss.sonatype.org/content/repositories/releases/"

addSbtPlugin("com.github.scct" % "sbt-scct" % "0.2.1")
```

### build.sbt

``` scala
scalariformSettings

org.scalastyle.sbt.ScalastylePlugin.Settings

ScctPlugin.instrumentSettings

libraryDependencies ++= Seq(
    "org.specs2" %% "specs2" % "2.3.4" % "test"
)

testOptions in Test += Tests.Argument("junitxml", "html", "console")
```

### .gitignore

```
target/*
project/target/*
project/project/target/*
```

### src/main/scala/hello.scala

``` scala
package hello

object Hello extends App {
  println(hello)

  def hello = "hello, world."
}
```

### src/test/scala/helloSpec.scala

``` scala
package hello

import org.specs2._
import specification._

class HelloSpec extends script.Specification with Grouped {
  def is = s2"""
  + hello は "hello, world." という文字列を返す
  """

  "" - new group {
    eg := Hello.hello mustEqual "hello, world."
  }
}
```

確認する
-------

```
$ sbt test
[info] Loading project definition from /Users/erukiti/work/test3/project
[info] Set current project to test3 (in build file:/Users/erukiti/work/test3/)
[info] HelloSpec
[info]   + hello は "hello, world." という文字列を返す
[info]   
[info] Total for specification HelloSpec
[info] Finished in 18 ms
[info] 1 example, 0 failure, 0 error
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[success] Total time: 2 s, completed 2013/11/22 0:00:44
```

sbt test を走らせるとこんな感じで、正しくテストが通るはずだ

```
$ sbt scalastyle
[info] Loading project definition from /Users/erukiti/work/test3/project
[info] Set current project to test3 (in build file:/Users/erukiti/work/test3/)
warning file=/Users/erukiti/work/test3/src/main/scala/hello.scala message=Header does not match expected text line=1
warning file=/Users/erukiti/work/test3/src/main/scala/hello.scala message=Regular expression matched 'println' line=4 column=2
warning file=/Users/erukiti/work/test3/src/main/scala/hello.scala message=Public method must have explicit type line=6 column=6
warning file=/Users/erukiti/work/test3/src/main/scala/hello.scala message=File must end with newline character
Processed 1 file(s)
Found 0 errors
Found 4 warnings
Finished in 5 ms
[success] created: /Users/erukiti/work/test3/target/scalastyle-result.xml
[success] Total time: 0 s, completed 2013/11/22 0:01:46
```

sbt scalastyle では、帰ってくる警告の数は違っていたりするかもしれないが、このような感じで実行できれば良い

```
$ sbt scct:test
[info] Loading project definition from /Users/erukiti/work/test3/project
[info] Set current project to test3 (in build file:/Users/erukiti/work/test3/)
[info] HelloSpec
[info]   + hello は "hello, world." という文字列を返す
[info]   
[info] Total for specification HelloSpec
[info] Finished in 18 ms
[info] 1 example, 0 failure, 0 error
scct: [test3] Generating coverage report.
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[success] Total time: 3 s, completed 2013/11/22 0:03:00
```

sbt scct:test では、テスト結果に加えて、scct によるカバレッジ計測結果が出力されるはずだ

ここまで正常にセットアップできているなら、git init してからコミットするなり、プロジェクト用のリポジトリに push するなりすれば準備はできた。

Jenkins設定
----------

まず Jenkins のプラグインがいくつか必要になるのでセットアップしておく

* Checkstyle plug-in
* Jenkins Cobertura plugin

必要に応じてgit関連のプラグインなども入れておけば良い。

### ジョブ作成を行う

* フリースタイル・プロジェクトのビルドを選択する

### ソースコード管理

リポジトリに応じて適切なものを選ぼう

### ビルド手順の追加

シェルの実行を選ぶ (sbtプラグインを使うのも手だが、僕の手元ではうまく行かなかった)

```
/FULLPATH/sbt -Dsbt.log.noformat=true -Xm1024 clean test scalastyle scct:test
```

sbt のパスは which sbt などを使って調べておこう

### ビルド後の処理の追加 (Checkstyle警告の集計)

集計するファイル

```
target/scalastyle-result.xml
```

### ビルド後の処理の追加 (Cobertura カバレッジ・レポートの集計)
Cobertura XMLレポート パターン

```
target/*/coverage-report/cobertura.xml
```

### ビルド後の処理の追加 (JUnitテスト結果の集計)

テスト結果XML

```
target/test-reports/*.xml
```

これで設定はできたので、保存をしてから、ビルドを実行してみよう。