-
-
Notifications
You must be signed in to change notification settings - Fork 180
Snippets
- Access a version string at runtime, from a jar
- Accessing test resources
- Task environment conflicts
- Add previously resolved jar to the fileset
- Check dependency conflicts
- Re-using a built-in task name
Often it is desirable to print the version of the source used to build the jar. This may be a version string or a git hash. One way to achieve this is to add the version number to a file in the classpath:
;; in build.boot
(def version "1.0")
;; or from the environment
;; (def version (or (System/getenv "CIRCLE_SHA1") "SNAPSHOT"))
(deftask add-version-txt []
(with-pre-wrap fs
(let [t (tmp-dir!)]
(spit (clojure.java.io/file t "version.txt") version)
(-> fs (add-resource t) commit!))))
(deftask dist []
(comp (pom :project 'my-project
:version version)
(add-version-txt)
(aot :namespace '#{my-project.core})
(uber)
(jar :main 'my-project.core)))
;; in your app code
(defn get-version []
(some-> "version.txt" clojure.java.io/resource slurp clojure.string/trim))
In lein, you just create a dev-resources directory for your testing resources. Boot is almost as easy. Just as you need to add the source files you use for testing to the source-paths, you also need to add to the resource-paths:
(deftask testing
"Profile setup for running tests."
[]
(set-env! :source-paths #(conj % "test/clj"))
(set-env! :resource-paths #(conj % "dev-resources"))
identity)
Source: Micha Niskin on Slack
Sometimes boot tasks have conflicts with your project. You can filter the dependencies that will be used on the pod using this:
(defmacro with-env
[env & body]
(let [orig (into {} (map #(vector % (gensym)) (keys env)))]
`(let [~@(mapcat (fn [[k v]] [v `(get-env ~k)]) orig)]
~@(for [[k v] env] `(set-env! ~k ~v))
(with-let [ret# (do ~@body)]
~@(for [[k v] orig] `(set-env! ~k ~v))))))
(defn filter-deps
[deps]
(->> (get-env :dependencies)
(filterv #(some (set deps) ((juxt first (comp symbol name first)) %)))))
(defmacro with-deps
[deps & body]
`(with-env {:dependencies (filter-deps '~deps)} ~@body))
Usage: Project has deps that conflict with boot-jetty, so we filter all of those out when we instantiate the task--it will not create pods with the troublesome deps.
(deftask foo
[]
(comp (watch)
(hoplon)
(cljs)
(with-deps [boot-jetty] (serve))))
Source: Andrea Richiardi's boot-pack-source
The standard built-in/sift :add-jar
will fail when trying to resolve symbols that are not in the current env - not in (:dependencies (get-env)
.
But what if I want to explode a jar given its (already resolved) path? Say a transitive dependency obtained through pod/resolve-dependencies
. The following task will help you with that.
(core/deftask sift-jar
"Custom version of boot.task.built-in/sift :add-jar which accepts
a (previously resolved) jar file in input."
[j jar PATH str "The path of the jar file."
i include MATCH #{regex} "The set of regexes that paths must match."
v invert bool "Invert the sense of matching."]
(core/with-pre-wrap fileset
(-> fileset
(core/add-cached-resource
(digest/md5 jar)
(partial pod/unpack-jar jar)
:include (when-not invert include)
:exclude (when invert include)
:mergers pod/standard-jar-mergers)
(core/commit!))))
Source: Sean Corfield on Slack
Be fussy about dependency conflicts. Throws an exception if any.
(deftask check-conflicts
"Verify there are no dependency conflicts."
[]
(with-pass-thru fs
(require '[boot.pedantic :as pedant])
(let [dep-conflicts (resolve 'pedant/dep-conflicts)]
(if-let [conflicts (not-empty (dep-conflicts pod/env))]
(throw (ex-info (str "Unresolved dependency conflicts. "
"Use :exclusions to resolve them!")
conflicts))
(println "\nVerified there are no dependency conflicts.")))))
The tasks in boot.task.built-in are automatically included in the boot.user
namespace. As
a result, re-using one of these task names in your build.boot
results in an error.
For example, if you try to define a task called repl
, you will see the following exception:
java.lang.IllegalStateException: repl already refers to: #'boot.task.built-in/repl in namespace: boot.user
The solution is to remove the binding from the namespace before defining the task.
(ns-unmap 'boot.user 'repl)
(require '[boot.task.built-in])
(deftask repl []
(comp
(with-pass-thru _
(println "it works"))
(boot.task.built-in/repl)))
You can find other developers and users in the #hoplon
channel on freenode IRC or the boot slack channel.
If you have questions or need help, please visit the Discourse site.
- Environments
- Boot environment
- Java environment
- Tasks
- Built-ins
- Third-party
- Tasks Options
- Filesets
- Target Directory
- Pods
- Boot Exceptions
- Configuring Boot
- Updating Boot
- Setting Clojure version
- JVM Options
- S3 Repositories
- Scripts
- Task Writer's Guide
- Require inside Tasks
- Boot for Leiningen Users
- Boot in Leiningen Projects
- Repl reloading
- Repository Credentials and Deploying
- Snippets
- Troubleshooting
- FAQ
- API docs
- Core
- Pod
- Util