Setting unique snapshot version when cross-building in SBT

I'm not sure if it's recommended approach in SBT 0.13.x, but the following has seemed to have worked fine for me.

If you need to "have the same timestamp" for all versions listed in crossScalaVersions, then you may want to leverage Generating files, i.e. IO.write and IO.read methods, to save a timestamp file with a unique snapshot version.

NOTE Do not set scalaVersion in build.sbt as it overwrites the one set by +. That was the problem in my initial answer.

Have the following task stampVersion in build.sbt (I leave migrating it to SBT < 0.13 as an exercise):

lazy val stampVersion = taskKey[File]("Generates timestamp file with unique snapshot version")

stampVersion := {
  val log = streams.value.log
  val stmp = System.currentTimeMillis
  val file = target.value / "timestamp"
  log.info(s"Stamping version $stmp saved in $file")
  IO.write(file, s"""$stmp""")
  file
}

When you run the task stampVersion, a file gets created in target/timestamp file.

With the following task, you can read its content.

lazy val getStampVersion = taskKey[String]("Retrieves unique snapshot version from timestamp file")

getStampVersion := {
  val log = streams.value.log
  val file = (target in Compile).value / "timestamp"
  val v = IO.read(file)
  log.info(s"Retrieving version from $file: $v [scalaVersion: ${scalaVersion.value}]")
  v
}

Use show getStampVersion to show the version saved in the file.

[sbt-0-13-1]> stampVersion
[info] Stamping version 1390606523705 saved in /Users/jacek/sandbox/so/sbt-0.13.1/target/timestamp
[success] Total time: 0 s, completed Jan 25, 2014 12:35:23 AM
[sbt-0-13-1]> show getStampVersion
[info] Retrieving version from /Users/jacek/sandbox/so/sbt-0.13.1/target/timestamp: 1390606523705 [scalaVersion: 2.10.3]
[info] 1390606523705
[success] Total time: 0 s, completed Jan 25, 2014 12:35:34 AM

In order to set version key to a timestamped version, I defined a command setVersionFromStampFile (as it changes the state of a project).

def setVersionFromStampFile = Command.command("setVersionFromStampFile") { state =>
  val e = Project extract state
  import e._
  val (newState, stampVersion) = runTask(getStampVersion, state)
  val scalaV = scalaVersion in currentRef get structure.data getOrElse Nil
  state.log.info(s"scalaVersion: $scalaV")
  val settings = Seq(
    version := stampVersion
  )
  append(settings ++ structure.settings, state)
}

commands += setVersionFromStampFile

With the command setVersionFromStampFile, whenever it gets run, version gets set appropriately.

