Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle multiple build targets, e.g. dev, test, main?

Tags:

maven

sbt

I'm currently migrating from Maven to SBT, and I'm struggling to understand how I can handle multiple build targets (dev, test, train, prod etc).

For example, I have a persistence.xml 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 really easy to handle this using profiles.

I've already tried what was suggested here for SBT, but I'm not having any success with that approach. How to Add Environment Profile Config to SBT.

Also, using that approach I would need a new directory for each new environment. I just think that there has to be a better way to handle this kind of setup using SBT?

like image 325
Daniel Avatar asked Jan 25 '26 18:01

Daniel


1 Answers

tl;dr Use ivyConfigurations to add custom configs and resourceGenerators to process files per environment.

All credits goes to Eugene Yokota for the answer to How to Add Environment Profile Config to SBT. There are some modification that make the solution of mine...cough...cough...slightly better.

The following build.sbt defines two new configurations - dev and qa. It also defines resourceGenerators per configuration that effectively gives a way to access what configuration the new resourceGenerator executes in:

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 the per-configuration processing is possible with the configuration setting 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'll see that there are two files generated with target/scala-2.10/resource_managed/qa/demo/myapp.properties with the content that's specific to a configuration:

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

The trick now is to use the resourceGenerator to meet your needs and since you're in Scala code you can do whatever you want - just use configuration.value as the qualifier for a configuration-specific code.

Say, you want to use a qa-specific properties file in the standard src/main/resources directory. Just know where the value is bound to (what configuration and setting the value comes from). It's just compile:resourceDirectory.

> show compile:resourceDirectory
[info] /Users/jacek/sandbox/envs/src/main/resources

Just use resourceDirectory in Compile whenever you need a "stable" (aka configuration-fixed) value like 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'd 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)
like image 180
Jacek Laskowski Avatar answered Jan 28 '26 10:01

Jacek Laskowski



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!