1

通常,我的所有服务器端应用程序都有一个 URL GET 路由,它返回当前的 git 哈希,作为检查给定实例上运行的代码的确切版本的简单方法。在解释型语言(例如 Python、Node.js)中,这很容易,您只需检查在子进程中运行 shell 命令的输出。但是我通过使用lein uberjar.

所以我可以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 定义并通过 http-kit 提供的 URL 路由返回。如何在编译时或构建时运行该函数并将其转储到常量或其他我可以从路由返回的东西?

虽然我想要一个沿着这些思路的解决方案,正如所说的,这里的最终游戏是能够通过 HTTP 查询正在运行的实例并找到运行的代码的确切版本(强烈喜欢 git sha 而不是例如 semver 编号)生产中的给定实例。

我意识到我可以通过将 repo 克隆到所有实例并通过例如 ansible 在本地构建 jar 并在已知目录中查找 sha 来解决这个问题,但这看起来,嗯,hacky,以及容易出错 vs “签名” 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]}})
4

2 回答 2

2

我认为我没有做任何特别的事情来实现这一点,所以检查一下你的罐子里面有没有

 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]))))
于 2020-12-29T18:11:45.630 回答
2

我在一个项目中遇到了这个问题,他们使用了一些疯狂的无证黑客通过 lein 将 git SHA 放入全局变量中。不要那样做。

相反,要意识到您的构建过程不止一个步骤。在最简单的情况下,这两个步骤是:

  1. 捕获 git SHA 并将其保存到文件中(通常类似于./resources/build-info.txt(或者,甚至更好build-info.edn)。
  2. 调用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!)。

于 2020-12-29T19:37:27.163 回答