访问此版本号的一种方法是通过MANIFEST.MF
存储在 JAR 文件中的文件。这将允许在运行时通过 Java 的java.lang.Package
类进行访问。这需要以下三个步骤:
- 将 Jenkins 内部版本号传递给 Leiningen,以合并到
project.clj
的defproject
声明中。
- 指示 Leiningen 构造 a
MANIFEST.MF
的值为Implementation-Version
。
- 调用
Package#getImplementationVersion()
以获取对String
包含版本号的访问权限。
1 - 获取 Jenkins 内部版本号
可以使用 Jenkins 的环境变量来访问内部版本号(很好命名BUILD_NUMBER
)。这在 JVM 进程中可用,使用System.getenv("BUILD_NUMBER")
. 在这种情况下,JVM 进程可以是 leiningenproject.clj
脚本,它是可以调用的 Clojure 代码(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 ...)
when 定义是允许开发者在build-version
本地构建 JAR,而不需要模拟 Jenkins 的环境变量。:uberjar-name
配置是允许创建一个使用 Maven/Ivy 约定命名的 JAR 文件。此示例中的生成文件将是my-web-service-1.2.42.jar
.
使用此配置,当 Jenkins 在版本号 42 上调用 Leiningen 时,生成的 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
。因此,我们确保从这个命名空间(对 的调用(:gen-class)
)生成一个 Java 类(然后我们可以getPackage
从该类访问该方法。
该函数的结果是一个字符串,例如“1.2.42”。
注意事项
值得注意的是,您可能需要担心一些陷阱,但对于我们的用例来说是可以接受的:
project.clj
动态设置'调用中定义的版本字符串(defproject ...)
可能会导致其他一些工具无法工作,如果它们依赖于被硬编码的版本
- 的语义
getImplementationVersion
被稍微滥用了。确实版本应该是: pkg.getSpecificationVersion() + "." + pkg.getImplementationVersion()
,但由于没有其他任何东西读取这些值,我们可以只设置实现版本。请注意,正确执行此操作还需要将“规范版本”添加到清单中。
通过上述步骤,我正在运行的 Clojure 应用程序可以访问与打包代码的 Jenkins 构建相对应的版本号。