Since we’re operating in continuous deployment mode, it’s important to us to know the current application version and to link it with its code snapshot. This helps us to pinpoint problems, bad versions, and compatibility issues and to keep track of server-side analytics events. On our internal admin tools, we can then introspect our server and quickly understand what version we are at and when we compiled and pushed that version.
To do that, we have our application distribution (zip) file tagged with the build time, git branch and commit hash. We also persist that information inside the distribution package using the code below, which we added to Play’s Build.scala:
import org.joda.time.{DateTime, DateTimeZone, LocalDate, LocalTime} import org.joda.time.format.DateTimeFormat ... val BUILD_DATETIME_FORMAT = DateTimeFormat.forPattern("yyyyMMdd-HHmm") .withLocale(Locale.ENGLISH) .withZone(DateTimeZone.forID("America/Los_Angeles")) val buildTime = BUILD_DATETIME_FORMAT.print(new DateTime(DateTimeZone.forID("America/Los_Angeles"))) val appVersion = "%s-%s-%s".format(buildTime, "git rev-parse --abbrev-ref HEAD".!!.trim, "git rev-parse --short HEAD".!!.trim) val PT = DateTimeZone.forID("America/Los_Angeles") val now = DateTimeFormat.forPattern("E, dd MMM yyyy HH:mm:ss Z") .withLocale(Locale.ENGLISH).withZone(PT).print(new DateTime(PT)) def writeToFile(fileName: String, value: String) = { val file = new PrintWriter(new File(fileName)) try { file.print(value) } finally { file.close() } } writeToFile("conf/app_version.txt", appVersion) writeToFile("conf/app_compilation_date.txt", now) |
And this simple application runtime code reads it:
lazy val currentVersion: ServiceVersion = current.mode match { case Mode.Test = ServiceVersion("Test mode service") case _ = ServiceVersion(io.Source.fromURL(Play.resource("app_version.txt").get).mkString) } lazy val compilationTime: DateTime = current.mode match { case Mode.Test = currentDateTime case _ = val timeStr = io.Source.fromURL(Play.resource("app_compilation_date.txt").get).mkString DateTimeFormat.forPattern("E, dd MMM yyyy HH:mm:ss Z") .withLocale(Locale.ENGLISH) .withZone(zones.PT).parseDateTime(timeStr) } |
[...] [...]