Fork me on GitHub
#boot
<
2017-01-23
>
neupsh00:01:24

@mobileink i really spent too much time figuring that out 😢

ag02:01:14

hey guys, I’m trying to get powerlaces/boot-cljs-devtools to work, but failing. can someone advise?

ag02:01:47

nevermind, I think I got it

richiardiandrea03:01:23

@ag that should work, I am glad you solved, let me know if there is any other issue or open one on the repo ok?

ag03:01:55

@richiardiandrea of course! thanks!

tmarble14:01:18

Does anyone have a "best practices", minimal example of setting up a dual CLJS (browser) and CLJ (server) REPL? Right now I've added two tasks to my profile.boot: cljs-dev (which calls cider serve watch cljs-repl cljs) and clj-dev (which calls cider repl wait), but it seems "wrong" to have to pivot between these two manually when I cider-jack-in?

tmarble14:01:28

And putting tasks in profile.boot is problematic because I need to set dependencies (e.g. boot-cljs-repl) which are loaded for all other projects (I realize this is suboptimal)

martinklepsch14:01:24

@tmarble without cider but you can try tenzing. it gives you a repl that can be “turned into cljs mode” with (start-repl) and you can switch between plain clojure and cljs

tmarble14:01:44

oh yes folks have pointed me to tenzing!

tmarble14:01:51

@martinklepsch IIUC once I have "nREPL server started on port 63518 on host 0.0.0.0" i can cider-connect to that from Emacs (or connect from Cursive, etc.), right?

tmarble14:01:16

Hmmm I appreciate the point about #noBackend, but in my project I already have a backend... So perhaps my classic "cider-jack-in" will work for the backend REPL?

martinklepsch14:01:53

the repl is a repl, if you have backend code it’s not gonna say “I’m not going to load this!” 🙂

tdavis15:01:20

anybody gotten squiggly to work via cider-connect with boot? adding it to default-dependencies just breaks cider-nrepl

tosh16:01:22

@mobileink do you have an example for making http requests on app engine / boot-gae in the standard environment? i tried http-kit which gave me a security exception (?) and then i switched to http-clj and it raised

Uncaught exception from servlet
java.lang.NoClassDefFoundError: java.net.ProxySelector is a restricted class. Please see the Google App Engine developer's guide for more details.
i’m probably missing something 😄

mobileink16:01:27

@tosh did you try the greeter example? it responds to POST requests. the uploader example responds to POST.

mobileink16:01:46

what does your servlet code look like? are you using a blacklisted jar?

tosh16:01:56

i’m trying to issue post requests

tosh16:01:11

to another api (facebook messenger)

mobileink16:01:10

so you want your gae servlet to send a POST request?

tosh16:01:25

yes 🙂

tosh16:01:57

iirc the gae standard environment is a bit restrictive (eg for the python runtime it took some time to write wrappers to make sure the http libs work)

mobileink16:01:39

see also https://github.com/migae/urlfetch - haven’t used it in months but it should work, i think.

mobileink16:01:20

i see i never got around to pushing migae/urlfetch to clojars. it was developed before i switched to boot. you’ll have to clone and install it locally until I get around to pushing it, sorry.

qqq18:01:45

when using clj + cljs with different dependency sets, do I create one boot file, or separate boot files for server/client ?

esanmiguelc18:01:07

@qqq do you mean so that you don’t package dependencies for cljs in your clj code?

qqq18:01:42

and while we're at it, what's the boot equiv of "lein ring uberwar" ? 🙂

alandipert18:01:16

something like boot web uber -j war but i don't see a recent example anywhere

alandipert18:01:19

i'll make one, we should have that

esanmiguelc18:01:56

@qqq do you need to use cljs dependencies beyond your development/CI environment?

qqq18:01:42

@alandipert : awesome, thanks!

qqq18:01:26

@esanmiguelc : here's the XY problem I am writing an app where server side `= clojure on GAE client side = cljs I used to have a lein setup taht works fine (I still do) I am switching to boot and am trying to figure out how to make this all work on boot.

esanmiguelc18:01:53

@qqq right, so typically when I deploy, I deploy the compiled cljs. So my cljs dependencies are only needed in my local development, I use maven’s scope https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope to control what gets bundled for my server. I don’t know if there is a boot version of profie dependency definitions

qqq18:01:37

@esanmiguelc : oh right, yes, after my cljs is compield to js, I only care about the js libs it depends on, I don't care about the clojure libs used to generated the js

qqq18:01:48

(I compeltely misread your question earlier.)

alandipert18:01:16

i'll add a dev task that uses reload middleware in a sec

qqq18:01:46

@alandipert : you're challenging my belief that all ad companies consist solely of dementors

qqq18:01:06

I don't get it build.boot and core.clj and build.properties are really short

qqq18:01:10

is the whole thing < 20 lines ?

qqq18:01:12

this seems way too simple

alandipert18:01:18

it leans on lots of tasks built in boot

alandipert18:01:48

the little stack there ropes in probably a few thousands lines of clj

alandipert18:01:55

well, maybe a few hundred

qqq18:01:59

okay, this makes sense

