Introduce boot.task/deftask-edn, create tasks with pure data
This PR adds the deftask-edn facilities. It basically uses edn data to generate tasks.
A better explanation can be found in the docstring:
(defmacro deftask-edn
"Create boot tasks based on an edn conf.
The body of this macro will be evaluated and the expected result has
to match the following example:
{:env {:resource-paths #{\"resources\"}
:source-paths #{\"src/web\" \"src/shared\"}
:dependencies '[[org.clojure/clojure \"1.9.0-alpha14\"]
[adzerk/boot-cljs \"2.0.0-SNAPSHOT\" :scope \"test\"]
[org.clojure/clojurescript \"1.9.456\" :scope \"test\"]
[reagent \"0.6.0\"]
...]}
:pipeline '(comp (pandeiro.boot-http/serve)
(watch)
(powerlaces.boot-cljs-devtools/cljs-devtools)
(powerlaces.boot-figreload/reload)
(adzerk.boot-cljs-repl/cljs-repl)
(adzerk.boot-cljs/cljs))
:cljs {:source-map true
:optimizations :advanced
:compiler-options {:closure-defines {\"goog.DEBUG\" false}
:verbose true}}
:cljs-devtools {...}}
As in any declarative approach, we need to establish some convention:
- the `:env` key will be passed with no modification to `set-env!`
- the `:props` key will need to contain a map of `string` keys to
`string` values that will set Java System Properties
- the keys that match a task name will provide options to that task
- the `:pipeline` key will contain the `comp` typically used in
`boot` tasks (order counts)
- if a tasks has full namespace in `:pipeline`, the namespace will be
required and the task resolved. If not, the task will be resolved in
`boot.task.built-in` first and finally in `boot.user`"
[sym & forms]
...
I welcome any feedback or rejection of this. It is basically taking the declarative/lein approach, which sometimes can be very convenient. Of course for me this should go in core so that the user has the choice :smile:
Interesting, I am using a declarative approach for the env like this: https://github.com/flyboarder/meta/blob/master/src/meta/boot.clj#L27-L34
@flyboarder It looks very similar!
So from Slack there are two votes for renaming it to boot.task/deftask-edn. Naming is hard :smile:
Also, the :pipeline key could be converted to a vector, or even a map, so that it will be easier to replace tasks in the pipeline, by either using conj or assoc on it.
Should the :env key be using merge-env!? Occasionally I need to compose multiple tasks which modify env in multiple ways (or rather I have a base & then add dev to the env).
Props is awesome, this is the other thing I commonly do.
I'm a little confused by the :cljs and :cljs-devtools key, is this related to task-options!
Yes names are only attempts 😀
So those keys are identifying the task your want to declarativly set options for .
So they must be task names.
-- Sent from my Android device with K-9 Mail. Please excuse my brevity.
Only once for every task call the set-env! is invoked.
If I have multiple tasks which add to the source-paths, does using set-env! cause them to clobber? (I thought it did, so I've been using merge-env!)
How does powerlaces.boot-cljs-devtools/cljs-devtools link to :cljs-devtools? Should it be using the full namespace (e.g. :powerlaces.boot-cljs-devtools/cljs-devtools) instead? Although I think this is kind of impractical. ::dev-tools/cljs-devtools makes the syntax a little more palatable though.
Actually, to use the full namespace, we could use symbols instead. This makes it nicer for :refer'd variables:
{`test {:foo :bah}}
;; => {adzerk.boot-test/test {:foo :bah}}
Yes we could, but I did not want to type it every time so the macro looks for task symbols in order at the moment: https://github.com/adzerk-oss/bootlaces/pull/16/files#diff-ce48b98546ca95cbc67c4ae8588d0bacR43
About set-env!, it works fine but I have noticed something...haven't had time to debug it but it looks like composing tasks will call set-env! multiple times and therefore make a mess as you are saying..