Ensure 're-start' task automatically runs before it:test - scala

Is it possible to get the re-start (aka reStart) task to automatically run before I run the IntegrationTest target (it:test)?
I thought this would do it:
test <<= (test in IntegrationTest) dependsOn reStart
However, I'm getting this error:
build.sbt:54: error: not found: value reStart
test <<= (test in IntegrationTest) dependsOn reStart
^
[error] Type error in expression
By adding import Revolver._ I got a bit further, but it still fails. Now I get a more descriptive error, however:
build.sbt:55: error: type mismatch;
found : sbt.InputKey[spray.revolver.AppProcess]
required: sbt.Scoped.AnyInitTask
(which expands to) sbt.Def.Initialize[sbt.Task[T]] forSome { type T }
test in IntegrationTest <<= (test in IntegrationTest) dependsOn reStart
Is there a way to get around that?

You can define special TaskKey-typed task for that like this (working example):
lazy val reStart0 = TaskKey[AppProcess]("re-start-0")
lazy val emptyArgs = SettingKey[revolver.Actions.ExtraCmdLineOptions]("empty-args")
lazy val projectA = Project(
id = "hello-a",
base = file("./a"),
settings = Project.defaultSettings ++ Revolver.settings
).settings(
emptyArgs := revolver.Actions.ExtraCmdLineOptions(Nil, Nil),
reStart0 <<= {
(streams, Revolver.reLogTag, thisProjectRef, Revolver.reForkOptions, mainClass in Revolver.reStart, fullClasspath in Runtime, Revolver.reStartArgs, emptyArgs)
.map(revolver.Actions.restartApp)
.dependsOn(products in Compile)
}
)
lazy val projectB = Project(
id = "hello-b",
base = file("./b"),
settings = Project.defaultSettings ++ Revolver.settings ++ Defaults.itSettings)
.configs(IntegrationTest)
.settings(
test in (IntegrationTest) <<= (test in IntegrationTest).dependsOn(reStart0 in projectA)
)

Related

SBT Create a DockerFile Using a Function

I was trying this piece of code:
// Get the Docker Configurations
def dockerConfForModule(moduleName: String): Dockerfile = {
val jarFile: File = (Compile / packageBin / sbt.Keys.`package`).value
val classpath = (Compile / managedClasspath).value
val mainclass = (Compile / packageBin / mainClass).value.getOrElse(sys.error("Expected exactly one main class"))
val jarTarget = s"/app/${jarFile.getName}"
// Make a colon separated classpath with the JAR file
val classpathString = classpath.files.map("/app/" + _.getName)
.mkString(":") + ":" + jarTarget
new Dockerfile {
// Base image
from("openjdk:8-jre")
// Add all files on the classpath
add(classpath.files, "/app/")
// Add the JAR file
add(jarFile, jarTarget)
// On launch run Java with the classpath and the main class
entryPoint("java", "-cp", classpathString, mainclass)
}
}
Which I'm calling as a function in one of my module like below:
// Define Sub Modules and its settings
lazy val cleanse = (project in file(MODULE_NAME_CLEANSE)).dependsOn(core)
.settings(
commonSettings,
enablingCoverageSettings,
name := MODULE_NAME_CLEANSE,
description := "Clean the incoming data for training purposes",
docker / dockerfile := dockerConfForModule(MODULE_NAME_CLEANSE)
)
.enablePlugins(DockerPlugin)
But this runs into an error:
/home/joesan/Projects/Private/ml-projects/housing-price-prediction-data-preparation/build.sbt:22: error: `value` can only be called on a task within a task definition macro, such as :=, +=, ++=, or Def.task.
val jarFile: File = (Compile / packageBin / sbt.Keys.`package`).value
^
/home/joesan/Projects/Private/ml-projects/housing-price-prediction-data-preparation/build.sbt:23: error: `value` can only be called on a task within a task definition macro, such as :=, +=, ++=, or Def.task.
val classpath = (Compile / managedClasspath).value
^
/home/joesan/Projects/Private/ml-projects/housing-price-prediction-data-preparation/build.sbt:24: error: `value` can only be called on a task within a task definition macro, such as :=, +=, ++=, or Def.task.
val mainclass = (Compile / packageBin / mainClass).value.getOrElse(sys.error("Expected exactly one main class"))
^
sbt.compiler.EvalException: Type error in expression
[error] sbt.compiler.EvalException: Type error in expression
[error] Use 'last' for the full log.
[warn] Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore? (default: r)
What is wrong in what I'm trying?

