问题
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?
回答1:
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)
来源:https://stackoverflow.com/questions/26217862/how-to-handle-multiple-build-targets-e-g-dev-test-main