1

Background: We're working on a spark pipeline that generates models from data. Standard datasciency stuff. We're going to be using these models in a variety of places, and doing A/B testing to ensure parity with older models. I'd like to add data to all of our outputted models that tells us which version of the code generated the model, but rather than just having a version, I want to include unique information about the .jar. Compilation time, computer it was compiled on, username, etc etc. Lets us do A/B testing on stuff that was compiled by devs outside of our release process as well.

Is there a good way in SBT to compute that stuff at compile time and embed it into the program?

Zach H
  • 469
  • 5
  • 18
  • 1
    You can generate any files with whatever information you want: [sbt doc](https://www.scala-sbt.org/1.0/docs/Howto-Generating-Files.html). As is, the question seems a bit too broad. – Andrey Tyukin Sep 14 '18 at 17:11
  • 4
    Also take a look at [sbt-buildinfo](https://stackoverflow.com/a/8736724/2707792). – Andrey Tyukin Sep 14 '18 at 18:13
  • @AndreyTyukin could you post your comments as an answer? – laughedelic Sep 17 '18 at 23:56
  • 1
    @laughedelic The comment about `sbt-buildinfo` is not really an answer, it's merely a vague suggestion that the OP could seek some inspiration in the code of a compiler plugin that does something similar. I've done something similar before, so I'm pretty sure that it works, but I currently have no time/energy to dig deeper into SBT documentation to refresh how exactly it all works, and unlike Eugene Yokota in the linked post, I'm not familiar enough with SBT to write down a generic sbt plugin off the top of my head. As I said: currently the question is too broad and thus unanswerable. – Andrey Tyukin Sep 18 '18 at 00:32
  • @laughedelic I also doubt somewhat that SBT buildinfo provides the information about "computer it was compiled on, username, etc. etc.". Afair, `sbt-buildinfo` seemed a bit more focused. But again - it probably could be done, but for that, the question asker should specify a bit more specifically what is meant by "all that stuff". – Andrey Tyukin Sep 18 '18 at 00:37
  • OK, thanks for clarifying your position. I voted to close it then, unless it will be improved. IMO sbt-buildinfo can solve this anyway: it just provides a way to generate some simple code with given values; you can get those values any way you want (e.g. by calling an external command). – laughedelic Sep 18 '18 at 17:26

1 Answers1

0

We ended up using a combination of sbt-buildinfo and Vcs plugins through sbt-release to do the job. Here's what we put in our build.sbt file:

lazy val root = (project in file(".")).
  enablePlugins(BuildInfoPlugin).
  settings(
    buildInfoKeys := Seq[BuildInfoKey](
      name,
      version,
      scalaVersion,
      sbtVersion,
      // actions are computed at compile time
      BuildInfoKey.action("buildTime") {
        LocalDateTime.now(Clock.systemUTC())
      },
      // actions are computed at compile time
     BuildInfoKey.action("buildUser") {
        val user = System.getenv("USER")
        val username = System.getenv("USERNAME")
        if (user != null) user
        else if (username != null) username
        else "Unknown"
      },
      BuildInfoKey.action("buildSha") {
        // Find the current version control system and get the current hash of it
        Vcs.detect(new File(".")).map(_.currentHash)
      }
        ),
    buildInfoPackage := "company.package"
  )

The key bit here is that BuildInfo actions are calculated and set at compile time instead of runtime.

Zach H
  • 469
  • 5
  • 18