目的
AWS Lambdaで動いてMarkdown記法のテキストを出力する、小さな社内サービスを開発しています。
きちんとバージョニングするほどでもないのですが、デバッグのために出力時のコードは特定できるようにする必要があります。
そこでGitのコミットハッシュ値、せっかくなのでGitHubのリンクまで出力するようにしてみました。
出力イメージ
(本文)
commit: e83c516 [modified]
log: (ログストリームへのリンク)
仕組み
Scalaで開発しているため、ビルドツールはsbtを使っているのですが、探してみたところsbt-git-stampというプラグインがありました。
これはJGitを利用して、sbt assembly
で生成されるJARのマニフェストファイルに、その時点のGit情報を埋めこむシンプルなプラグインです。あとはその情報を実行時に読みだせばOKというわけです。
他の言語でも同様のことができると思います。まぁ何となれば、ビルド時に直接Gitコマンド叩いて、それをよしなに埋めこめばいいですしね。そういえばSubversionを使っていた頃、svnversion
で取得したリビジョン番号をソースに直接書きこむリリース用スクリプトを見かけた記憶が……。
コード
次のようなシングルトンを書いてみました。
"manifest-reader"
は、build.sbtで設定したプロジェクト名です。
import java.util.jar.Manifest
import scala.collection.JavaConversions._
import scala.util.control.Exception.allCatch
/** 自身のマニフェストファイル読みこみ */
object ManifestReader {
// クラスパスにあるマニフェスト列
private[this] val manifests = getClass.getClassLoader.
getResources("META-INF/MANIFEST.MF").toSeq.
map(mu => new Manifest(mu.openStream()))
// プロジェクト名で自身のマニフェストファイルを検索
private[this] val mainAttributes = manifests.
map(_.getMainAttributes).
find(_.getValue("Implementation-Title") == "manifest-reader")
def value(key: String): Option[String] = mainAttributes.
flatMap(as => Option(as.getValue(key)))
/** sbt-git-stampが埋めこむGitのローカル状態 */
def gitClean: Option[Boolean] = value("Git-Repo-Is-Clean").
flatMap(s => allCatch.opt(s.toBoolean))
/** sbt-git-stampが埋めこむGitのハッシュ値 */
def gitRev: Option[String] = value("Git-Head-Rev")
}
これを利用してテキスト出力するところは、こんな感じ。
object Main extends App {
val githubUrl = "https://github.com/git/git"
val text = "commit: " +
ManifestReader.gitRev.map(r =>
"[" + r.take(7) + "](" + githubUrl + "/commit/" + r + ")"
).getOrElse("?") + " " +
ManifestReader.gitClean.map {
case false => "[modified]"
case true => ""
}.getOrElse("")
println(text)
}
なお仕組み上、sbt run
による実行では、JARファイルを経由しないためGit情報を取得できません。
sbt assembly
で生成したJARファイルを、scala target/scala-2.11/manifest-reader-assembly-0.0.0.jar
のようにして実行する必要があります。
確認環境
name := "manifest-reader"
version := "0.0.0"
scalaVersion := "2.11.7"
Seq(com.atlassian.labs.gitstamp.GitStampPlugin.gitStampSettings: _*)
addSbtPlugin("com.atlassian.labs" % "sbt-git-stamp" % "0.1.2")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.1")
sbt.version=0.13.9