Fork me on GitHub
#boot
<
2016-03-13
>
bo01:03:50

Is it possible to change the boot env for a single task run? E.g. a build task can’t be called from a repl because I might have dev-only source-paths added, so I’d like to be able to make it set a specific source-path for building without affecting the source paths in the repl as a whole. Is this possible?

bo01:03:18

may be an obvious question, but I’m only a day into boot and haven’t been able to figure out how people handle these situations.

bo01:03:33

Like-wise for wanting to run tests from the repl without adding the test sources into the main repl

micha01:03:52

i think what you might want to do is create a separate repl in a pod

micha01:03:09

and have the main pod have the correct classpath for running tasks

micha01:03:27

because you need to run tasks in the main pod context

micha01:03:41

because there is state there that boot needs

micha01:03:07

you can use the boot.pod/make-pod function to create a new pod

micha01:03:19

then you can use boot.core/launch-nrepl to launch a repl server in that pod

bo01:03:18

It may just be that I don’t grok pods, but I thought I’d seen that a REPL can’t be in a pod). Furthermore, I don’t see how that fixes the problem of runnign tasks that have different source-path needs. Like running a (boot (tests)) then (boot (build)) as the former will affect the contents of the built jar

micha01:03:59

there is a way to run boot in boot

micha01:03:03

which is the way to do that

micha01:03:16

but if this is your first day you may not want to get frustrated with that

micha01:03:48

but you can totally make a repl in a pod, no problem

micha01:03:55

i mean the repl you're in is in a pod

micha01:03:06

with boot all clojure runs in pods

bo01:03:15

so multiple reps are you meaning having multiple processes or having a repl that I exit every time I need to run a boot task in the main repl, then re-enter?

micha01:03:41

you can have multiple repls, yes

micha01:03:01

it's unusual to need that though

bo01:03:11

in the smae process? I don’t visualise how that’s useful

micha01:03:20

because it's rare to be both developing, testing, and making production builds all at the same time

micha01:03:45

i'm not following

bo01:03:52

re: repl in pod, https://github.com/boot-clj/boot/wiki/Cider-REPL seems to allude to repls being special and that they can’t run in a pod because it needs to be in project context AND have access to boot context

bo01:03:26

@micha: frankly, I’m probably just confused. Boot seems to try to be quite functional but then has a global shared, mutable, env

micha01:03:32

yes, the repl task can't run in a pod

micha01:03:41

but you can start a repl in a pod

micha01:03:50

it's just that tasks can only really run from the main pod

micha01:03:58

which is the pod your build.boot is evaluated in

bo01:03:59

@micha: use-case where I first ran into this: a build task which first runs all the tests to check that it’s passing before building. The former corrupts the env which then makes the build artifact include tests

micha01:03:22

ah you can use the boot-test tasks

micha01:03:28

that runs tests in a pod

micha01:03:37

so as not to affect your main environment

bo01:03:46

I am using boot-test. It doesn’t see my test paths unless I first add them to the env though

bo01:03:00

it doesn’t appear to have an option to specify test paths either

bo01:03:11

based on boot bt/run-tests -h, for example

bo01:03:13

