问题描述
通常,我的所有服务器端应用程序都有一个 URL GET 路由,它返回当前的 git 哈希,作为检查给定实例上运行的代码的确切版本的简单方法。在解释型语言(例如 Python、Node.js)中,这很容易,您只需检查在子进程中运行 shell 命令的输出。但是我正在通过使用 lein uberjar
打包来将我的 Clojure 应用分发给实例。
所以我可以像这样使用 clojure.java.shell
以编程方式获取当前的 git sha:
(defn get-git-sha
[_req]
(trim ((sh "/bin/sh" "-c" "git rev-parse HEAD") :out)))
(defroutes server-routes
(GET "/revision" [] get-git-sha))
(defn serve-http
[port]
(http-server/run-server server-routes {:port port}))
但我需要一种方法在 uberjar 过程中(而不是在运行时当 jar 不再在 repo 中)将它嵌入代码中,以便从我使用 compojure 定义的 URL 路由返回并通过 http-kit 提供.我如何在编译时或构建时运行该函数并将其转储到一个常量或其他我可以从路由返回的东西?
虽然我想要一个沿着这些方向的解决方案,如上所述,这里的最终游戏是能够通过 HTTP 查询正在运行的实例并找到正在运行的代码的确切版本(强烈喜欢 git sha 而不是例如 semver 编号) 在生产中的给定实例上。
我意识到我可以通过将 repo 克隆到所有实例并通过例如在本地构建 jar 来解决这个问题。 ansible 并在已知目录中查找 sha,但这似乎是 hacky,以及容易出错与“签名”jar 文件相比,在构建时可以这么说。
编辑:
我的 project.clj 看起来像这样:
(defproject gps-server "0.1.0-SNAPSHOT"
:description "Receives GPS data over TCP"
:url "http://someurl"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "https://www.eclipse.org/legal/epl-2.0/"}
:dependencies [...]
:main ^:skip-aot gps-server.core
:target-path "target/%s"
:profiles {:uberjar {:aot [gps-server.core]}})
解决方法
我不认为我正在做任何特别的事情来实现这一点,所以请检查你的罐子里
META-INF/maven/your-project/name/pom.properties
your-project/name
来自用于构建 uberjar 的 project.clj
(defproject your-project/name "4.2.6"
...
在 pom.properties 中:
#Leiningen
#Tue Oct 01 13:20:45 CEST 2019
version=4.2.6
revision=4625a070a34ddc3c563b71025fa5dd907b406331
groupId=your-project
artifactId=name
修订版来自 git。
我有一个 /version
端点返回此信息,使用此函数
defn- get-version []
(let [rsrc (io/resource "META-INF/maven/your-project/name/pom.properties")
rdr (io/reader rsrc)
props (java.util.Properties.)]
(.load props rdr)
(into {} (for [[k v] props] [k v]))))
,
我在一个项目中遇到了这个问题,他们使用了一些疯狂的无证黑客通过 lein 将 git SHA 转换为全局变量。不要那样做。
相反,要意识到您的构建过程不止一个步骤。在最简单的情况下,两个步骤是:
- 捕获 git SHA 并将其保存到文件中(通常类似于
./resources/build-info.txt
(或者更好的是build-info.edn
)。 - 调用
lein uberjar
将所有内容打包到部署工件中。
因此,不要仅从命令行调用 lein uberjar
,而是制作一个包含上述步骤的 2 行部署脚本。也许像这样简单:
#!/bin/bash
# Capture current git SHA (or: git log -n1 --format=format:"%H")
git rev-parse HEAD > ./resources/build-info.txt
# Create uberjar
lein clean ; lein uberjar
# Copy output someplace,etc...
上述内容可以简单地保存到 ./scripts/deploy.bash
或类似的文件中(当然,它会被签入 git
!)。