Dnomyar Dnomyar - 2 months ago 12
Scala Question

How to dynamically 'inject' environment variables defined in a file in run task with SBT

I'am looking for a way to inject environment variables in an SBT task from a dynamic file.

For example :

sbt run -dev
or
sbt dev:run
or
sbt dev run
launches sbt run task after having injected environment variables defined in the file
conf/env/database.dev


For the moment I have this code in
build.sbt
:

// ...
val dev = taskKey[Unit]("Dev config")
val local = taskKey[Unit]("Local config")

def setEnvVar(env: String) = {
try{
val split: Array[String] = (s"cat conf/env/database.$env" !!).split("\\n")
val raw_vars = split.map(_.span(! _.equals('='))).map(x => x._1 -> x._2.tail).toList
raw_vars foreach (v => {
println(s"INJECTING ${v._1} = ${v._2}")
javaOptions += s"-D${v._1}=${v._2}"
})
}catch{
case e: Exception => println(s"Cannot inject env vars (${e.getMessage})")
}
}


dev := {
setEnvVar("dev")
}

local := {
setEnvVar("local")
}


When I launch
sbt dev run
, I have the following result :

[info] Loading project definition from ...
[info] Set current project to ...
INJECTING PG_DB = qgd
INJECTING PG_HOST = localhost
INJECTING PG_PORT = 5432
INJECTING PG_USERNAME = ...
INJECTING PG_PASSWORD = ...
[success] Total time: 0 s, completed 12 févr. 2016 10:46:10

--- (Running the application, auto-reloading is enabled) ---

[info] p.c.s.NettyServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9000

(Server started, use Ctrl+D to stop and go back to the console...)


But, when I go to
localhost:9000
, I can see that variables are not injected.

In my application.conf :

// ...
pg.db = ${?PG_DB}
pg.host = ${?PG_HOST}
pg.port = ${?PG_PORT}
pg.default.username = ${?PG_USERNAME}
pg.default.password = ${?PG_PASSWORD}
// ...


Do you have any idea to solve my problem ?

Answer

As @AjayPadala suggested, I solved my problem by using fork processes.

I just updated my previous code with the following one :

fork := true // <=======================

val dev = taskKey[Unit]("Dev config")
val local = taskKey[Unit]("Local config")

def setEnvVar(env: String) = {
  try{
    val split: Array[String] = (s"cat conf/env/database.$env" !!).split("\\n")
    val raw_vars = split.map(_.span(! _.equals('='))).map(x => x._1 -> x._2.tail).toList
    val sysProp = System.getProperties // <=======================
    raw_vars foreach (v => {
      println(s"INJECTING ${v._1} = ${v._2}")
      sysProp.put(v._1, v._2) // <=======================
    })
    System.setProperties(sysProp) // <=======================
  }catch{
    case e: Exception => println(s"Cannot inject env vars (${e.getMessage})")
  }
}


dev := {
  setEnvVar("dev")
}

local := {
  setEnvVar("dev.default")
}
Comments