@micha: I was precisely expecting boot-test to provide a way to declare test paths for it to use (I was also expecting it to have a task that would only call the next-task if the tests passed, but instead I'd just use the version that throws an exception, which seems good enough)

bo01:03:12

so I suppose what you are saying is that I could make my own test task which creates a pod, adds the path, then calls boot-test’s task, which I suppose creates yet another pod?

bo01:03:40

@micha: at a glance, that looks like exactly what I was hoping for

bo01:03:59

hah except that it mutates the state, then resets it

bo01:03:08

which seems less nice

micha01:03:10

that's how dynamic bindings work

micha01:03:31

it's not really doing anything bad

micha01:03:46

like with clojure when you do (binding [*foo* bar] ...)

micha01:03:54

that's mutating state

micha01:03:08

but clojure guarantees that it's only visible to a single thread

micha01:03:12

which is also what boot does

micha01:03:21

the boot pipeline runs in a single thread

bo01:03:25

micha: fair enough

bo01:03:34

I was expecting it to surround it with a pod

bo01:03:40

but I guess that’s probably a bunch slower for no real gain

micha01:03:56

pods are completely separate runtimes though

micha01:03:04

so you can't really wrap anything in a pod as such

micha01:03:24

like a clojure vector in one pod would be just an unknown java object in another pod

micha01:03:32

any clojure data basically

micha01:03:01

because each clojure runtime creates the classes and interfaces for core collections etc at runtime, dynamically

micha01:03:37

so the class clojure.lang.PersistentVector in one pod is totally different from the class named clojure.lang.PersistentVector in another pod

bo01:03:54

Yeah, that’s how I already understood it, but probably not deeply enough to grok all implications. You earlier stated that boot-test creates it’s own pod so was vamping on that idea a bit

micha01:03:23

yeah the test pod is like a sort of worker

micha01:03:32

you can send it a job and it will doit

bo01:03:37

yeah I was reading the code a bit and did see that

bo01:03:57

I guess having boot-test just accept some extra source-paths would be neat

micha01:03:39

yeah that's a good idea

micha01:03:50

i wonder if there is already an issue for that

micha01:03:08

i'm working on boot stuff this weekend, i'll see if i can add that

bo01:03:45

@micha: in the “boot for lein users” pages I don’t see dev dependencies listed much. From reading a bunch of boot scripts in different projects it seems like some people are just adding deps to the env in certain tasks (which I have been) while others are adding them to the root env but with scope “test”. Are there any implications of one approach or the other or are they specifically for different use cases that I haven’t picked up on yet?

bo01:03:49

@micha: want me to open an issue?

micha01:03:58

i myself havent had the need to have separate dev dependencies ever

micha01:03:13

i'm curious to know about your use case

micha01:03:22

why do you need to separate the dev deps?

micha01:03:41

(i use the :scope "test" method myself)

bo01:03:19

@micha: well for example I don’t need asset autobuilding in production (i’d precompile it all to be served), or in dev I might want a ring middleware which displays extra debug information on exceptions, but in production I wouldn’t expose exceptions at all

micha01:03:09

normally i'd use environment variables for that kind of thing

micha01:03:25

like my app wouldn't use that middleware if it's in production according to the env

bo01:03:56

micha: I do too but it’s common practice at least in lein land to not even include those dependencies in, for example, an uberjar for prod

micha01:03:16

the uber task will only include certain scopes

micha01:03:25

test isn't included in uber's explosions

bo01:03:31

so in my case, I have a dev-only source-path which might expose middleware to be wired up and require the dev-only middleware

bo01:03:03

yeah that’s what I have inferred from reading other projects’ build.boot files

bo01:03:11

i too have been adding test scope to those dependencies

micha01:03:27

it's also quite easy to use the sift task to sift out things you don't want

bo01:03:35

but since the “for lein users” doc pages don’t explicitly make that connection, I wasn’t 100% sure I was on the right path there

micha01:03:38

before you make the jar

bo01:03:00

yeah I am using sift now to clean out source assets and .clj files that are aot’d etc

bo01:03:24

I think :scope “test” is the clearest way I’ve seen so far and it sounds like there isn’t a gotcha with that that I’ve missed so should be a-ok.

micha01:03:00

in general we have tried to avoid adding things like directly specifying dependencies to tasks etc

micha01:03:21

because it starts to get more complicated to think about

micha01:03:36

i like scope test, i can do eevrything i need to do using that technique

micha01:03:50

i mean as far as test dependencies etc goes

bo01:03:00

yeah it works fine for “dev dependencies” (which aren’t test in the sense they aren’t strictly there to support any kind of automated tests) it’s just the name (which I understand is a maven thing) through me momentarily

micha01:03:06

for uberjars i've been having very good results using a very small shim that gets AOT compiled, leaving my actual application as source

bo01:03:10

yeah I suppose with :aot :all things you don’t require won’t get aot’d so simply wiping any /.clj[cs]?$/ files is enough to remove dev deps anyway

micha01:03:16

AOT has all kinds of weird footguns lurking, i try to avoid it

micha01:03:57

the main idea there is

(ns foo.main
  (:gen-class))

(defn -main [& args]
  (require 'foo.core)
  (apply (resolve 'foo.core/-main) args))

micha01:03:15

to AOT compile that namespace instead of foo.core

micha01:03:08

then you can use the watch task while you're working on your uberjar

bo01:03:16

micha: yeah I’m actually doing this incidentally anyway, though I’m aot’ing everything atm

micha01:03:22

and you won't get issues with recompiling a class that's already been loaded

bo02:03:03

I’m not doing any kind of compilation with watch atm

micha02:03:05

uberjars get a huge benefit from incremental compilation because boot can cache everything

bo02:03:26

I can imagine

micha02:03:30

so like the first compile might take 8-10 seconds to build the uberjar

micha02:03:36

and then after that it's like 1s

bo02:03:14

if you’re watch’ing only right? My understanding is that boot doesn’t maintain any kind of cross-process cache

micha02:03:38

that's right, although uberjar's do use a persistent cache

micha02:03:52

there is a facility in boot for making persistent caches

micha02:03:01

both global and per-project

micha02:03:19

the uber task uses the global one, with the hash key being the md5 hash of the jar contents

micha02:03:26

i mean of the jar file itself

micha02:03:37

so once it unzips a jar it can cache all of that

micha02:03:55

so the second time you build an uberjar will be a lot faster than the first time

micha02:03:01

even without the watch task

micha02:03:23

this is possible because boot knows exactly when to invalidate the cache

micha02:03:43

if the jar file's md5sum hasn't changed then it knows that the cached contents are ok

micha02:03:47

and it can use them

bo02:03:21

makes sense

micha02:03:34

so tl;dr boot will cache things, but only when there is a foolproof way to invalidate the cache

micha02:03:39

so you never get stale things

bo02:03:13

can the content-addressed cache strategy be used for :aot?

bo02:03:35

(none of this is really important to me right now, FWIW, I’m just curious and playing with boot in a fresh project so I don’t have any strict needs or anything)

micha02:03:35

it's not used for that currently, i'm not sure how that would work

micha02:03:55

is it possible to know if a compiled class is "correct"?

micha02:03:15

like how would boot know to evict a compiled class from the cache?

micha02:03:57

also a single namespace will be compiled into multiple .class files, which is also weird and hard to think about

bo02:03:10

ah yeah of course

micha02:03:45

i just remember having a terrible time with caching in every build tool i've ever used pretty much

micha02:03:07

and you end up running the clean task all the time out of desperation

micha02:03:01

it's extremely depressing to spend an hour debuggin some crazy problem that turns out to be caused by stale artifacts

micha02:03:31

or your thing works and you work for a few hours, then you clean and rebuild and everything is broksn

micha02:03:38

also incredibly depressing lol

bo02:03:12

yes I too have been there

bo02:03:27

anyway thanks for the discussion. It’s been very helpful. Unfortunately I have to go to some grocery shopping and other real life things.

micha02:03:05

later! if you have any issues let us know simple_smile

micha02:03:15

i mean with boot

micha02:03:19

not with groceries

taylor.sando02:03:44

(deftask api-test []
  (merge-env! :source-paths (get-in config [:api :test :source-paths])
              :dependencies (get-in config [:api :test :dependencies]))

  (require 'adzerk.boot-test)
  (let [api-test (resolve 'adzerk.boot-test/test)]
    (println "Hello World")
    (comp
     (watch)
     (api-test)
     #_(report-test))))

taylor.sando02:03:02

Can you run this in the repl? Seems like when I run (api-test), it returns the comp function

taylor.sando02:03:54

I mostly just want to save memory by not having to run a separate jvm instance for testing

micha02:03:34

@taylor.sando: does (boot (api-test)) not work in the repl?

micha02:03:14

it looks like it should work ok

micha02:03:30

oh wait, it's recursive

micha02:03:04

i'm not sure my brain can handle that

micha02:03:56

oh nevermind, it's not recursive

taylor.sando03:03:57

I wasn't running the boot before api-test. Can you run the watch task in a future or delay so that it doesn't take over the repl?

micha03:03:37

you can do (def b (future (boot (api-test))))

micha03:03:50

then to end it you can do (future-cancel b)

taylor.sando03:03:57

Does boot-test always have a really long delay to run? I'm getting 16 seconds for just one test.

micha03:03:31

is datomic involved?

taylor.sando03:03:00

It's a dependency, but not involved in the one test I just made

taylor.sando03:03:15

Does loading datomic slow things down?

micha03:03:34

i think so

micha03:03:45

you can probably test it by removing things

taylor.sando03:03:59

Ya taking out the requires speeds things up a lot

micha03:03:54

boot test has a :requires option

micha03:03:08

you can use that to preload those and warm them up

micha03:03:15

should help some

micha03:03:47

> :requires Extra namespaces to pre-load into the pool of test pods for speed.

taylor.sando03:03:56

I added :requires #{'datomic.api}, but it didn't really speed things up.

micha03:03:02

maybe it's osmething you're doing with datomic that's being slow

taylor.sando03:03:18

The test is just (is (= 5 5)) at the moment. I removed the datomic-specific tests

taylor.sando03:03:34

I'll just run a separate instance and use run-all-tests with the namespaces, it's not absolutely critical that I have this all in one jvm

micha03:03:00

how does multiple jvms relate to the slowness problem?

micha03:03:07

wouldn't it be just as slow in another jvm?

taylor.sando03:03:47

I can run clojure.test/run-all-tests without the same slowness. The separate jvm is just because I'm using mount at the moment, and you can't really have two instances of mount going. There is yurt, but it hasn't been updated to use the latest mount changes.

bo03:03:41

@micha with-env from boot-snippets doesn’t seem to do anything. I did a (show :environment true) inside and outside the block and the env seems unchanged

micha03:03:10

look at boot.pod/env somewhere in there

micha03:03:15

it should be different

taylor.sando04:03:30

requiring pedestal seems to really slow things down on the initial run

bo04:03:54

micha: egh actually I think it’s the way I’m using env. It really has to wrap the invocation of a specific task but I’m wrapping a whole composition of tasks which means when they actually are called the environment is probably already reset

bo04:03:01

er wtf no even that doesn’t work

micha04:03:05

tasks are kind of like stateful transducers, like the way the creation of the transducer is done separately from the use of it in a pipeline

micha04:03:16

tasks normally will create their pods in the creation phase

micha04:03:29

which should work, but some of them unfortunately do not

micha04:03:46

this is something that i'm working on fixing in the boot core tasks

micha04:03:59

and the ones i help to maintain

micha04:03:26

so you may be running into an issue related to that

bo04:03:45

I mean the with-env macro is really simple, so I am kinda surprised that this still has a :source-paths of just #{“src”}:

(with-env
    {:source-paths #{"src" "test”}}
    (show :env true))

micha04:03:57

oh that's differernt

micha04:03:09

that's showing the env that is in effect when the pipeline runs

micha04:03:15

so that's working correctly

micha04:03:44

the with-env macro only affects the environment during the creation of the task

micha04:03:48

for example:

bo04:03:03

hmm well this is what I was originally trying, but run-tests still does not use the altered source-paths:

(with-env
    {:source-paths #{"src" "test"}}
    (comp (watch)
       (bt/run-tests)))

bo04:03:14

I’m guessing that’s because it’s been reset by the time it actually runs as mentioned above

micha04:03:32

(deftask foo
  []
  (let [p (make-pod (get-env))]
    (with-pre-wrap [fs]
      ...

bo04:03:34

it might work if I wrapped both watch and run-tests, but that’s annoying

micha04:03:41

look at that task

micha04:03:00

if you wrap that with the with-env macro it will affect the env when the pod is created

micha04:03:12

which is what that macro is intended to do

micha04:03:44

(deftask bar
  []
  (comp
    (watch)
    (with-env the-env
      (foo))))

micha04:03:41

i've only really used a macro like that when i had some annoying dependency conflicts and i wanted a shortcut to get something working temporarily

bo04:03:21

yeah I can tell I’m going against the grain here, but I guess I’m just used to a certain workflow.

bo04:03:42

Maybe I need to learn more abotu pods so I can jsut create my own

micha04:03:03

that sounds like a good plan simple_smile

bo04:03:22

(comp (watch) (with-env {…} (run-tests))) probably might work in some way, but then I imagine the watch isn’t watching the tests, right?

micha04:03:48

the watch task just watches your source files

bo04:03:52

hence (let [e {…}] (comp (with-env e (watch)) (with-env e (run-tests))))

micha04:03:08

it doesn't really know anything about the tasks it will pass the fileset to for the rest of the pipeline

micha04:03:47

i suspect there is a simpler way to make it work

bo04:03:52

So recall I’m trying to avoid polluting the caller of a task with changes needed for the task. I started with a (set-env! :source-paths #(conj % “src”)) in the test task

micha04:03:10

i'd probably start there

bo04:03:22

but since I’m having a task which is a “dev” mode entry point, which starts a repl with just src and dev src-paths and an auto test runner with src and test paths, it’s getting messy

micha04:03:36

it's extremely rare to need to do so much shuffling of environment stuff

micha04:03:55

there is almost certainly a more straightforward way to organize the project

bo04:03:11

this isn’t about organization, it’s about workflow

micha04:03:29

what is the workflow you'd like to achieve?

bo04:03:33

I’ll take anything that lets me have a workflow of something like boot [cider] dev which starts an nREPL server that just has “dev” and “src” on the source-paths and starts a watch and test run with both “src” and “test” in source-paths

micha04:03:11

what is the purpose of having different classpaths?

micha04:03:19

that's the part i'm not understanding

bo04:03:02

It’s a matter of purity I guess. Each task should have the same classpath when run as a group as when run individually

bo04:03:19

if I just ran boot test it wouldn’t include dev

bo04:03:28

if I just ran boot repl it wouldn’t include test

micha04:03:32

but what's the purpose?

micha04:03:09

i don't really have any philosophical preference, i just want to make computer programs

bo04:03:00

really, it just bothers me. Probably rooted in my background with languages like Ruby where when A loads B and then loads C somehow C knows about B and it means a lot of spooky action at a distance so I have a keen aversion to that kind of pollution

micha04:03:02

i put all the things i need on the classpath, and just go from there

micha04:03:23

luckily we don't need to do those kinds of things in clojure, though

bo04:03:47

micha: thank god, I’m just giving context for this particular tick of mine

bo04:03:08

in any case, it does seem strange to me that the fileset etc is strictly functional but the environment is not

micha04:03:25

you should give the straightforward alltogether way a shot and see how it goes, maybe you'll enjoy it simple_smile

bo04:03:39

from an ergonomic perspective as a first time user, it was very surprising. I expected a change in env to propagate to a task and it’s sub-tasks but not to the previous task

micha04:03:41

the fileset isn't strictly functional, though

micha04:03:53

it's still closely coupled to the classpath

micha04:03:01

which is definitely mutable shared state

micha04:03:13

what the fileset gives you is a way to manage that state

bo04:03:22

Maybe not strictly functional but the method of passing the input and output fileset between tasks is still pretty functional, compared to the environment

micha04:03:35

right, and the fileset is an immutable value, too

bo04:03:47

micha: sure but it was surprising to me that there wasn’t a great way to manage the state of the environment

micha04:03:05

but the immutable fileset object is useless if it doesn't directly relate to the actual mutable classpath

micha04:03:11

well there is

micha04:03:24

i mean the classpath isn't a value

micha04:03:29

it wouldn't work if it was

micha04:03:37

because the whole purpose of it is to be shared state

micha04:03:51

if each expression had its own immutable classpath then you couldn't add dependencies

micha04:03:56

or anything like that

micha04:03:35

but anyway you're going to be interacting with java things that expect to use a noremal java classpath

micha04:03:47

so reinventing that wasn't really an option

micha04:03:30

one of the things about the jvm is that you can't unload classes reliably

micha04:03:52

so adding a jar to a classloader is not a reversible process

micha04:03:31

or a directory, for that matter, but boot does a thing that makes it work

bo04:03:52

Yeah I understand that. My desire for separation of the class path in these different modes is probably because I’ve picked up from projects like luminus and examples in system/mount, etc, patterns like declaring the same namespace in different source-paths to do things like vary configuration (e.g. diff middleware definition) with minimal conditionals. That’s really really nice, but it requires being able to not include a certain path in the source-paths at certain times

micha04:03:53

you can use pods to have separate cojure runtimes each with their own different dependencies

bo04:03:47

this first actually bit me because my build task wouldn’t run from the repl because my dev-only user.clj depended on boot but was getting accidentally included into the jar because “dev” was on source-path and then obviously not compiling

micha04:03:47

why wouldn't it compile?

bo04:03:53

because boot is not in the uberjar

bo04:03:57

it’s not a project dependency

micha04:03:01

are you talking about AOT or just require?

bo04:03:08

require

micha04:03:41

why would that be needed in the uberjar?

bo04:03:44

running (boot (build)) complained about not finding boot.core if AOT or similarly when later run if not AOT

bo04:03:06

it’s not needed in the uberjar. It’s not wanted. It was a side-effect of having dev dir on the source-path

micha04:03:20

having the file in the jar isn't a problem though

micha04:03:28

only if you require it

bo04:03:35

which is what prompted my quest to have the source paths specifically set during the execution of a certain task without pollution other parts

micha04:03:56

boot tasks are similar

bo04:03:58

dev/user.clj requires boot. That’s a file I only expect to ever be relevant when developing locally, where boot is present

micha04:03:05

if you look at most boot tasks, like boot-test for example

micha04:03:20

there is a namespace adzerk.boot-test.impl or something like that

micha04:03:37

it depends on things that are not in the environment that you run the test task from

bo04:03:37

(which works great IFF “dev” is nto on the source-paths set when uberjarring happens)

micha04:03:46

it can only run in the pod that the task creates

micha04:03:53

it's in the jar file

micha04:03:06

but it's not a problem because you don't require that namespace except in the pod

micha04:03:24

there is no need for fancy footwork there

micha04:03:00

if your -main function in the uberjar doesn't require the user namespace there won't be a problem

micha04:03:25

unless you're doing AOT compilation for every namespace, in which case you'll probably have many weird issues to untangle

bo04:03:09

well I’m gonna step back a bit and stop trying to go against the grain

bo04:03:23

I’ll live as long as I can with the single classpath and just ignore it

micha04:03:43

haha give it a shot

bo04:03:46

it’s probably just OCD on my part but it really bothers me that different tasks pollute the env of others

micha04:03:10

maybe don't think of it as pollution

bo04:03:12

I wish env passed between tasks just like filesets

bo04:03:27

though env wouldn’t be the ideal name in that case hah

bo04:03:28

maybe ctx

micha04:03:31

one thing about tasks that you will like is that no boot task every has transitiev dependencies

micha04:03:47

that is, tasks don't pollute the classpath

micha04:03:13

you can add as many boot task dependencies to your project as you want, you can never have a conflict

micha04:03:40

that's the place where it's really important to maintain discipline and hygiene

bo04:03:49

yeah… I probably don’t fully grok that yet.

micha04:03:56

because when you add a dependency you're using someone else's code

micha04:03:26

however the stuff you have in your project is controlled by you

micha04:03:39

so you can organize it so the dev things don't conflict iwth other things

micha04:03:19

i'm not familiar with the patterns you describe about overloading namespace names and sort of metaprogramming in the project.clj by including or excluding them

bo04:03:39

It just always feel wrong whenever I have to go change some thing over there to change the behaviour of something over here. I’m chanigng source-paths in a global env so that a task I’m about to call which will check that env for that config can act on it. It’s impossible to tell the watch task, for instance, to watch “src” and “test” without telling everything everywhere that “test” is now a source-path 😞

micha04:03:41

but i am kind of skeptical of those patterns

micha04:03:05

well you're setting up the jvm classpath

bo04:03:45

I know the source-paths affect the classpath at certain points, but watch, for example, doesn’t strictly need to modify the cp

bo04:03:53

it’s just taking advantage of a known key that has that implication

micha04:03:58

it's looking at the classpath

micha04:03:11

that's what it's watching

bo04:03:19

huh that’s annoying

micha04:03:31

you can make your own watch task, though

bo04:03:37

I mean not really annoying I guess

micha04:03:51

there is also a "manual" option to the watch task

bo04:03:54

it’s just my mental model is not quite right and is taking a bruising

taylor.sando04:03:43

For bootignore, how would you exclude all subdirectories? I've tried #"^src/dev/path/to/dir/.*?" #"^src/dev/path/to/dir/*" and #"^src/dev/path/to/dir"

micha05:03:44

the patterns should match paths in the fileset

micha05:03:04

not paths in the filesystem

taylor.sando05:03:24

What would the pattern look like if I want to include "src/main", but exclude "src/main/do-not-want"?

micha05:03:02

first do boot show -f

micha05:03:11

that will show you the paths you will be matching against

micha05:03:31

do you see src in the output of that?

micha05:03:12

so any pattern with src in it won't match anything

micha05:03:45

you can try different patterns until boot show -f produces the result you like

onetom06:03:17

@micha: what's the point of uberjar-ing in dev mode?

onetom06:03:28

we are using the reloaded.repl flow and that ensures <1s reload times

onetom06:03:47

or were u talking about some CI server making the uberjars in 1s?

micha06:03:26

@onetom: just if i want to run the uberjar while i'm working

micha06:03:34

for whatever reason

bo06:03:21

are people typically using boot-reload instead of figwheel?

onetom08:03:07

@bo: i haven't even realized there is a boot-figwheel, but as i see it just brought over the same declarative config approach which proved to be a bit rigid in lein.

onetom08:03:49

we just started using boot-reload because about a year ago but it's still a bit unclear to me how to make it play well with hoplon and have sub-second updates without reloading the whole page.

juhoteperi16:03:13

Boot only reads build.boot from workdir so I don't understand what is this projectdir supposed to be

micha16:03:48

i think it was for if you have subdirectories with their own build.boot files in them

micha16:03:16

i don't think it's officially documented, so we could remove it

juhoteperi16:03:00

Yeah, I don't know if causes any problems but looks like it might if the project is not git project

juhoteperi16:03:07

And doesn't seem very useful

micha16:03:35

yeah it was premature

juhoteperi16:03:50

Empperi mentioned some problems on IRC about Boot not reading boot.properties file (on Windows)

micha16:03:56

that's a case of less-is-more i think

juhoteperi16:03:22

Doesn't look like that is the reason, but we wondered why does it exist

micha16:03:43

maybe we remove that in 2.6.0

dominicm18:03:59

I'm looking forward to 2.6

danielsz21:03:39

Hi there, to do multiple builds with boot-cljs, does it matter where in the project you put the *.cljs.edn files? In the wild, I've seen examples with the edn files under src, but I've also seen them under resources/js.

taylor.sando21:03:42

Anything in the input-path of the fileset with a .cljs.edn extension will be available.

taylor.sando21:03:04

Anything in source-paths or resource-paths

danielsz21:03:23

Is the init-fns mandatory?

danielsz21:03:48

It seems that boot-cljs does the right thing in the default case (when no builds are specified). How does it know what the main function is?

juhoteperi21:03:32

It doesn't. I will just require all namespaces in the fileset.

danielsz21:03:23

@juhoteperi: Ah, I see. Cool. So can I omit the init-fns in the ednfile?

danielsz21:03:45

Ah, I suppose not.

juhoteperi21:03:47

Ah I meant the case with no cljs.edn files

juhoteperi22:03:00

But yes, you can usually omit init-fns

juhoteperi22:03:29

If your namespaces have top-level calls to start the app, init-fns is unncessary

danielsz22:03:59

OK, very nice. Thanks.