clojure - 如何获取运行着的Clojure应用程序版本号的运行时访问?

  显示原文与译文双语对照的内容
0 0

我有个Web服务用Clojure即连续发表 。 可以让我们的自动化部署工具来了解哪些版本的基本代码已经部署,web服务应该提供一种方法来查询哪一个版本是。 中的版本声明作为项目的一部分进行安装 Leiningen 生成工具,如下所示:

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

基本代码被打包为一个jar文件。

我们开发人员每个不想递增附属程序集的版本号。 实际上,我们希望该数值递增时自动触发新的生成在我们持续集成服务器( 在本例中Jenkins ) 。 例如,当构建此基本代码,版本的版本控制签入提示40秒 1.2.42.

对于任何特定的jar被构建并部署,我想让查询版本号( e .g不知何故。 带有HTTP请求,但是这是一个实现细节) 。 此响应应该包含字符串 1.2.42.

如何用版本号提供给正在运行的应用程序?

( 可能重复,但它并不包括Jenkins纵横比: Embed版本字符串中从leiningen项目应用程序 )?

时间:原作者:1个回答

0 0

访问此版本号的一种方法是通过 MANIFEST.MF文件,该文件是存储在jar文件中。 这将在运行时允许访问,通过Java是java.lang.Packageclass 。 这需要以下三个步骤:

  1. 同时将Jenkins内部版本号以Leiningen中出现了新的 project.clj's defproject声明。
  2. 指示Leiningen来构造一个 MANIFEST.MF使用的值。 Implementation-Version.
  3. - - - - - Package#getImplementationVersion()以获得访问权限。 String包含版本号。

1 获取Jenkins内部版本号

我们可以只使用Jenkins'环境变量可以很好地访问内部版本号( named BUILD_NUMBER) 。 这可以作为一个JVM过程,使用 System.getenv("BUILD_NUMBER"). 在这种情况下,进程可以是leiningen JVM project.clj该方法可以调用脚本,这是Clojure代码 (System/getenv "BUILD_NUMBER"). 在上例中,之后返回的String将" 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-version是让开发人员在本地生成jar,无需模拟Jenkins'环境变量。 。 :uberjar-name配置是允许创建一个jar文件,该文件是使用Maven/Ivy命名约定 本示例中生成的文件就是 my-web-service-1.2.42.jar.

使用此设置,当Leiningen Jenkins不调用在内部版本号42.48生成的jar中的清单将包含一行version: " 实现 1 .2 .42 " 。

在运行时访问version 3

既然String我们想要使用的版本已经可以在manifest文件中,我们可以使用Java标准库Clojure代码中访问它。 下面的代码片断演示了这种情况:

(ns version-namespace
  (:gen-class))
(defn implementation-version []
  (-> (eval 'version-namespace) .getPackage .getImplementationVersion))

这里请注意,才能调用 getImplementationVersion()怎么样, Package实例,就可以得到我们需要的一个实例 java.lang.Class. 因此我们可以保证会产生一个Java类从此命名空间( 在调用 (:gen-class)) ( 我们便可访问 getPackage方法将从该类。

此函数的结果是一个.g String,e 。 " 1 .2 .42 " 。

警告

值得注意的是有几个小技巧你可以不用担心,但我们一直在可接受的使用情况:

  • 动态地设置中定义的版本字符串 project.clj's (defproject ...)调用会throw一些其它工具无法正常工作的,如果它们被硬编码依赖版本
  • 语义的 getImplementationVersion被虐待一动也不动。 真正的版本应该是: pkg.getSpecificationVersion() + "." + pkg.getImplementationVersion()不过反正也无事,我们只需要读取其中一个值就是设置实现版本。 还请注意,这样做将需要正确版本" " 规范添加到清单。

通过上步骤,我的版本号对应于运行Clojure应用程序可以访问的Jenkins生成封装代码。

原作者:
...