qqq19:01:08

it'sbasically jsut "wrapping" the uber/war tasks

qqq19:01:12

which is why it's so short

alandipert19:01:43

this is a thing we do a lot, so there's already lots of code to support it and things like it

alandipert19:01:14

the difference here between boot and most other tools is that the integrations of the concerns happen with the fileset value

alandipert19:01:35

ie in and of themselves, these tasks are independent of one another, and can be used in user-supplied order

qqq19:01:58

to continue beating this dead horse -- this is literally something that I can just type on the commandline, but what you have done is nicely packaged it into a single "task" right ? so I can type "boot build-war" instead of "boot web uber war :file "appwar" sift :include ... target" right?

alandipert19:01:02

it would be a little different like boot web --serve boot-war-example.core/serve war --file app.war sift --include app.war target but yeah

alandipert19:01:23

there is a different protocol for supplying args at cli than in clj

alandipert19:01:38

the othre thing that's nicer, about the build.boot, is the deps

alandipert19:01:18

boot -r src/ -d org.clojure/clojure:1.8.0 -d ring:1.5.1 web --serve boot-war-example.core/serve war --file app.war sift --include app.war target

alandipert19:01:36

ye whole thing

alandipert19:01:49

minus inferring clojure-version

qqq19:01:45

@alandipert : thanks! this clarifies alot; I'm a big fan of how "explicit" and "compositional" (as opposed to "magical") boot is compared to lein

qqq19:01:13

the boot build system is "brain dead" in the best possible way

alandipert19:01:27

it's maximally dumb

qqq19:01:47

boot.user=> (println (slurp "build.boot"))

(merge-env!
 :resource-paths #{"src"}
 :dependencies (template
                [[org.clojure/clojure ~(clojure-version)]
                 [ring "1.5.1" :exclusions [org.clojure/clojure]]]))

