Sbt build .war with custom configuration/profile - scala

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.

Related

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")

Importing assets from an NPM Package

Say I want to include font-awesome in my webapp. So I define my build.sbt as follows:
val commonSettings = Seq(
name := "repro",
version := "1.0",
scalaVersion := "2.12.8",
unmanagedSourceDirectories in Compile +=
baseDirectory.value / ".." / "shared" / "src" / "main" / "scala"
)
val client = project.in(file("client"))
.settings(commonSettings: _*)
.settings(
npmDependencies in Compile ++= Seq(
"font-awesome" -> "4.7.0",
),
mainClass in Compile := Some("app.App"),
scalaJSUseMainModuleInitializer := true,
webpackBundlingMode := BundlingMode.LibraryOnly(),
)
.enablePlugins(ScalaJSPlugin)
.enablePlugins(ScalaJSBundlerPlugin)
val server = project.in(file("server"))
.settings(commonSettings: _*)
.settings(
npmAssets ++= NpmAssets.ofProject(client) { nodeModules =>
(nodeModules / "font-awesome").allPaths
}.value
)
.enablePlugins(WebScalaJSBundlerPlugin)
Can I configure this project so that my "package" command will then include the css in my target/webapp folder? Or is there another command I have to use?
In addition to your configuration, you have to add the following settings to the server project:
.settings(
scalaJSProjects := Seq(client),
pipelineStages in Assets := Seq(scalaJSPipeline),
managedClasspath in Runtime += (packageBin in Assets).value,
WebKeys.packagePrefix in Assets := "public/"
)
The first line introduces a dependency between the server project and the assets produced by the client project. The scalaJSProjects settings is introduced by the sbt-web-scalajs plugin.
The second line integrates the assets produced by the client project into the Web assets managed by sbt-web.
The third line tells sbt to include the assets produced by the sbt-web plugin to the classpath of the server.
The last line is optional, it simply puts the produced assets into the public/ resource directory, so that they are not mixed with other classpath resources which are not meant to be exposed to the outside world.
With this configuration, you can build the production assets with the following command:
> server/web-assets:package
Or, from a build file, by using the packageBin in Assets task.
This will produce a target/scala-2.12/repro_2.12-1.0-web-assets.jar file containing the JavaScript bundle produced by Webpack on your client project, as well as the font-awesome/ directory.

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.

Test-jar in Classpath during Test SBT

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: _*)

adding another unmanaged source file to my play project

I try to add another source directory to my play project with
def temporarySources = Def.setting { (baseDirectory in Compile).value / "temporary" }
and then add to settings
(unmanagedSources in Compile) += temporarySources.value
after running sbt test, sbt complains , that the directory doesn't exist, although i'm sure it is there (i can cd to the directory)
I guess you need unmanagedSourceDirectories and not unmanagedSources, try the following setting:
unmanagedSourceDirectories in Compile += (baseDirectory.value / "temporary"),
unmanagedSourceDirectories in Test += (baseDirectory.value / "temporary")