16

Clojure で書かれた継続的に配信される Web サービスがあります。自動デプロイ ツールがデプロイされたコードベースのバージョンを認識できるようにするために、Web サービスはそれがどのバージョンであるかを照会する方法を提供する必要があります。バージョンは、次のように、Leiningenビルド ツールのプロジェクト セットアップの一部として宣言されます。

(defproject my-web-service "1.2-SNAPSHOT"
  ; ... rest of project.clj
  )

コードベースは JAR ファイルとしてパッケージ化されています。

私たち開発者は、コミットごとにバージョン番号を増やしたくありません。代わりに、継続的インテグレーションサーバー (この場合は Jenkins) で新しいビルドがトリガーされるたびに、自動的にインクリメントされるようにします。たとえば、バージョン管理チェックインがこのコードベースの 40 秒ビルドを要求した場合、バージョンは1.2.42.

ビルドおよびデプロイされた特定の JAR について、何らかの方法でバージョン番号を照会できるようにしたいと考えています (たとえば、HTTP 要求を使用しますが、これは実装の詳細です)。応答には文字列が含まれている必要があります1.2.42

そのバージョン番号を実行中のアプリケーションで利用できるようにするにはどうすればよいですか?

(重複の可能性がありますが、Jenkins の側面は含まれていません: Embed version string from leiningen project in application )

4

1 に答える 1

19

このバージョン番号にアクセスする 1 つの方法はMANIFEST.MF、JAR ファイル内に保存されているファイルを使用することです。これにより、Java のjava.lang.Packageクラスを介して実行時にアクセスできるようになります。これには、次の 3 つの手順が必要です。

  1. Jenkins のビルド番号を Leiningen に渡し、project.cljdefproject宣言に組み込みます。
  2. MANIFEST.MFの値を持つを構築するようにライニンゲンに指示しますImplementation-Version
  3. バージョン番号を含むPackage#getImplementationVersion()へのアクセスを取得するために呼び出します。String

1 - Jenkins ビルド番号の取得

Jenkins の環境変数を使用して、ビルド番号 (適切な名前のBUILD_NUMBER) にアクセスできます。これは、 を使用して、JVM プロセス内で使用できますSystem.getenv("BUILD_NUMBER")。この場合、JVM プロセスはproject.clj、 を呼び出すことができる Clojure コードである leiningen スクリプトにすることができ(System/getenv "BUILD_NUMBER")ます。上記の例に従うと、返される文字列は「42」になります。

2 - MANIFEST.MF でのバージョンの設定

JAR をビルドするとき、Leiningen はMANIFEST.MFデフォルトでファイルをインクルードします。また、そのファイルに任意のキーと値のペアを設定できる構成オプションもあります。したがって、Clojure で Jenkins のビルド番号にアクセスできる場合は、それを静的バージョン宣言と組み合わせてImplementation-Version、マニフェストで を設定できます。関連する部分は次のproject.cljようになります。

(def feature-version "1.2")
(def build-version (or (System/getenv "BUILD_NUMBER") "HANDBUILT"))
(def release-version (str feature-version "." build-version))
(def project-name "my-web-service")

(defproject project-name feature-version
  :uberjar-name ~(str project-name "-" release-version ".jar")
  :manifest {"Implementation-Version" ~release-version}

  ... )

この例のいくつかの詳細に注目する価値があります。(if-let ...)いつ定義するかは、build-versionJenkins の環境変数をエミュレートする必要なく、開発者がローカルで JAR をビルドできるようにするためです。構成は、:uberjar-nameMaven/Ivy 規則を使用して名前が付けられた JAR ファイルを作成できるようにすることです。この例の結果のファイルはmy-web-service-1.2.42.jar.

この構成では、ビルド番号 42 で Leiningen が Jenkins によって呼び出されると、結果の JAR のマニフェストに「Implementation-Version: 1.2.42」という行が含まれます。

3 - 実行時のバージョンへのアクセス

使用したいバージョン文字列がマニフェスト ファイルにあるので、Clojure コードで Java 標準ライブラリを使用してアクセスできます。次のスニペットはこれを示しています。

(ns version-namespace
  (:gen-class))

(defn implementation-version []
  (-> (eval 'version-namespace) .getPackage .getImplementationVersion))

ここで、 を呼び出すgetImplementationVersion()にはPackageインスタンスが必要であり、取得するには のインスタンスが必要であることに注意してくださいjava.lang.Class。したがって、Java クラスがこの名前空間 ( への呼び出し) から生成されることを確認します (その後、そのクラスからメソッド(:gen-class)にアクセスできます。getPackage

この関数の結果は、「1.2.42」などの文字列です。

注意事項

心配しなければならない問題がいくつかあることに注意してください。

  • project.cljの呼び出しで定義されたバージョン文字列を動的に設定すると、(defproject ...)ハードコードされているバージョンに依存している場合、他のツールが機能しなくなる可能性があります
  • のセマンティクスはgetImplementationVersionわずかに悪用されています。実際にはバージョンは :pkg.getSpecificationVersion() + "." + pkg.getImplementationVersion()である必要がありますが、これらの値のいずれかを読み取るものは他にないため、実装バージョンを設定するだけで済みます。これを正しく行うには、マニフェストに「Specification-Version」も追加する必要があることに注意してください。

上記の手順により、実行中の Clojure アプリケーションは、コードをパッケージ化した Jenkins ビルドに対応するバージョン番号にアクセスできます。

于 2012-09-26T10:40:36.597 に答える