How to handle multiple build targets eg. dev, test, main?
I am currently switching from Maven to SBT and I am struggling to figure out how I can handle multiple build targets (dev, test, train, prod, etc.).
For example, I have persistence.xml
one that looks like this:
<properties>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="javax.persistence.jdbc.url" value="${db.connectionURL}"/>
<property name="javax.persistence.jdbc.user" value="${db.username}"/>
<property name="javax.persistence.jdbc.password" value="${db.password}"/>
<property name="eclipselink.target-database" value="Oracle10"/>
</properties>
With Maven it was very easy to get around using profiles.
I've already tried what has been suggested here for SBT, but I haven't had that much success. How to add environment profile configuration to SBT .
Also, using this approach, I will need a new directory for every new environment. I just think there must be a better way to handle this kind of setup using SBT?
source to share
tl; dr Use ivyConfigurations
to add custom configurations and resourceGenerators
to process files in the environment.
All credits go to Eugene Yokota for his answer to How to Add Environment Profile Configuration to SBT . There are some modifications that make my decision ... cough ... cough ... a little better.
The next one build.sbt
defines two new configurations - dev and qa . It also defines, resourceGenerators
for each configuration, which effectively allows access to the configuration that the new resource generator is executing:
val Dev = config("dev") extend Runtime
val Qa = config("qa") extend Runtime
ivyConfigurations ++= Seq(Dev, Qa)
// http://www.scala-sbt.org/0.13.5/docs/Howto/generatefiles.html#resources
lazy val bareResourceGenerators: Seq[Setting[_]] = Seq(
resourceGenerators += Def.task {
val file = resourceManaged.value / "demo" / "myapp.properties"
println(s"Inside ${configuration.value}")
val contents = s"config=${configuration.value}"
IO.write(file, contents)
Seq(file)
}.taskValue
)
inConfig(Dev)(Defaults.configSettings ++ bareResourceGenerators)
inConfig(Qa)(Defaults.configSettings ++ bareResourceGenerators)
Inside the new ResourceGenerator, you can do whatever you want, and handling each configuration is possible with a parameter configuration
that gives you the name of the configuration:
> show dev:configuration
[info] dev
> show qa:configuration
[info] qa
Now when you execute show qa:resources
, you will see that there are two files generated with the target/scala-2.10/resource_managed/qa/demo/myapp.properties
content defined for the config:
> show qa:resources
Inside qa
[info] List(/Users/jacek/sandbox/envs/target/scala-2.10/resource_managed/qa/demo/myapp.properties, /Users/jacek/sandbox/envs/src/qa/resources)
Now you need to use the ResourceGenerator to meet your needs, and since you are in Scala code you can do whatever you want, just use it configuration.value
as a qualifier for the configuration specific code.
Let's say you want to use a properties file qa
in the standard directory src/main/resources
. Just know what the value is bound to (what configuration and value setting comes from). It's simple compile:resourceDirectory
.
> show compile:resourceDirectory
[info] /Users/jacek/sandbox/envs/src/main/resources
Just use resourceDirectory in Compile
whenever you need a "stable" (as well as a fixed configuration) value, eg src/main/resources
.
val props = (resourceDirectory in Compile).value / s"${configuration.value.name}.properties"
println(s"Read files from $props")
With the above lines, you get:
> show qa:resources
Inside qa
Read files from /Users/jacek/sandbox/envs/src/main/resources/qa.properties
[info] List(/Users/jacek/sandbox/envs/target/scala-2.10/resource_managed/qa/demo/myapp.properties, /Users/jacek/sandbox/envs/src/qa/resources)
> show dev:resources
Inside dev
Read files from /Users/jacek/sandbox/envs/src/main/resources/dev.properties
[info] List(/Users/jacek/sandbox/envs/target/scala-2.10/resource_managed/dev/demo/myapp.properties, /Users/jacek/sandbox/envs/src/dev/resources)
source to share