How to load javascript in the JVM cross project

I have run into some difficulties and was wondering if someone can help me. I have the following Build.scala and I am trying to access the the compile javascript from the JVM project.
lazy val webProject = CrossProject(base = file("./main/web"), crossType = CrossType.Full, jvmId = "api-gateway", jsId = "web-js")
.settings(
name := "web",
unmanagedSourceDirectories in Compile += baseDirectory.value / "shared" / "main" / "scala",
libraryDependencies ++= Dependencies.Client.sharedDeps.value)
.jvmSettings(
persistLauncher := true,
persistLauncher in Test := false,
libraryDependencies ++= Dependencies.Client.jvmDeps.value)
.jsSettings(libraryDependencies ++= Dependencies.Client.jsDeps.value)
lazy val webJS = webProject.js.enablePlugins(ScalaJSPlugin)
lazy val webJVM = webProject.jvm
.settings((resources in Compile) += (fastOptJS in(webJS, Compile)).value.data)
.dependsOn(dominos)
The compile javascript is generated
[info] Fast optimizing /.../main/web/js/target/scala-2.11/web-fastopt.js
When I try to access the compile javascript by running get server, it can't be found.
object Main extends App {
implicit val system = ActorSystem("my-system")
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
val routes = pathEndOrSingleSlash(getFromResource("web-fastopt.js"))
Http().bindAndHandle(routes, "localhost", 8080)
}
Isn't this line suppose to add the javascript the the JVM's resources folder when it runs?
(resources in Compile) += (fastOptJS in(webJS, Compile)).value.data
Any help would be greatly appreciated.
Seems like this like doesn't work for me for some reason
(resources in Compile) += (fastOptJS in(webJS, Compile)).value.data
Instead I ended having to move the fastOptJS file
lazy val webJVM = webProject.jvm
.settings(Seq(fastOptJS, fullOptJS, packageJSDependencies)
.map(pkg ⇒ crossTarget in(webJS, Compile, pkg) := scalaJSOutput.value))
I also needed to add
getFromResourceDirectory("")
to the Akka Http routes.

Error while using aspectj with Scala

I am having an application in scala. I need to use AOP for one of the functionality. I used the plugin sbt-aspectj . Everything is working fine when I run using the sbt console. However, I am not able to make it work when using the executable jar. I tried the the sample code provided in the sbt-aspect git page. But, I am getting the errors as
[warn] warning incorrect classpath: D:\source\jvm\modules\scala\frameworks\aspectjTracer\target\scala-2.11\classes
[warn] Missing message: configure.invalidClasspathSection in: org.aspectj.ajdt.ajc.messages
[error] error no sources specified
.
[trace] Stack trace suppressed: run 'last aspectjTracer/aspectj:ajc' for the full output.
[error] (aspectjTracer/aspectj:ajc) org.aspectj.bridge.AbortException: ABORT
[error] Expected project ID
[error] Expected configuration
[error] Expected ':' (if selecting a configuration)
[error] Expected key
[error] Not a valid key: aspectjTracker (similar: aspectjSource, aspectj-source, aspectjDirectory)
[error] last aspectjTracker/aspectj:ajc
[error]
My Build.scala is given below :
object frameworkBuild extends Build {
import Dependencies._
val akkaV = "2.3.6"
val sprayV = "1.3.1"
val musterV = "0.3.0"
val common_settings = Defaults.defaultSettings ++
Seq(version := "1.3-SNAPSHOT",
organization := "com.reactore",
scalaVersion in ThisBuild := "2.11.2",
scalacOptions ++= Seq("-unchecked", "-feature", "-deprecation"),
libraryDependencies := frameworkDependencies ++ testLibraryDependencies,
publishMavenStyle := true,
)
connectInput in run := true
lazy val aspectJTracer = Project(
"aspectjTracer",
file("aspectjTracer"),
settings = common_settings ++ aspectjSettings ++ Seq(
// input compiled scala classes
inputs in Aspectj <+= compiledClasses,
// ignore warnings
lintProperties in Aspectj += "invalidAbsoluteTypeName = ignore",
lintProperties in Aspectj += "adviceDidNotMatch = ignore",
// replace regular products with compiled aspects
products in Compile <<= products in Aspectj
)
)
// test that the instrumentation works
lazy val instrumented = Project(
"instrumented",
file("instrumented"),
dependencies = Seq(aspectJTracer),
settings = common_settings ++ aspectjSettings ++ Seq(
// add the compiled aspects from tracer
binaries in Aspectj <++= products in Compile in aspectJTracer,
// weave this project's classes
inputs in Aspectj <+= compiledClasses,
products in Compile <<= products in Aspectj,
products in Runtime <<= products in Compile
)
)
lazy val frameworks = Project(id = "frameworks", base = file("."), settings = common_settings).aggregate( core, baseDomain,aspectJTracer,instrumented)
lazy val core = Project(id = "framework-core", base = file("framework-core"), settings = common_settings)
lazy val baseDomain = Project(id = "framework-base-domain", base = file("framework-base-domain"), settings = common_settings).dependsOn(core,aspectJTracer,instrumented)
}
Does anyone know how to fix this? I posted this in the sbt-aspectj github page and waiting for a response there as well. But I am in a little hurry to fix this. Your help will be really appreciated.
Finally the problem is resolved. I had added javaagent in the build.scala. But, while running with the sbt-one-jar, it was not taking that jar. So I have manually provided the javaagent as the aspectweaver jar file and it worked. However, it is almost taking 3-4 minutes to start the jar file with the aspect.
Sometime it is even taking 15 min to start the jar file due to the aspectjwaver. I am not sure if this is problem with aspectj or sbt-one-jar, I guess its with the one-jar.
has anyone else faced the same issue ? I don't see any activity in sbt-one-jar, so asking it here.

