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

时光怂恿深爱的人放手 提交于 2020-01-04 03:15:23

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!