【问题标题】:What is a common convention for storing a project version number in a Clojure project?在 Clojure 项目中存储项目版本号的常见约定是什么?
【发布时间】:2021-11-25 19:58:21
【问题描述】:

我们的团队正在处理使用 deps.edn 的 Clojure 项目

我们习惯于将版本号存储在 package.json 文件中的 NPM 项目。看起来 Leiningen 用户之前可能已经将版本号存储在 project.clj 文件中。是否有针对 Clojure 项目版本控制的社区范围的约定?我看到人们和official docs 提到使用 Git 标签,但想知道是否有一些流行的方式让开发人员使用 deps.edn 将版本号存储在文件中。

谢谢!

【问题讨论】:

    标签: clojure version versioning leiningen deps-edn


    【解决方案1】:

    到目前为止,我只使用 Leiningen 发布 JAR 文件。在这种情况下,版本字符串位于文件的顶部,如

    (defproject tupelo/demo "0.1.0-SNAPSHOT"
    

    只需编辑project.clj即可轻松维护。

    就在上个月,tools.build 的最终版本发布了,这是使用Deps/CLI 系统发布 JAR 文件的“官方”方式。我还没有机会玩它,但the example in the guide 展示了如何在构建 JAR 文件时包含版本字符串。该示例甚至使用了一种基于 git 中的提交计数的自动化技术。

    (ns build
      (:require [clojure.tools.build.api :as b]))
    
    (def lib 'my/lib1)
    (def version (format "1.2.%s" (b/git-count-revs nil)))
    (def class-dir "target/classes")
    (def basis (b/create-basis {:project "deps.edn"}))
    (def jar-file (format "target/%s-%s.jar" (name lib) version))
    
    (defn clean [_]
      (b/delete {:path "target"}))
    
    (defn jar [_]
      (b/write-pom {:class-dir class-dir
                    :lib lib
                    :version version
                    :basis basis
                    :src-dirs ["src"]})
      (b/copy-dir {:src-dirs ["src" "resources"]
                   :target-dir class-dir})
      (b/jar {:class-dir class-dir
              :jar-file jar-file}))
    

    【讨论】:

      【解决方案2】:

      我不知道有一个既定的约定,但这是我使用的。

      对于应用程序(与 lib 相比),我所做的是将版本存储在 resources/version.edn 中(不受版本控制),并在启动期间将其作为应用程序配置的一部分进行读取。我使用major.minor.gitcount 版本控制,但您可以轻松更改它以满足您的需求。我使用juxt/aero 进行配置管理,但任何类似的库或定制的配置管理都应该可以工作。这是我的build.clj的摘录。

      (ns build
        "A build script for myapp."
        (:require [clojure.tools.build.api :as b]
                  [org.corfield.build :as bb]))
      
      (def major-version 0)
      (def minor-version 2)
      (def app 'com.myorg/myapp)
      (def main 'com.myorg.myapp)
      (def version (format "%d.%d.%s" major-version minor-version (b/git-count-revs nil)))
      (def version-file "resources/version.edn")
      
      (defn uber [opts]
        (b/write-file {:path version-file :content {:version-string version}})
        (-> opts
            (assoc :lib app :version version :main main)
            (bb/uber)))
      

      这是我的config.edn 的摘录(对于juxt/aero

      {:app-config #merge [{:name "My App Name"
                            :credentials-file-path #or [#env CRED_PATH #join [#env HOME "/credentials.json"]]
                            :other-config "something"
                            }
                           #include "version.edn"]
      }
      

      而且,-main 函数看起来像

      (defn -main
        [& args]
        (try
          (log/info "")
          (log/info ">>>>>>>>>>>>>>>>> Starting Log >>>>>>>>>>>>>>>>>")
          (let [{:keys [options arguments exit-message ok?]} (validate-args args cli-options)]
            (log/debug "Options:" options)
            (log/debug "Arguments:" arguments)
            (cond exit-message
                  (exit (if ok? 0 1) exit-message)
                  ;;
                  :else
                  (let [system-config (config/system-config :prod options)]
                    (log/info "Initializing My App.")
                    (cond (not (config/config-valid? system-config)) (exit 1 (config/explain-config system-config))
                          (:version options) (exit 0 (str "Version: " (config/app-version-string system-config)))
                          :else
                          (start-the-system)
                          ))
          (catch Exception e (log/error e))))
      

      【讨论】:

      • 我很好奇你为什么不在版本控制中跟踪你的 version.edn 文件。
      • 因为(在我的情况下)它依赖于 git 提交,因此是在生成 uberjar 之前生成的。我确实将 build.clj(包含主要/次要版本)置于版本控制之下。
      【解决方案3】:
      (defproject my.domain/service
        (-> "resources/service.VERSION" slurp .trim)
      ...
      

      关于 leiningen 项目

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      【解决方案4】:

      我会说这取决于您想要存储的版本号的预期用途,以及您正在使用的工具链。由于您显然没有使用 Lein,因此此答案不会引用与 Lein 相关的任何成语。

      deps.edn 世界中的一个约定是将项目版本数据存储在 pom.xml 文件中,该文件可以通过在与 @987654330 相同的目录中调用 clojure -Spom 从您的 deps.edn 文件中生成@ 文件,然后手动或通过脚本编辑该文件中的版本号。 deps 生态系统中的大量工具依赖于 pom.xml 文件的存在,并直接或传递地从该文件中读取版本信息。

      不幸的是,在 Clojure 中与 XML 交互不是很符合人体工程学,因此如果您需要在项目的运行代码中解析版本,这可能会有点麻烦。为了实现这一点,我在 POM 和 Clojure 其他地方看到了多个版本的独立维护(不理想),我看到 POM 作为资源读入和解析出的版本,我看到像 versioneer 这样的库使用也是。

      我个人建议在您的情况下使用versioneer,它将遍历系统属性,然后遍历pom.properties 文件,寻找版本。 source 简单易懂。 depstartools.build 都将生成一个 pom.properties 文件,版本管理员可以读取该文件。

      【讨论】:

        猜你喜欢
        • 2010-11-11
        • 1970-01-01
        • 2011-01-14
        • 1970-01-01
        • 2010-12-29
        • 1970-01-01
        • 2023-04-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多