[sbt-0-13-1]> show version
[info] 0.1-SNAPSHOT
[sbt-0-13-1]> setVersionFromStampFile
[info] Retrieving version from /Users/jacek/sandbox/so/sbt-0.13.1/target/timestamp: 1390606523705 [scalaVersion: 2.10.3]
[info] scalaVersion: 2.10.3
[info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
[sbt-0-13-1]> show version
[info] 1390606523705

In the build definition build.sbt, have the setting crossScalaVersions defined, e.g.

crossScalaVersions := Seq("2.9.3", "2.10.3")

Define a command alias setStampAsVersionAndShow in build.sbt to ease testing - you'll see the values of version and scalaVersion settings after executing the command setVersionFromStampFile:

addCommandAlias("setStampAsVersionAndShow",
                "; setVersionFromStampFile ; show version; show scalaVersion")

This lets you cross-execute a series of commands:

[sbt-0-13-1]> + setStampAsVersionAndShow
[info] Setting version to 2.9.3
[info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
[info] Retrieving version from /Users/jacek/sandbox/so/sbt-0.13.1/target/timestamp: 1390606523705 [scalaVersion: 2.9.3]
[info] scalaVersion: 2.9.3
[info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
[info] 1390606523705
[info] 2.9.3
[info] Setting version to 2.10.3
[info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
[info] Retrieving version from /Users/jacek/sandbox/so/sbt-0.13.1/target/timestamp: 1390606523705 [scalaVersion: 2.10.3]
[info] scalaVersion: 2.10.3
[info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
[info] 1390606523705
[info] 2.10.3
[info] Setting version to 2.10.3
[info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)

Define publishTo setting and another command alias setStampAsVersionAndPublish in build.sbt:

publishTo := Some(Resolver.file("file", target.value / "xxx"))

addCommandAlias("setStampAsVersionAndPublish",
                "; setVersionFromStampFile ; show scalaVersion ; publish")

You should now be able to publish as you'd expect:

  1. Let's start afresh.

    [sbt-0-13-1]> clean
    [success] Total time: 0 s, completed Jan 25, 2014 12:50:22 AM
    
  2. Generate a version file.

    [sbt-0-13-1]> stampVersion
    [info] Stamping version 1390607428495 saved in /Users/jacek/sandbox/so/sbt-0.13.1/target/timestamp
    [success] Total time: 0 s, completed Jan 25, 2014 12:50:28 AM
    
  3. Check it out with publish without cross-building (no +).

    [sbt-0-13-1]> setStampAsVersionAndPublish
    [info] Retrieving version from /Users/jacek/sandbox/so/sbt-0.13.1/target/timestamp: 1390607428495 [scalaVersion: 2.10.3]
    [info] scalaVersion: 2.10.3
    [info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
    [info] 2.10.3
    [info] Packaging /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/sbt-0-13-1_2.10-1390607428495-sources.jar ...
    [info] Done packaging.
    [info] Updating {file:/Users/jacek/sandbox/so/sbt-0.13.1/}sbt-0-13-1...
    [info] Wrote /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/sbt-0-13-1_2.10-1390607428495.pom
    [info] Resolving org.fusesource.jansi#jansi;1.4 ...
    [info] Done updating.
    [info] :: delivering :: default#sbt-0-13-1_2.10;1390607428495 :: 1390607428495 :: release :: Sat Jan 25 00:50:33 CET 2014
    [info]  delivering ivy file to /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/ivy-1390607428495.xml
    [info] Compiling 1 Scala source to /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/classes...
    [info] Main Scala API documentation to /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/api...
    model contains 2 documentable templates
    [info] Main Scala API documentation successful.
    [info] Packaging /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/sbt-0-13-1_2.10-1390607428495-javadoc.jar ...
    [info] Done packaging.
    [info] Packaging /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/sbt-0-13-1_2.10-1390607428495.jar ...
    [info] Done packaging.
    [info]  published sbt-0-13-1_2.10 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.10/1390607428495/sbt-0-13-1_2.10-1390607428495.pom
    [info]  published sbt-0-13-1_2.10 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.10/1390607428495/sbt-0-13-1_2.10-1390607428495.jar
    [info]  published sbt-0-13-1_2.10 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.10/1390607428495/sbt-0-13-1_2.10-1390607428495-sources.jar
    [info]  published sbt-0-13-1_2.10 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.10/1390607428495/sbt-0-13-1_2.10-1390607428495-javadoc.jar
    [success] Total time: 1 s, completed Jan 25, 2014 12:50:34 AM
    
  4. Give the final command a go - + enters the scene.

    [sbt-0-13-1]> + setStampAsVersionAndPublish
    [info] Setting version to 2.9.3
    [info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
    [info] Retrieving version from /Users/jacek/sandbox/so/sbt-0.13.1/target/timestamp: 1390607428495 [scalaVersion: 2.9.3]
    [info] scalaVersion: 2.9.3
    [info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
    [info] 2.9.3
    [info] Packaging /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.9.3/sbt-0-13-1_2.9.3-1390607428495-sources.jar ...
    [info] Done packaging.
    [info] Updating {file:/Users/jacek/sandbox/so/sbt-0.13.1/}sbt-0-13-1...
    [info] Wrote /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.9.3/sbt-0-13-1_2.9.3-1390607428495.pom
    [info] Resolving org.fusesource.jansi#jansi;1.4 ...
    [info] Done updating.
    [info] :: delivering :: default#sbt-0-13-1_2.9.3;1390607428495 :: 1390607428495 :: release :: Sat Jan 25 00:50:51 CET 2014
    [info] Compiling 1 Scala source to /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.9.3/classes...
    [info]  delivering ivy file to /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.9.3/ivy-1390607428495.xml
    [info] Main Scala API documentation to /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.9.3/api...
    model contains 2 documentable templates
    [info] Main Scala API documentation successful.
    [info] Packaging /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.9.3/sbt-0-13-1_2.9.3-1390607428495-javadoc.jar ...
    [info] Done packaging.
    [info] Packaging /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.9.3/sbt-0-13-1_2.9.3-1390607428495.jar ...
    [info] Done packaging.
    [info]  published sbt-0-13-1_2.9.3 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.9.3/1390607428495/sbt-0-13-1_2.9.3-1390607428495.pom
    [info]  published sbt-0-13-1_2.9.3 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.9.3/1390607428495/sbt-0-13-1_2.9.3-1390607428495.jar
    [info]  published sbt-0-13-1_2.9.3 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.9.3/1390607428495/sbt-0-13-1_2.9.3-1390607428495-sources.jar
    [info]  published sbt-0-13-1_2.9.3 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.9.3/1390607428495/sbt-0-13-1_2.9.3-1390607428495-javadoc.jar
    [success] Total time: 4 s, completed Jan 25, 2014 12:50:54 AM
    [info] Setting version to 2.10.3
    [info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
    [info] Retrieving version from /Users/jacek/sandbox/so/sbt-0.13.1/target/timestamp: 1390607428495 [scalaVersion: 2.10.3]
    [info] scalaVersion: 2.10.3
    [info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
    [info] 2.10.3
    [info] Packaging /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/sbt-0-13-1_2.10-1390607428495-sources.jar ...
    [info] Done packaging.
    [info] Updating {file:/Users/jacek/sandbox/so/sbt-0.13.1/}sbt-0-13-1...
    [info] Wrote /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/sbt-0-13-1_2.10-1390607428495.pom
    [info] Resolving org.fusesource.jansi#jansi;1.4 ...
    [info] Done updating.
    [info] :: delivering :: default#sbt-0-13-1_2.10;1390607428495 :: 1390607428495 :: release :: Sat Jan 25 00:50:55 CET 2014
    [info]  delivering ivy file to /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/ivy-1390607428495.xml
    [info] Compiling 1 Scala source to /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/classes...
    [info] Main Scala API documentation to /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/api...
    model contains 2 documentable templates
    [info] Main Scala API documentation successful.
    [info] Packaging /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/sbt-0-13-1_2.10-1390607428495-javadoc.jar ...
    [info] Done packaging.
    [info] Packaging /Users/jacek/sandbox/so/sbt-0.13.1/target/scala-2.10/sbt-0-13-1_2.10-1390607428495.jar ...
    [info] Done packaging.
    [info]  published sbt-0-13-1_2.10 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.10/1390607428495/sbt-0-13-1_2.10-1390607428495.pom
    [info]  published sbt-0-13-1_2.10 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.10/1390607428495/sbt-0-13-1_2.10-1390607428495.jar
    [info]  published sbt-0-13-1_2.10 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.10/1390607428495/sbt-0-13-1_2.10-1390607428495-sources.jar
    [info]  published sbt-0-13-1_2.10 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.10/1390607428495/sbt-0-13-1_2.10-1390607428495-javadoc.jar
    [success] Total time: 2 s, completed Jan 25, 2014 12:50:56 AM
    [info] Setting version to 2.10.3
    [info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
    
  5. Display basic information about sbt and the build with about.

    [sbt-0-13-1]> about
    [info] This is sbt 0.13.1
    [info] The current project is {file:/Users/jacek/sandbox/so/sbt-0.13.1/}sbt-0-13-1 0.1-SNAPSHOT
    [info] The current project is built against Scala 2.10.3
    [info] Available Plugins: com.typesafe.sbt.SbtGit, com.typesafe.sbt.SbtProguard, growl.GrowlingTests, np.Plugin, com.timushev.sbt.updates.UpdatesPlugin
    [info] sbt, sbt plugins, and build definitions are using Scala 2.10.3
    

Tags:

Scala

Sbt