When publish, if there is -SNAPSHOT in a version, I'd like to replace it with a unique timestamp. I've already done this and it works, except for cross-building with +.
It seems that the version setting I set with the timestamp gets cleared out whenever the Scala version is changed for the cross-build.
When I try to cross-build publish I'm using the following command:
sbt ";stamp-version ;+publish"
Here is the code for the command stamp-version:
object TimestampVersion {
import Version.Snapshot
lazy val versionSettings = Seq(commands += stampVersion)
def stampVersion = Command.command("stamp-version") { state =>
val extracted = Project.extract(state)
extracted.append(List(version in ThisBuild ~= { ver =>
val stmp = stamp(ver)
Logging.info("Stamping version %s".format(stmp))
stmp
}), state)
}
def stamp(version: String): String = {
if (version endsWith Snapshot) {
// we use a dot here to not break rpm versioning rules
(version stripSuffix Snapshot) + "." + timestamp(System.currentTimeMillis)
} else {
version
}
}
def timestamp(time: Long): String = {
// no delimiter between date & time in order to not break rpm versioning rules
val sdf = new java.text.SimpleDateFormat("yyyyMMddHHmmss")
sdf.setTimeZone(TimeZone.getTimeZone("UTC"))
sdf.format(new Date(time))
}
}
Is there a different way I can store my timestamped version that can be accessed by my cross-builds?
EDIT: To be clear, I want each cross-built version to have the same timestamp so that when I use it from somewhere else I can depend on like this: "x" %% "y" % "z"
Also, it would be best if the solution could work with SBT 0.12.x since I still have that dependency.
Typically, if a key has no associated value in a more-specific scope, sbt will try to get a value from a more general scope, such as the ThisBuild scope. This feature allows you to set a value once in a more general scope, allowing multiple more-specific scopes to inherit the value.
The publishLocal action is used to publish your project to your Ivy local file repository, which is usually located at $HOME/. ivy2/local/ . You can then use this project from other projects on the same machine.
sbt is a build tool for Scala, Java, and more. It requires Java 1.8 or later.
SBT's crossScalaVersions allows projects to compile with multiple versions of Scala. However, crossScalaVersions is a hack that reuses projects by mutates settings.
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:
Let's start afresh.
[sbt-0-13-1]> clean
[success] Total time: 0 s, completed Jan 25, 2014 12:50:22 AM
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
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
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/)
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
We could set the DATETIME in bash like so
export DATETIME=`date +"%Y-%m-%d_%H-%M-%S"`
and then build our software like
sbt 'set version in ThisBuild := s"1.0.0-${sys.env.get("DATETIME").get}"' +compile +publish
This will take care that same timestamp is used for both compile versions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With