最近やってる開発で以前書いた方法でTravisCIからCoverallsにカバレッジレポートを転送しようかと思ったのですが、デフォルト設定ではできないパターンがあったので行った対応とか書いてみます。

環境


  • sbt-coveralls 1.2.7

です。このsbt-coverallsプラグインでTravisCIからCoverallsにカバレッジレポートを転送します。

結論


先に結論を書いておくと、リポジトリのルートにbuild.sbtがない場合はsbt-coverallsプラグインの設定でgitリポジトリのパスを指定しないといけません。

構成とか


まず、今回のプロジェクトのディレクトリ構成はこんなかんじです。サブディレクトリにbuild.sbtを配置していました。

1
.
2
├── README.md
3
├── server-side
4
|    ├── build.sbt
5
|    ├── project
6
|    ...
7
|
8
├── .travis.yml
9
...

次に.travis.ymlはこうです。

1
sudo: false
2
language: scala
3
scala:
4
  - 2.12.6
5
jdk:
6
  - oraclejdk8
7
before_script:
8
  - "cd server-side"
9
script:
10
  - "sbt clean coverage test"
11
after_success: 
12
  - "sbt coverageReport coveralls"

サブディレクトリに切り替えてからビルド処理を行っています。

NoHeadException


これでビルドを走らせるとafter_successsbt coverageReport coverallsのカバレッジレポート転送処理が失敗します。ただし、失敗しますといってもafter_successキーが失敗するだけで、ビルドそのものに影響はありません。失敗するのはあくまでカバレッジレポートの転送だけです。

ログを確認すると下記のように「NoHeadException: No HEAD exists and no explicit starting revision was specified」というエラーが出力されていました。

1
 sbt coverageReport coveralls
2
[info] Loading settings for project server-side-build from plugins.sbt ...
3
[info] Loading project definition from /home/travis/build/YoshinoriN/ExampleProject/server-side/project
4
[info] Loading settings for project server-side from build.sbt ...
5
6
...(省略)
7
8
[info] Written HTML coverage report [/home/travis/build/YoshinoriN/ExampleProject/server-side/target/scala-2.12/scoverage-report/index.html]
9
[info] Statement coverage.: 4.31%
10
[info] Branch coverage....: 6.25%
11
[info] Coverage reports completed
12
[info] All done. Coverage was [4.31%]
13
[success] Total time: 5 s, completed Jan 13, 2019 3:30:32 PM
14
[info] Repository = ./.git
15
[error] org.eclipse.jgit.api.errors.NoHeadException: No HEAD exists and no explicit starting revision was specified
16
[error] 	at org.eclipse.jgit.api.LogCommand.call(LogCommand.java:148)
17
[error] 	at org.scoverage.coveralls.GitClient.lastCommit(GitClient.scala:63)
18
[error] 	at org.scoverage.coveralls.CoverallPayloadWriter.addGitInfo(CoverallPayloadWriter.scala:52)
19
[error] 	at org.scoverage.coveralls.CoverallPayloadWriter.start(CoverallPayloadWriter.scala:39)
20
[error] 	at org.scoverage.coveralls.CoverallsPlugin$.$anonfun$coverallsTask$2(CoverallsPlugin.scala:89)
21
[error] 	at org.scoverage.coveralls.CoverallsPlugin$.$anonfun$coverallsTask$2$adapted(CoverallsPlugin.scala:54)
22
[error] 	at scala.Function1.$anonfun$compose$1(Function1.scala:44)
23
[error] 	at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:40)
24
[error] 	at sbt.std.Transform$$anon$4.work(System.scala:67)
25
[error] 	at sbt.Execute.$anonfun$submit$2(Execute.scala:269)
26
[error] 	at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:16)
27
[error] 	at sbt.Execute.work(Execute.scala:278)
28
[error] 	at sbt.Execute.$anonfun$submit$1(Execute.scala:269)
29
[error] 	at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:178)
30
[error] 	at sbt.CompletionService$$anon$2.call(CompletionService.scala:37)
31
[error] 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
32
[error] 	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
33
[error] 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
34
[error] 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
35
[error] 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
36
[error] 	at java.lang.Thread.run(Thread.java:748)
37
[error] (coveralls) org.eclipse.jgit.api.errors.NoHeadException: No HEAD exists and no explicit starting revision was specified
38
[error] Total time: 1 s, completed Jan 13, 2019 3:30:33 PM

例外の前の行を見るとわかるのですが[info] Repository = ./.gitというログが出力されており、どうもsbt-coverallsの処理でgitリポジトリ(.gitディレクトリ)を使ってごにょごにょしているみたいです。今回はビルド前にディレクトリをサブディレクトリに切り替えており、当然サブディレクトリに.gitディレクトリはありません。

じゃあ、ルートディレクトリに変更してからsbt coverageReport coverallsを実行すればええかな?

といえばそういうわけでもなく、どうも調べた限りではsbtのタスクはbuild.sbtが存在するディレクトリでしか実行できないようです。つまりcd .. && sbt coverageReport coverallsとかでルートディレクトリに移動してから実行してもダメなんですね。今度はbuild.sbtがないと怒られてしまう。

sbt-coverallsのgitディレクトリ設定を変更する


あ、これ困ったな~。なんて思ってたんですが、ちゃんとPull Reqが出てて設定できるようになってました。

Configurable Git Repository Location

今回の場合だとbuild.sbtに下記のような感じで.gitディレクトリは一階層上であるということを示してやれば良いです。

1
org.scoverage.coveralls.Imports.CoverallsKeys.coverallsGitRepoLocation := Some("..")

後はビルド実行すれば通ります。先ほどと違って[info] Repository = ../.gitというふうに一階層をみにいっているのもログに出てます。

1
19.41s$ sbt coverageReport coveralls
2
[info] Loading settings for project server-side-build from plugins.sbt ...
3
[info] Loading project definition from /home/travis/build/YoshinoriN/ExampleProject/server-side/project
4
5
...(省略)
6
7
[info] All done. Coverage was [4.31%]
8
[success] Total time: 5 s, completed Jan 15, 2019 10:14:46 AM
9
[info] Repository = ../.git
10
[info] Generating reports for 33 files
11
[info] Adding file reports to the coveralls file (coveralls.json)
12
[info] Uploading the coveralls file (coveralls.json)
13
[info] Uploading to https://coveralls.io succeeded: Job #47.1
14
[info] https://coveralls.io/jobs/44141391
15
[info] (results may not appear immediately)
16
[success] Total time: 3 s, completed Jan 15, 2019 10:14:50 AM

おわり。