Reputation: 4062
Our team is working with Clojure projects that use deps.edn
We are used to NPM projects where we store the version number in the package.json file. It looks like Leiningen users may have stored the version number in a project.clj file before. Is there a community-wide convention for versioning Clojure projects? I have seen that people and official docs mention using Git tags but wondering if there is some popular way that developers using deps.edn store the version number in a file.
Thank you!
Upvotes: 1
Views: 606
Reputation: 1446
I would say it depends on the intended use of the version number you would like to store, as well as the toolchain you are using. Since you're apparently not using Lein, this answer won't refer to any idioms related to Lein.
A convention in the deps.edn
world, would be to store the project version data in the pom.xml
file, which can be generated from your deps.edn
file by invoking clojure -Spom
in the same directory as your deps.edn
file, and then editing the version number in that file manually or via a script. A fair amount of tooling in the deps ecosystem relies on the existence of a pom.xml
file and directly or transitively reads version info from that file.
Unfortunately, XML isn't very ergonomic to interact with in Clojure, so if you need to parse the version in the running code of your project, this can be a bit of a nuisance. To achieve this, I have seen the independent maintenance of multiple versions before (not ideal) in the POM and in Clojure elsewhere, I have seen POM's read in as resources and the version parsed out, and I have seen libraries like versioneer used as well.
I personally would recommend using versioneer in your case, which will traverse system properties and then the pom.properties
file, looking for a version. The source is straightforward and easy to understand. Both depstar and tools.build will generate a pom.properties
file which versioneer can read.
Upvotes: 0
Reputation: 807
I don't know that there is an established convention, but this is what I use.
For an app (in contrast to a lib) what I've done is store the version in resources/version.edn
(which is NOT kept under version control) and read that as part of the config of the app during startup. I use the major.minor.gitcount
versioning, but you can change that easily to suit your needs. I use juxt/aero
for configuration management, but any similar library or bespoke config management should work. Here is an excerpt from my 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)))
Here is an excerpt from my config.edn
(for 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"]
}
And, the -main
function looks like
(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))))
Upvotes: 1
Reputation: 11
(defproject my.domain/service
(-> "resources/service.VERSION" slurp .trim)
...
as for leiningen projects
Upvotes: 1
Reputation: 29958
I have only used Leiningen to publish JAR files so far. In this case, the version string is at the top of the file like
(defproject tupelo/demo "0.1.0-SNAPSHOT"
and it is most easily maintained by just editing project.clj
.
Just last month, the final version of tools.build was released, which is the "official" way of publishing JAR files using the Deps/CLI
system. I haven't had a chance to play with it yet but the example in the guide shows how to include the version string when building a JAR file. The example even uses an automation technique based on counting commits in 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}))
Upvotes: 6