(task-options!
 uber {:as-jars true}
 web  {:serve 'boot-war-example.core/serve}
 war {:file "app.war"})


(deftask build-war []
  (comp
   (web)
   (uber)
   (war :file "app.war")
   (sift :include [#"app.war"] )
   (target)))

nil
boot.user=> (load-file "build.boot")
deftask boot.user/build-war was overridden
#'boot.user/build-war
boot.user=> (build-war)
#object[clojure.core$comp$fn__4495 0x441eb9d3 "[email protected]"]
boot.user=> 
I'm trying to run the build-war task directly from the repl. It does not appear to be working. What am I doing wrong How do I fix it?

seancorfield19:01:56

(boot (build-war)) I believe

seancorfield19:01:28

Tasks are higher-order functions: they return a function that boot can execute.

qqq19:01:23

@seancorfield : got it working, thanks!

qqq20:01:47

rm -rf tmp
mkdir tmp
cp config/* tmp

echo ""
echo "**********************************************"
echo "***** cleaning compiled js; building min *****"
echo "**********************************************"
echo ""
lein cljsbuild once min


echo ""
echo "*****************************************"
echo "***** clearning war; rebuilding war *****"
echo "*****************************************"
echo ""
# (cd tmp; mkdir src; (cd ../src; find . -name \*_s.clj -exec cp {} ../tmp/src); lein ring uberwar; rm -rf src)
(cd tmp; mkdir src; cp -R ../src/g src; mkdir resources; cp ../resources/cdn/index_prod.html resources/index.html; lein ring uberwar; rm -rf src)


echo ""
echo "*********************"
echo "***** uploading *****"
echo "*********************"
echo ""
(cd tmp; mkdir -p target/war;
  cd target/war;
  jar xf ../v1-0.1.0-SNAPSHOT-standalone.war;
  cp ../../appengine-web.xml WEB-INF;
  cp ../../web.xml WEB-INF;
  mkdir -p static/cdn;
  cp ../../../resources/cdn/index_prod.html static/index.html;
  cp -R ../../../resources/cdn/hw static/cdn;
  cp -R ../../../resources/cdn/prod-js static/cdn;
  cp -R ../../../resources/cdn/index_prod.html static/cdn;
  appcfg.sh update .)
^^ this is my curent build script (in bash) that uses lein to do "cljs build" and "ring uberwar" with boot, in practice, I can get rid of the bash dependency, and write all of this entirely in clojure right ?

qqq20:01:21

so I can build boot task called pack-stuff-and-deploy-on-gae ... then do (boot (pack-stuff-and-deploy-on-gae)) from my boot repl -- and everything will just work

qqq20:01:24

this is the boot way right?

alandipert20:01:46

you could, whether or not its good depends on your team situation, what you want to spend time on, etc

qqq20:01:10

whether it's a good idea to use it in the end, it's a good excuse to learn more boot 🙂

alandipert20:01:11

but in general its good i think

alandipert20:01:19

it's nice for a build to require just one tool imo

qqq20:01:20

also, at this point, I thikn I know more clojure than I know bash

qqq20:01:26

agreed, single tool = optimal

qqq20:01:52

using just one jvm / clojure is even better; I hate the delay in firing up new jvms / clojure

alandipert20:01:52

another bonus is, once you're happy with the clj you made to represent your process, you can make that a library and use it in other apps

qqq20:01:21

oh, you mean "deply-to-gae" instead o being a externla bashscript, can now be a BOOT-LIBRARY

alandipert20:01:24

yeah, like deploy to acme/standard-deploy 1.0.0

alandipert20:01:39

so now that has a bunch of tasks $FUTURE_YOU can reuse

qqq20:01:16

I'm more generous than that, it's a bunch of tasks $ALL_CLOJURIANS can use

qqq20:01:32

never thought writing build scripts could e so fun

alandipert20:01:16

it's great fun

alandipert20:01:18

well it will be, as long as programming remains fun

alandipert20:01:37

which is always longer than the amount of time configuring is fun

qqq20:01:13

Suppose CLJS depends on library REAGENT; but Clj/Server/GAE side does not depend on REAGENT. Suppose I do not want REAGENT to be in my WAR file. Does this mean I need to use 2 separate build.boot files with their own dependencies sections, or is there some way to do this in one build.boot file? The main thing is that my build-cljs task needs to use one set of dependencies, which includes REAGENT build-war task needs ot use another set of dependencies, which does NOT include REAGENT

qqq20:01:54

@alandipert : ^^ one more help? 🙂

alandipert20:01:06

kind of hinges on how critical it is that reagent isn't in your war

qqq20:01:24

it's important; unnecesary dependenceis makes GAE slow

alandipert20:01:24

if it's critical to separate, the best path is probably to have 2 separate apps, one for frontend, one for backend. i know @jumblerg prefers this

qqq20:01:28

I want my WAR to be as minimal as possible

qqq20:01:52

okay, two separate *.boot files it is; easy enough; thanks!

alandipert20:01:00

so that you can upload it faster?

qqq20:01:48

yeah, atleast in my experience, the puny 512MB machines that GAE spins up relaly doesn't like having lots of JARS around

qqq20:01:12

and on my client side, I'm about to include datascript, re-frame, specter, http://thi.ng, some sound libraries, and who knows what else

alandipert20:01:38

so - one alternative

alandipert20:01:45

is to mark your cljs dependencies as :scope "test"

alandipert20:01:58

i did that for a few deps in the war example

alandipert20:01:41

oh nvm - i thought that would hide them from uber but it didn't

alandipert20:01:06

oh wait, nvm, i was right 🙂

alandipert20:01:15

uber has an :exclude-scope option

alandipert20:01:27

i believe you can use this to trim your cljs deps from the war

alandipert20:01:43

i.e. dependencies that are in scope "test" are around at cljs compile and build time, but don't get included in the .war

alandipert20:01:40

hm, playing around, can't get it to work

qqq20:01:25

StackOverflow mentions the same words as you, but I haven't found a working example yet either.

qqq20:01:44

this is enough, I can take it from here -- thanks again for your help

alandipert20:01:29

ok so i've done some testing, inconclusive, but seems to work in the cases that matter

alandipert20:01:49

if you bring in some dep like [alandipert/hyperturbo "1.0.0" :scope "test"]

alandipert20:01:53

assume that's reagent or whatever

alandipert20:01:03

it's on the classpath for the duration of the boot run, like for your cljs build

alandipert20:01:10

but does not get picked up by uber, and does not go in the .war

alandipert20:01:34

according to (doc uber) deps in the "test" scope are not included by default

qqq20:01:57

it appears I can also specify other scopes to :exclude-scope

qqq20:01:02

so I should be able to setup a :scope "my-cljs"

qqq20:01:08

and then tell uber to :exclude-scope "my-cljs"

alandipert20:01:10

i don't think you can invent scopes

alandipert20:01:17

there's a closed set, defined by maven

alandipert20:01:23

we just overload their meanings

qqq20:01:35

good to know

qqq20:01:52

you should start a consulting service

qqq20:01:53

I would pay

alandipert20:01:30

we've thought about it

alandipert20:01:40

i think we just need to put the shingle out

mobileink21:01:58

@qqq that's what gae services are for. break your app into services, maintain and upload independently. also gae uses war dirs, not war jars, so uber is unnecessary.

michael.heuberger21:01:28

does anyone know how to dynamically require another ns inside a deftask?

michael.heuberger21:01:39

(deftask dev-run
  []
  (set-env! :source-paths #(conj % "env/dev/src"))
  (require '[abc.api-proxy.boot :refer [proxy-serve]])
  (comp
    (serve :port 1112 :handler ‘abc-ui.catch/all)
    (proxy-serve 
…

michael.heuberger21:01:32

1. adding additional source paths for dev mode only and 2. require additional stuff (proxy in this case)

michael.heuberger21:01:51

doesnt work and throws clojure.lang.ExceptionInfo: Unable to resolve symbol: proxy-serve in this context

alandipert21:01:14

(require 'abc.api-proxy.boot) ((resolve 'abc.api-proxy.boot/proxy-serve) ...) i think is the recipe you seek?

michael.heuberger21:01:47

oh, no need to use set-env! ?

michael.heuberger21:01:01

and what to place after the resolve fn? the comp block?

alandipert22:01:20

yup that's the one