Search code examples
sbtjson4s

How to read data from file in task and use it to set another setting?


We are migrating our application to Play Framework. We've been working with the gradle build system and are facing a couple of issues with sbt.

We use jooq for our database, which means that our build file needs to contain the database username/password (since jooq generates code by reading the db schema). Since it isn't a good idea, all the sensitive data is stored in a protected file on each host the build might potentially run on, and the build system reads from the file and then configures the system accordingly. It was pretty straightforward in gradle, but I have hit a deadend with sbt. This is what I have till now:

import org.json4s._
import org.json4s.native.JsonMethods.

val jsonBuildConfig = TaskKey[JValue]("json-build-config")

jsonBuildConfig := {
   val confLines = scala.io.Source.fromFile("/etc/application.conf").mkString
   parse(confLines)
}

jooqOptions := Seq(
  "jdbc.driver"   -> "org.postgresql.Driver",
  "jdbc.url"      -> "FIXME",
  "jdbc.user"     -> "FIXME",
  "jdbc.password" -> "FIXME"
)

The problem is that the three configuration parameters, with FIXME as their current values in jooqOptions, need to be picked from the file.

Within jsonBuildConfig, I can do this:

val confLines = scala.io.Source.fromFile("/etc/application.conf").mkString
val jsonConf = parse(confLines)
(jsonConf / "stagingdb" / "url").values

But how do I set it in jooqOptions conf set?


Solution

  • If I've understood your question correctly, you want the jooqOptions value to depend on the value of jsonBuildConfig. There's a section about that here:

    http://www.scala-sbt.org/0.13.5/docs/Getting-Started/More-About-Settings.html

    Basically, you would want to use <<= instead of := to set jooqOptions, e.g.

    jooqOptions <<= jsonBuildConfig.apply { jsonConf =>
      val dbSettings = jsonConf / "stagingdb"
      val dbUrl = dbSettings / "url"
      val dbUser = ...
      ...
      Seq("jdbc.driver" -> "...", "jdbc.url" -> dbUrl, ...)
    }
    

    For newer versions of SBT, you can avoid the setting.apply{...} pattern by calling setting.value within a setting initializer block, e.g.

    jooqOptions := {
      val dbSettings = jsonBuildConfig.value / "stagingdb"
      ...
    }
    

    I linked to the docs for SBT 0.13.5, which does support the .value feature. Double-check which version of SBT you are using, and open the appropriate docs page to see if it supports that feature.