travis-ciでwindowsを使ってsbtでScalaプロジェクトのテストをする

2018年10月くらいからWindows使えるようになってたんですね。まだexperimentalな扱いみたいですが。

blog.travis-ci.com

そういうニュースを見た覚えもある気もするし、見てない気もするし、いずれにせよ全く試したことなかったんですが、今回試したのでblog書いておきます。

本題に入る前に、windowsでの(無料の?)CIといえばappveyorあたりが有名だと思いますが*1

www.appveyor.com

もちろん、今までも(ある意味)これからも、それ使ってもいいわけですが、 CIのサービス2つ設定するよりtravis-ciで全部済むならそのほうが基本的には便利なので、それに越したことはないですね。

ちなみに、appveyorといえば、自分が知っているScala関連のprojectだと、sbtやslickなどが設定しています

さてそろそろ本題に入りますが、travis-ciのwindows関連の公式リファレンスはこちら

https://docs.travis-ci.com/user/reference/windows/

このblog書いている時点だと、サポートしているのは以下の言語だけなようです。

C with language: c
C++ with language: cpp
Node.js with language: node_js
Rust with language: rust
Go with language: go
Bash language: bash or language: shell

つまりJavaすらサポートしてないので、現状ではJavaのインストール自体から手動でやる必要があります。

さすがに他にやってる人いるだろう、とググって以下をたどって、簡単にインストールするやつを作っている人がいたので、それ使うことにしました

https://travis-ci.community/c/environments/windows

https://travis-ci.community/t/java-support-on-windows/286

https://github.com/DanySK/Gravis-CI

このGravis-CI自体は、中身はjabbaという有名なJava自体のversion managerを利用しているだけのようです *2

github.com

それで、結果として出来た設定例がこちら

https://github.com/scalikejdbc/scalikejdbc/pull/1033

matrix:
  include:
  - os: windows
    language: bash
    env: JDK="adopt@1.8.212-04"
    before_script:
    - curl "https://raw.githubusercontent.com/DanySK/Gravis-CI/c8f400623d8f756ef7c/.install-jdk-travis.sh" --output .install-jdk-travis.sh
    - source .install-jdk-travis.sh
    - wget https://raw.githubusercontent.com/paulp/sbt-extras/0ee2dae2eba72efb4a464a5ad255e348696ecda7/sbt && chmod +x ./sbt
    script:
    - ./sbt "++ 2.12.8" test

かるく解説すると

  • osはwindowsを指定
  • languageはJavaとかScalaとか指定しても現時点ではエラーになるのでbashを指定
  • curlwgetはとりあえず使えるらしい*3
  • curlで上記のGravis-CIのscript経由でJavaをインストール*4 *5
  • wgetでsbt-extrasのshell script使ってsbt起動*6
  • あとは普通にそれぞれのproject毎にsbt testとかするだけ
  • scala-js動かしたい場合デフォルトでは( language: bashでは) node が入ってない*7ので、更に工夫が必要そう
  • windows上でだけscalafmtCheckが失敗する場合があった*8
  • 全部確かめてないけど、MySQLなどの各種ミドルウェアも、Linuxと同じ設定でデフォルトで動いてるのを期待するのは無理そう
  • 他にも色々なプロジェクトをビルドしてみると、色々と制約に引っかかりそうだが、まだあまり試してないので把握してない
  • windowsだけ落ちるテストを一旦pendingしたい場合は、たとえば以下のようなやつを書くと*9便利です。*10
val excludeTestsIfWindows = Set(
  "example.TestA",
  "example.TestB",
)

testOptions in Test in ThisBuild ++= {
  if (scala.util.Properties.isWin) {
    Seq(Tests.Exclude(excludeTestsIfWindows))
  } else {
    Nil
  }
}

といった感じです。 この程度なら十分実用的だとは思いますが、もっといい方法あるみたいな情報見つけたら教えてください。

Windowsでのビルド重視したいか、というとそこまでやる気あるわけでもないですが、気が向いたらもう少し自分が関わってるプロジェクトでWindowsのビルド設定追加してみようかと思います。

*1:というか個人的に他をあまり知らないだけ

*2:Gradle関連の設定も多少あるようだが、sbtのビルドに使うにはその部分余計だが、とはいえ害もないのでひとまずこれを使っている

*3:他にどこまで何が使えるのかよくわかってない

*4:ここはそれのREADMEの記述に従っただけ

*5:実質必要な部分20行とか30行程度?なので、なんなら全部コピペして組み込んでもいいかも

*6:sbt公式のwindowsインストーラーという方法もあるだろうけど、こっちでうまくいったし、こっちのほうが慣れてるので、こっちでいいかなぁ、という

*7:or pathに入ってない?

*8:scalafmt自体のバグなのか、制約なのか、version上げれば直るのか、あるいは・・・

*9:テストコード本体いじらなくていいので

*10:test class単位でしかfilterできないので、もっと細かくfilterしたいならテストコードいじったほうがいいが