Test-jar in Classpath during Test SBT - scala

We have a Stub classes and Real classes of disptach-reboot in two seperate jars. We need a way in SBT so that we need Stub classes in class path when unit test is run and Real classes when code running in production.

Using the multi-project .sbt build definition and unmanaged dependencies:
lazy val commonSettings = Seq(
dependencyClasspath in Compile += baseDirectory.value / "lib-main" / "realclasses.jar",
dependencyClasspath in Runtime += baseDirectory.value / "lib-main" / "realclasses.jar",
dependencyClasspath in Test += baseDirectory.value / "lib-test" / "stubclasses.jar"
)
lazy val root = (project in file(".")).settings(commonSettings: _*)

Related

Is it possible to have in SBT a Test Fixture source folder?

Reading the following SBT documentation:
https://www.scala-sbt.org/1.x/docs/Appending-Values.html
And also
https://www.scala-sbt.org/1.x/docs/Classpaths.html
I can get on how to create a test source folder with only utils classes to be consume both by the tests in the same project and in all other projects that depend on it.
I tried the following but got compilation issues:
Test / sourceDirectories := Seq( baseDirectory.value / "testFixtures", baseDirectory.value / "test")
And also the following but this time sbt does not find any tests in the project:
sourceDirectory in Test := baseDirectory.value / "test"
Test / unmanagedSourceDirectories += baseDirectory.value / "testFixtures"
any idea ?
Thanks

Sbt build .war with custom configuration/profile

I have an sbt project with custom env configuration.
val Prod = config("prod") extend Compile describedAs "Scope to build production packages."
val Stage = config("stage") extend Compile describedAs "Scope to build stage packages."
val Local = config("local") extend Compile describedAs "Scope to build local packages."
lazy val root = (project in file("."))
.configs(Prod, Stage, Local)
.enablePlugins(WarPlugin)
.settings(
name := "pet",
dependencySettings
).
settings(inConfig(Prod)(Classpaths.configSettings ++
Defaults.configTasks ++ Defaults.resourceConfigPaths ++ Seq(
unmanagedResourceDirectories += {baseDirectory.value / "src" / "main" / configuration.value.name / "resources"}
)): _*).
settings(inConfig(Stage)(Classpaths.configSettings ++
Defaults.configTasks ++ Defaults.resourceConfigPaths ++ Seq(
unmanagedResourceDirectories += {baseDirectory.value / "src" / "main" / configuration.value.name / "resources"}
)): _*).
settings(inConfig(Local)(Classpaths.configSettings ++
Defaults.configTasks ++ Defaults.resourceConfigPaths ++ Seq(
unmanagedResourceDirectories += {baseDirectory.value / "src" / "main" / configuration.value.name / "resources"}
)): _*)
So when I run sbt Local/compile or sbt Local/run command I see in the target directory my compiled classes with my Local configuration.
Then I add xsbt-web-plugin for packaging .war file
addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "4.2.4")
And in build.sbt
enablePlugins(WarPlugin)
Now I try to run sbt Local/package command and get just .jar but not .war
If I run sbt package command I get .jar and .war files but without my Local configuration.
Help me, please. How can I make sbt Local/package work correct?
Or maybe you know some other way to build .war file with sbt.

how to change the scalaPB default path of protobuf files?