SBT 0.13 Build.scala References to undefined settings

I am new to SBT and I have been trying to build a custom task for this build.
I have a simple build project:
import sbt._
import Keys._
object JsonBuild extends Build{
lazy val barTask = taskKey[Unit]("some simple task")
val afterTestTask1 = barTask := { println("tests ran!") }
val afterTestTask2 = barTask <<= barTask.dependsOn(test in Test)
lazy val myBarTask = taskKey[Unit]("some simple task")
//val afterMyBarTask1 = myBarTask := { println("tests ran!") }
lazy val afterMyBarTask2 = myBarTask <<= (myBarTask).dependsOn(test in Test) map { _ => println("tests ran!") }
//settings ++ Seq(afterMyBarTask2)
override lazy val settings = super.settings ++ Seq(afterMyBarTask2)
}
I keep getting the error:
References to undefined settings:
{.}/*:myBarTask from {.}/*:myBarTask (C:\Users\haques\Documents\workspace\SBT\jsonParser\project\Build.scala:13)
{.}/test:test from {.}/*:myBarTask (C:\Users\haques\Documents\workspace\SBT\jsonParser\project\Build.scala:13)
Did you mean test:test ?
I have googled around and I cannot find a solution.
Can you explain why it is not working?
lazy val myBarTask = taskKey[Unit]("some simple task")
override lazy val settings = super.settings ++ Seq(myBarTask := { (test in Test).value; println("tests ran!") } )
myBarTask is undefined when you call dependsOn. you should define it before using dependsOn. also value call on key (task/setting) is now preferred way to depend on other keys. you can still use your version, but define myBarTask
This has been bothering.
I did a bit more reading.
I think I know why the above code does not work.
lazy val afterMyBarTask2 = myBarTask <<= (myBarTask).dependsOn(test in Test) map { _ => println("tests ran!") }
When I write (myBarTask).dependsOn(test in Test), the project scope for test is chosen by SBT as ThisBuild.
{.}/test:test from {.}/*:myBarTask (C:\Users\haques\Documents\workspace\SBT\jsonParser\project\Build.scala:13)
ThisBuild project scope does not have the setting test in configuration Test.
Only projects have the setting test.
The key I think that setting is added by some default SBT plugin to the projects settings.
You check what scopes settings exist in SBT by using the inspect command.
If you type in the SBT REPL:
{.}/test:test
The output is:
inspect {.}/test:test
[info] No entry for key.
SBT correctly suggests:
test:test which is:
{file:/C:/Users/haques/Documents/workspace/SBT/jsonParser/}jsonparser/test:test
If the project is not specified in the project scope axis, SBT chooses the current project by default.
Every SBT project if not specified has its own project settings.

SBT: How to make one task depend on another in multi-project builds, and not run in the root project?

For my multi-project build, I'm trying to create a verify task that just results in scct:test and then scalastyle being executed in order. I would like scct:test to execute for all the subprojects, but not the top-level project. (If it executes for the top-level project, I get "timed out waiting for coverage report" from scct, since there's no source and no tests in that project.) What I had thought to do was to create verify as a task with dependencies on scct:test and scalastyle. This has turned out to be fairly baroque. Here is my Build.scala from my top-level project/ directory:
object MyBuild extends Build {
val verifyTask = TaskKey[Unit]("verify", "Compiles, runs tests via scct:test and then runs scalastyle")
val scctTestTask = (test in ScctPlugin.Scct).scopedKey
val scalastyleTask = PluginKeys.scalastyleTarget.scopedKey
lazy val root = Project("rootProject",
file("."),
settings = Defaults.defaultSettings ++
ScalastylePlugin.Settings ++
ScctPlugin.instrumentSettings ++
ScctPlugin.mergeReportSettings ++
Seq(
verifyTask in Global := {},
verifyTask <<= verifyTask.dependsOn(scctTestTask, scalastyleTask)
)
) aggregate(lift_webapp, selenium_tests)
lazy val subproject_1 = Project(id = "subproject_1", base = file("subproject_1"))
lazy val subproject_2 = Project(id = "subproject_2", base = file("subproject_2"))
}
However, the verify task only seems to exist for the root project; when I run it I don't see the same task being run in the subprojects. This is exactly the opposite of what I want; I'd like to issue sbt verify and have scct:test and scalastyle run in each of the subprojects but not in the top-level project. How might I go about doing that?
solution 1: define verifyTask in subprojects
First thing to note is that if you want some task (verify, test, etc) to run in some projects, you need to define them scoped to the subprojects. So in your case, the most straightforward thing to do this is to define verifyTask in subproject_1 and subproject_2.
lazy val scalaTest = "org.scalatest" %% "scalatest" % "3.0.4"
lazy val verify = taskKey[Unit]("verify")
def verifySettings = Seq(
skip in verify := false,
verify := (Def.taskDyn {
val sk = (skip in verify).value
if (sk) Def.task { println("skipping verify...") }
else (test in Test)
}).value
)
lazy val root = (project in file("."))
.aggregate(sub1, sub2)
.settings(
verifySettings,
scalaVersion in ThisBuild := "2.12.4",
skip in verify := true
)
lazy val sub1 = (project in file("sub1"))
.settings(
verifySettings,
libraryDependencies += scalaTest % Test
)
lazy val sub2 = (project in file("sub2"))
.settings(
verifySettings,
libraryDependencies += scalaTest % Test
)
solution 2: ScopeFilter
There was a recent Reddit thread that mentioned this question, so I'll post what I've done there.
If you want to manually aggregate on some subprojects, there's also a technique called ScopeFilter.
Note that I am using sbt 1.x here, but it should work with sbt 0.13 some minor change.
lazy val packageAll = taskKey[Unit]("package all the projects")
lazy val myTask = inputKey[Unit]("foo")
lazy val root = (project in file("."))
.aggregate(sub1, sub2)
.settings(
scalaVersion in ThisBuild := "2.12.4",
packageAll := {
(packageBin in Compile).all(nonRootsFilter).value
()
},
myTask := {
packageAll.value
}
)
lazy val sub1 = (project in file("sub1"))
lazy val sub2 = (project in file("sub2"))
def nonRootsFilter = {
import sbt.internal.inc.ReflectUtilities
def nonRoots: List[ProjectReference] =
allProjects filter {
case LocalProject(p) => p != "root"
case _ => false
}
def allProjects: List[ProjectReference] =
ReflectUtilities.allVals[Project](this).values.toList map { p =>
p: ProjectReference
}
ScopeFilter(inProjects(nonRoots: _*), inAnyConfiguration)
}
In the above, myTask depends on packageAll, which aggregates (packageBin in Compile) for all non-root subprojects.
sbt:root> myTask
[info] Packaging /Users/xxx/packageall/sub1/target/scala-2.12/sub1_2.12-0.1.0-SNAPSHOT.jar ...
[info] Done packaging.
[info] Packaging /Users/xxx/packageall/sub2/target/scala-2.12/sub2_2.12-0.1.0-SNAPSHOT.jar ...
[info] Done packaging.
[success] Total time: 0 s, completed Feb 2, 2018 7:23:23 PM
I may be wrong, but you are defining the verify task dependency only for the current project.
Maybe you can try:
Seq(
verifyTask in Global := {},
verifyTask <<= (verifyTask in Global).dependsOn(scctTestTask, scalastyleTask)
)
Or you can add the verifyTask settings to all your modules.