sbt-revolver
sbt-revolver copied to clipboard
Fails to run in test configuration scope despite correct test:reStart::mainClass
For esoteric reasons (but reasonable ones can probably be imagined), I have some projects with executable classes living in the sbt test configuration. test:run
works fine and show test:reStart::mainClass
is set as expected, but running it fails. Here is a trivial reproduction:
$ mkdir -p /tmp/revolver-test/{project,src/test/scala}
$ cd /tmp/revolver-test
$ echo 'sbt.version = 1.0.4' > project/build.properties
$ echo 'addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1")' > project/plugins.sbt
$ cat <<'EOF' >> src/test/scala/Hello.scala
> object Hello extends App {
> println("Hello, world!")
> }
> EOF
$ sbt test:reStart
[info] Loading settings from plugins.sbt ...
[info] Loading global plugins from /Users/cmartin/.sbt/1.0/plugins
[info] Loading settings from plugins.sbt ...
[info] Loading project definition from /private/tmp/revolver-test/project
[info] Set current project to revolver-test (in build file:/private/tmp/revolver-test/)
[info] Application revolver-test not yet started
[error] java.lang.RuntimeException: No main class detected!
[error] at scala.sys.package$.error(package.scala:27)
[error] at spray.revolver.Actions$.$anonfun$startApp$2(Actions.scala:38)
[error] at scala.Option.getOrElse(Option.scala:121)
[error] at spray.revolver.Actions$.startApp(Actions.scala:38)
[error] at spray.revolver.Actions$.restartApp(Actions.scala:30)
[error] at spray.revolver.RevolverPlugin$.$anonfun$settings$6(RevolverPlugin.scala:58)
[error] at scala.Function1.$anonfun$compose$1(Function1.scala:44)
[error] at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:42)
[error] at sbt.std.Transform$$anon$4.work(System.scala:64)
[error] at sbt.Execute.$anonfun$submit$2(Execute.scala:257)
[error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:16)
[error] at sbt.Execute.work(Execute.scala:266)
[error] at sbt.Execute.$anonfun$submit$1(Execute.scala:257)
[error] at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:167)
[error] at sbt.CompletionService$$anon$2.call(CompletionService.scala:32)
[error] at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error] at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
[error] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
[error] at java.lang.Thread.run(Thread.java:745)
[error] (*:reStart) No main class detected!
[error] Total time: 0 s, completed Dec 28, 2017 1:11:50 AM
Not certain yet how this might be achieved in plugins, or if there's a better way, but a workaround is to duplicate the task definition inConfig(Test)
:
lazy val hello = (project in file("."))
.settings(
inConfig(Test) {
import spray.revolver.Actions._
reStart := Def.inputTask{
restartApp(
streams.value,
reLogTag.value,
thisProjectRef.value,
reForkOptions.value,
(mainClass in reStart).value,
(fullClasspath in reStart).value,
reStartArgs.value,
startArgsParser.parsed
)
}.dependsOn(products in Compile).evaluated
}
)
Unfortunately with this ~test:reStart
triggered execution doesn't watch main source files, tried many forms of watchSources
and couldn't resolve that yet. Edit: this part is possibly sbt's fault, seems like there were a slew of file watch regressions in 1.0.x, follow the rabbit hole from sbt/io#102 and sbt/io#82).