I have a build.sbt for a couple of packages in the same project.
When I do sbt compile, my protobuf files are under [packagename]/src/main/protobuf/*,
so it won't scan these files since they have that additional package name in the path.
How to change the default protobuf file path?
It is unclear from your question whether your sbt build is a single or multi-project build. You can tell that it is a multi-project build if you see lines like val someSubProject = project.in(file(...).
If your build.sbt is a single project build, you can add a line to customize where protos are being scanned:
Compile / PB.protoSources += file("pkgname/src/main/protobuf")
If you have a multi-project build with a project proj1, then it should already work in the way you expect:
val proj1 = project.in(file("proj1"))
.settings(
PB.targets in Compile := Seq(
scalapb.gen(javaConversions=true) -> (sourceManaged in Compile).value / "scalapb"
),
libraryDependencies ++= Seq(
"com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf",
)
)
then sbt-protoc will generate sources for the protos under proj1/src/main/protobuf. The sources will get compiled as poart of the proj1 project.
You can customize the path it looks for by setting Compile / PB.protoSources within that project's setting. For example, if you want it to generate source for protos that are in another top-level directory, you can do:
val proj1 = project.in(file("proj1"))
.settings(
PB.targets in Compile := Seq(
scalapb.gen(javaConversions=true) -> (sourceManaged in Compile).value / "scalapb"
),
Compile / PB.protoSources :=
Seq((ThisBuild / baseDirectory).value / "somewhere" / "protos"),
libraryDependencies ++= Seq(
"com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf",
)
)
I recommend using AkkaGrpcPlugin and a multi-project SBT configuration.
Put the .proto files in a separate project and make the others depend on it. This project just has a single directory <root>/grpc/src/main/protobuf containing the .proto files. When this project is compiled it will create all the stub files which can be picked up by other projects that depend on it.
Here is an outline build.sbt file:
lazy val top_level =
(project in file("."))
.aggregate(grpc, main)
lazy val grpc =
project
.in(file("grpc"))
.settings(
???
)
.enablePlugins(AkkaGrpcPlugin)
lazy val main =
project
.in(file("main"))
.settings(
???
)
.dependsOn(grpc)
And add this to plugins.sbt:
addSbtPlugin("com.lightbend.akka.grpc" % "sbt-akka-grpc" % "1.1.1")

Can I create a proto jar for scalaVersion 2.11/2.12 and use it within the same sbt under different sub-project?

I have a set of .proto files (protobuf) which I generate java from using scalapb. I also have in the same sbt 2 sub-projects, one is scalaVersion 2.11 compatible (can't upgrade it to 2.12 due to missing packages) and the other one is scala 2.12.
I created a sub-project to hold my proto, and by default 2.12 is used and my 2.12 sub-project can use it, but my 2.11 can't.
I set the crossScalaVersions to 2.11/2.12, I compiled my project with both, which passed, but then even then I was unable to get the 2.11 sub-project to find that code.
I am "wondering" if that is something supported, or if there is a track I could use a single location to hold my .proto yet have my 2 sub-projects using the same sbt file use those.
lazy val scala212 = "2.12.13"
lazy val scala211 = "2.11.12"
lazy val supportedScalaVersion = List(scala212, scala211)
ThisBuild / scalaVersion := scala212
lazy val root = (project in file("."))
.aggregate(proto, subproject1, subproject2)
.settigns(
crossScalaVersions := Nil,
publish / skip := true
)
lazy val proto = project
.settings(
crossScalaVersions := supportedScalaVersions,
name := "proto",
libraryDependencies += "com.trueaccord.scalapb" %% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion % "protobuf",
PB.targets in Compile := Seq(
scalapb.gen(grpc = false) -> (sourceManaged in Compile).value / "protobuf"
)
)
lazy val subproject1 = project
.dependsOn(proto)
lazy val subproject2 = project
.settings(
scalaVersion := scala211
)
.dependsOn(proto)
So, from the above, if I do sbt "+ proto" I can compile both versions. If I do sbt subproject1/compile it works too. Using sbt subproject2/compile fails indicating that it cannot find the 2.11:proto jar file.
Either, I would like the above somehow to work nicely, or any other trick that I could generate the code from the same proto location but within subproject1/subproject2 would be appreciated.
You could try the sbt-projectmatrix plugin:
https://github.com/sbt/sbt-projectmatrix
The idea is to have separate sbt subprojects for the different Scala versions, so you can simply reference the relevant subproject when calling dependsOn.
I think this plugin is going to end up in sbt some day as it's a much better solution in general than the current built-in stateful cross compilation support, and it's developed by Eugene Yokota, who is also an sbt developer.

Multi module Scala Play 2.3 conf location

I've been tasked with rewriting an old ant build script to SBT. As it happens, our suite is built up of 3 modules:
A Play 2.3 front-end webserver;
A back-end for retrieving data from various other systems;
A middle module containing some shared classes for database access and business logic.
Below an excerpt of my Build.scala file can be found:
val sharedSettings = Seq(
organization := <organization here>,
version := "1.2.5",
scalaVersion := "2.11.1",
libraryDependencies ++= libraries,
unmanagedJars in Compile ++= baseDirectory.value / "lib",
unmanagedJars in Compile ++= baseDirectory.value / "src",
unmanagedJars in Compile ++= baseDirectory.value / "test"
)
lazy val middle = project.settings(sharedSettings: _*)
lazy val back = project.settings(sharedSettings: _*).dependsOn(middle)
lazy val front =
project
.enablePlugins(play.PlayScala)
.settings(sharedSettings: _*)
.settings(scalaSource in Compile := baseDirectory.value / "app")
.settings(
routesImport ++= Seq(
"scala.language.reflectiveCalls", // Removes warnings when using multiple routes files
"com.asml.cerberus.front.toolbox.Binders._")
)
.dependsOn(middle % "compile->compile;test->test")
I've got my application.conf in the ./front/conf/ directory. Unfortunately, if I now run sbt, it looks for a ./conf/application.conf file. (I've tested this by moving the conf directory.)
Is there any way how I can tell SBT/Play to use the front module's conf directory in stead?
In case that helps, we have a wrapper script around activator (sbt) activatorWrapper:
#!/bin/bash
activator -Dconfig.file=front/conf/application.conf
Then you can start your application with :
$ ./activatorWrapper
You can use system properties to specify an alternative config file. See here for the details.