Fork me on GitHub
#babashka
<
2021-04-26
>
borkdude09:04:36

@karol.wojcik Perhaps I will remove the logging stuff which I pretty much butchered together and will just expose *task-name*. So you can do:

(println ">>>" *task-name*)
in your tasks, if you want to print the task name

pithyless10:04:03

Can we use some kind of middleware/interceptor pattern for tasks (similar to :init)? That way we could globally define and customize things like printing task names, logging responses, etc.

borkdude10:04:54

hmm, interesting!

borkdude10:04:25

:pre-task (fn [...] ...) :post-task (fn [...] ...) ?

borkdude10:04:48

I guess if you want to save some state, you can accumulate it in some atom you define in :init

pithyless10:04:20

:interceptors [{:name "optional"
                :pre-task (fn [..] ...)
                :post-task (fn [..] ...)}]

👍 2
pithyless10:04:56

^ perhaps something like that, and you can probably ship with a couple default interceptors built-in

pithyless10:04:20

so the previous discussions would boil down to:

:interceptors [log-task-names, log-task-outputs]

Karol Wójcik10:04:37

Please allow binding interceptors from task script as well.

borkdude10:04:48

What do you mean exactly?

Karol Wójcik10:04:52

I want to add interceptors from script not via bb.edn:

(ns holy-lambda.tasks
  "This namespace contains tasks!"
  (:require
   [clojure.string :as s]
   [clojure.pprint :as pprint]
   [clojure.java.shell :as csh]
   [clojure.edn :as edn]
   [babashka.tasks :as tasks]
   [babashka.deps :as deps]
   [babashka.fs :as fs]
   [babashka.curl :as curl]
   [babashka.process :as p]
   [ :as io]))

(tasks/add-interceptors [{:name "Wrap task"
                          :enter (fn [task-name] (println task-name))
                          :leave (fn [task-name] (println task-name))}])

borkdude10:04:14

What is the reason you want this in addition to declaring them in bb.edn?

borkdude10:04:31

Hmm, we could add the value of each task execution into the middleware map as it executes

borkdude10:04:42

and then each middleware fn gets to see the middleware map

borkdude10:04:50

and can add/remove to it

borkdude10:04:25

> Hmm, we could add the value of each task execution into the middleware map as it executes hmm, but this is already supported by :depends as well, but perhaps it doesn't hurt to have some more flexibility

borkdude10:04:26

baz {:enter (fn [m1] (assoc m :foobar 2)) :task 66 :leave (fn [m2] ...)}
where m1 = {foo 1 bar 2 :task-name baz} and m2 = {foo 1 bar 2 baz 66 :foobar 2 :task-name baz}

Karol Wójcik11:04:45

Interceptors is an implementation detail for me. I don't want the user to change them.

borkdude11:04:31

What is "the user"

Karol Wójcik11:04:08

The one who interacts with holy-lambda via executing provided bb tasks.

borkdude11:04:41

Is holy lambda generating a template project for the user with a bb.edn in it?

borkdude11:04:55

or how does it work?

Karol Wójcik11:04:07

When I'll be done with tasks I will just reference to holy-lambda-babashka-tasks/bb.edn from template. Running

lein new holy-lambda <some-project>
will scaffold a project with bb.edn.
bb version
will check for new version of tasks if found a new version then will ask the user to update the sha in bb.edn https://github.com/FieryCod/holy-lambda/blob/master/modules/holy-lambda-babashka-tasks/bb.edn

borkdude11:04:35

ok but note that a user of the template is as much a "power" user of the bb.edn as you are, a template is only a starting point of a project after which you make your own modifications

borkdude11:04:15

so whatever changes they want to make to the bb.edn, that should be allowed

Karol Wójcik11:04:26

Actually that's a good point

borkdude11:04:32

and btw, version is also a subcommand of babashka which you are overriding

borkdude11:04:42

but that shouldn't be a problem

Karol Wójcik11:04:52

I will use tasks:version then

borkdude11:04:25

Instead of calling it interceptors maybe a more basic "hook" system works better (also in combination with parallel tasks). You can define a global :enter and :leave hook (which gets to mutate the global context map) and you can override those per task. If you want to call the global hook, just call it manually in the override.

borkdude11:04:59

This way you don't get any weird API edge cases with interceptor ordering/insertion/appending.

borkdude11:04:36

Pretty much the same as (sync) Ring but two hooks, one before and one after

borkdude11:04:17

or can we get away with just one?

borkdude11:04:50

I think it's more flexible to have one before and one after hook probably

borkdude11:04:17

possibly you can also decide to abort/skip the task in the :enter hook based on some condition

pithyless11:04:24

yeah, even logic like should a "failing" task continue quietly or Sys/exit could be customized by a :leave hook

borkdude14:04:44

Should the :enter hook be executed before or after dependencies... :thinking_face:

borkdude21:04:51

I think I'll keep it more basic, in the same fashion :tasks are just expressions:

Re-considering, I think this is all that's needed to support logging of task names:

add *task-name* dynamic var
global :enter (println :> *task-name*)
global :leave (println :< *task-name*)
able to replace :enter and :leave on the task level
This is all that's needed, even to support some kind of middleware pattern, since you can define an atom in :init where :enter and :leave can mutate something to.

sh5411:04:01

Is there a built in way to stream out a processes output whilst the process is running? Right now I am just doing it myself which is fine. Just checking if I was missing out on some included batteries?

(defn attach-out-printer
  [proc]
  (thread
    (with-open [rdr ( (:out proc))]
      (let [lines (line-seq rdr)]
        (doseq [line lines]
          (println line)))))
  proc)

(-> (process ["./gradlew" "jvmFatJar"] {:dir kgpu-dir})
        (attach-out-printer))

borkdude11:04:45

@slack1003 {:out :inherit :err :inherit :in :inherit} or {:inherit true} for short

sh5411:04:58

nice! i’ll try that

sh5411:04:23

ah missed that. just started using your lib

sh5411:04:34

yup that works great

sh5412:04:25

in the process of converting the few little helper build scripts in my project over to your tasks system. Very smooth sailing so far!

borkdude12:04:35

@slack1003 cool. The tasks system also has a shell function which you can use like:

(shell {:dir kgpu-dir} "./gradlew jvmFatJar")
and it will do the same as above with :inherit true set by default

sh5412:04:37

alright. good to know. right now tasks has just been calling my prexisting bb scripts but I guess I may just do some shell stuff directly

borkdude12:04:23

both approaches are totally fine. in bb 0.3.6 I just added a new :continue option so shell won't automatically exit with a non-zero exit code

sh5412:04:58

that will be a nice addition. though all my stuff so far is happy to bail on non-zeroes

borkdude12:04:48

yeah, that's the default in shell

dangercoder12:04:21

is cheshire.factory included in babashka.json? I have a need of customizing the underlying object-mapper object. This is kind of nice in e.g. jsonista since you can pass it your own object-mapper.

2
dangercoder12:04:44

the answer is no

borkdude12:04:00

indeed. I'm not planning to since I'm not certain if cheshire is the right json tool in 2021 now that jsonista and clojure.data.json are also gaining popularity

borkdude12:04:45

so I'd like to keep the surface area somewhat minimal so it might be easier to port to some other solution in the future

borkdude12:04:51

could you convince me of the usefulness of providing your own object-mapper? examples?

dangercoder12:04:00

Options when parsing json. Right now I'm getting: ; clojure.lang.ExceptionInfo: [line 1, col 51] Unsupported escape character: \U. This would not be a problem if I configure the underlying object-mapper. e.g with jsonista:

(def object-mapper
  (-> jsonista/keyword-keys-object-mapper
      (.configure (.mappedFeature JsonReadFeature/ALLOW_UNESCAPED_CONTROL_CHARS) true)))

dangercoder12:04:56

so now, when using jsonista I can do: (jsonista/read-value json-string my-object-mapper)

dangercoder12:04:22

so basically this blocks me from using babashka from our ci-pipeline, but im going to figure out if I can use jsonista some way.

borkdude12:04:44

you can't currently use jsonista in babashka. Is there a way to fix the json first with str/replace?

dangercoder12:04:16

Gonna see, the json we receive is malformed from a system which we do not control. This option is kind of hacky indeed 🙂, I'll check it out. We still use BB for other parts of our CI and it's a pleasure to work with!

dangercoder12:04:06

its basically a nested json structure containing a json string as a value of a key which we do not want to parse directly.

borkdude12:04:17

Perhaps you can use a tool like jq to fix the JSON (if that tool supports it...)

borkdude12:04:40

Can you give a small example of such JSON?

Karol Wójcik13:04:42

How can I change in docker where .deps.clj/ClojureTools are downloaded? Here is what I tried:

ENV _JAVA_OPTIONS=-Duser.home=/project/.holy-lambda/
ENV XDG_CACHE_HOME=/project/.holy-lambda/
ENV XDG_CONFIG_HOME=/project/.holy-lambda/
ENV CLJ_CACHE=/project/.holy-lambda/
ENV CLOJURE_TOOLS_CP=/project/.holy-lambda/
ENV HOME=/project/.holy-lambda/

RUN curl  | bash
RUN bash -c "cd project/.holy-lambda && deps -P"
But it still downloads to /root/.deps.clj

Karol Wójcik13:04:02

CLOJURE_TOOLS_DIR is the thing! 🙂

borkdude14:04:48

What is CLOJURE_TOOLS_CP ?

Karol Wójcik14:04:17

Before I started reading deps.clj source code I tried my luck with this env var 😄

Karol Wójcik14:04:54

Have you ever seen babashka load/pod to write to '?' folder?

borkdude14:04:36

This environment variable is also documented in the README

Karol Wójcik14:04:20

Ok. It's really weird. Here is repro: https://github.com/FieryCod/holy-lambda/commit/22e18f5f434cfff484db5dd019a541ac04705062 git clone [email protected]:FieryCod/holy-lambda.git && make build-docker && cd modules/holy-lambda-babashka-tasks && bb stack:sync After command finishes you will see '?' folder 😮

borkdude14:04:01

could it be related about the order of these commands?

RUN mkdir -p /.babashka
RUN chmod -R 777 /clojure
RUN chmod -R 777 /.m2
RUN chmod -R 777 /.babashka

WORKDIR /project

borkdude14:04:09

shouldn't WORKDIR go before mkdir?

borkdude14:04:36

I'm just guessing, I don't know your project well enough

Karol Wójcik14:04:42

Nope. It's something with resolver. I got folder .holy-lambda/.babashka/pods/repository/org.babashka/aws/0.0.5/, but bin is downloaded to '?' ?/.babashka/pods/repository/org.babashka/aws/0.0.5/

borkdude14:04:53

$ bb stack:sync
----- Error --------------------------------------------------------------------
Type:     java.lang.Exception
Message:  File does not exist: stack:sync

Karol Wójcik14:04:37

In which folder are you?

borkdude14:04:23

> After command finishes you will see '?' folder how do I see this folder?

borkdude14:04:33

oh yes, I see it

👍 2
Karol Wójcik14:04:52

Uff. It's good that I'm not crazy 😄

borkdude14:04:41

I don't have time to debug your program, so can you make a small repro?

borkdude14:04:03

Do you have a more minimal one? There is a lot happening in this Dockerfile

borkdude14:04:11

Oh I see you have stripped it already

Karol Wójcik14:04:17

It's stripped.

Karol Wójcik14:04:29

I can use alpine if you want me to to make it even more minimal

Karol Wójcik14:04:50

But I guess you have graalvm-ce in cache so build should not take long

borkdude14:04:25

I don't use docker locally for graalvm, but I'm going to try. I do see the question mark dir, but how do I know this is not an issue with your docker config vs pods?

Karol Wójcik15:04:16

😄 I'm already using the same strategy for mountig .aws directory no question mark there

borkdude15:04:27

FWIW when I make a .babashka directory inside your repo, then I don't get the question mark dir

Karol Wójcik15:04:08

Hmm isn't it proof that it's something wrong with babashka resolver then?

borkdude15:04:35

I don't say there isn't but right now I'm debugging your docker issues while I have another job to do, so I'd say this is not a clear repro yet

Karol Wójcik15:04:44

Sure. I fixed the repro. It should be very minimal right now. You can spot '?' in error:

----- Context ------------------------------------------------------------------
 7: 
 8: (def PODS {'org.babashka/aws "0.0.5"})
 9: 
10: (doseq [[s v] PODS]
11:   (pods/load-pod s v))
      ^--- ?/.babashka/pods/repository/org.babashka/aws/0.0.5/manifest.edn (No such file or directory)

----- Locals -------------------------------------------------------------------
seq_2:   ([org.babashka/aws "0.0.5"])
chunk_3: nil
count_4: 0
i_5:     0
vec__9:  [org.babashka/aws "0.0.5"]
s:       org.babashka/aws
v:       "0.0.5"

----- Stack trace --------------------------------------------------------------
user - /usr/bin/download_pods:11:3

borkdude15:04:53

@karol.wojcik When I print in the script:

(prn (or
            (System/getenv "XDG_CACHE_HOME")
            (System/getProperty "user.home")))
I see "?".

Karol Wójcik15:04:16

When you run make you will see "?"

borkdude15:04:19

yes. it seems your XDG_CACHE_HOME env variable isn't properly set in the script. so it picks the value of user.home which is a question mark.

borkdude15:04:49

so it turns out I have been debugging your Docker issues instead of pods. :/

Karol Wójcik15:04:51

Hmm.. With this it still outputs question mark:

FROM 
MAINTAINER Karol Wójcik <Karol Wójcik>

WORKDIR /

RUN microdnf install wget

RUN mkdir -p /project
ENV _JAVA_OPTIONS=-Duser.home=/project
ENV XDG_CACHE_HOME=/project
ENV XDG_CONFIG_HOME=/project
ENV CLJ_CACHE=/project
ENV CLOJURE_TOOLS_DIR=/project
ENV HOME=/project
ARG BABASHKA_VERSION=0.3.6

RUN wget -c  -O - | tar -xz
RUN chmod +x bb
RUN mv bb /bin/bb

COPY download_pods .
RUN chmod +x download_pods
RUN mv download_pods /bin/download_pods

borkdude15:04:59

I think I have provided you with enough debugging now. I won't look at this anymore unless you can provide a repro without Docker, etc.

borkdude15:04:20

I don't want to sound like an asshole, but I what I mean is: this is a contextual problem between your Docker setup and bb. You can do more diagnosis before you poke me about it. E.g. bash into the container and inspect:

bash-4.4$ bb
Babashka v0.3.6 REPL.
Use :repl/quit or :repl/exit to quit the REPL.
Clojure rocks, Bash reaches.

user=> (System/getProperty "user.home")
"?"
user=> (System/getenv "XDG_CACHE_HOME")
nil

Karol Wójcik15:04:39

My first repro lacked one env variable which is: XDG_DATA_HOME

Karol Wójcik15:04:01

It sounded like you being asshole, but no worries I deserved it 😄

Karol Wójcik15:04:59

I should have studied resolver code more. I did not spot XDG_DATA_HOME I'm really sorry!

borkdude15:04:34

no worries ;)

Karol Wójcik16:04:35

I'm deeply sorry. I will spend more time on reading babashka code! 🙂 No more pokes today 🙂 Have a great day!

borkdude16:04:08

I don't mind the pokes, I think you're making a very interesting project. It's just that in case the bugs aren't directly related to bb a more clear cut repro could be made. Feel free to poke me anytime after you've done your part of the research, so it will save me time.

borkdude16:04:17

and if I think you should make it more clear cut, I will just say so (hopefully without sounding like an asshole :-D)

borkdude16:04:10

I also enjoy your feedback on the tasks, so thanks for that

viesti18:04:45

at least if you run as a user, which doesn't have a /etc/passwdentry, then you get ? for (System/getProperty "user.home") (just came to my mind from some previous docker adventure)

Karol Wójcik18:04:43

Huh. I didn't know that. Thanks @U06QSF3BK

borkdude18:04:21

You can force this property in bb by doing bb -Duser.home=/foobar

❤️ 3
👍 2
borkdude11:04:57

@karol.wojcik Btw, have you tested if the aws pod works in your docker container / lambda? If it's a musl based container (alpine, busybox) often pods don't work (because they depend on libc++) and have to be compiled statically, so that would be good to test.

borkdude11:04:06

org.babashka/aws "0.0.5"

Karol Wójcik12:04:07

I will not run babashka/pod on my docker image. 😄

borkdude12:04:38

but will it work in your target environment?

borkdude12:04:44

that is the question right

borkdude12:04:59

oh I guess it's the same for bb itself, if the normal bb works then the pod will also work

👍 3
Karol Wójcik15:04:09

Can I set a system property for clojure command as well? Don't see anything such option

borkdude15:04:41

@karol.wojcik How are you invoking Clojure?

borkdude15:04:53

without bb that is, right?

borkdude15:04:16

clojure -J-Duser.home=/foo

Karol Wójcik15:04:45

May I set it for deps.clj which babashka uses as well?

borkdude15:04:08

> without bb that is, right? > yes ?

borkdude15:04:11

so are you or are you not using bb to invoke clojure?

borkdude15:04:21

if not, where does deps.clj come in?

Karol Wójcik15:04:05

Ok. You're right. I think bb tasks needs deps.clj since I'm using a :deps keyword in bb.edn. To conclude I use both.

borkdude15:04:06

bb.edn doesn't forward any Java properties to its call to deps.clj

borkdude15:04:04

Maybe we should support this, but currently it doesn't

borkdude15:04:37

is this about setting the local .m2 folder?

borkdude15:04:54

you can put :mvn/local-repo "/tmp/.m3" in your bb.edn

borkdude15:04:33

it's a bit of a workaround probably

Karol Wójcik15:04:55

It's a little bit complicated, but what I want to achieve is to run clojure -P in docker container and sync it with .holy-lambda directory on host. Now I cannot set user.home for Clojure. I just tried what you've sent and user.home is not set.

Karol Wójcik15:04:32

With _JAVA_OPTIONS it kinda worked, but it prints a low of "Picked _JAVA_OPTIONS etc.

borkdude15:04:22

> but it prints a low of "Picked JAVAOPTIONS etc. I have no idea what this means, sorry =)

borkdude15:04:34

what is _JAVA_OPTIONS even?

Karol Wójcik15:04:29

Hmm. Ok it seems that I messed something with my docker again 😄

clojure -J-Duser.home=/foo -e "(println (System/getProperty \"user.home\"))"
You were right. It works.

Karol Wójcik15:04:51

@borkdude You're some sort of wizard. :mvn/local-repo works like a charm! Thank you so much! You rock man!

borkdude15:04:44

cool. Perhaps bb should have a separate argument to pass through to deps.clj.

bb --deps-args '-J-Duser.home=/foo'
or so

Karol Wójcik15:04:43

Yep. It would be useful

kokada21:04:03

Hi I am trying to use babashka.process to run a subprocess, but I don't want to capture its stdin/stdout/stderr (like subprocess.run from Python by default). Is there anyway to do this :thinking_face: ? I did not found anything in the documentation.

borkdude21:04:25

if you didn't find that in the documentation, then the docs need improving

kokada21:04:27

Huh... Did try this but it isn't printing anything on REPL

kokada21:04:30

Ah, of course

kokada21:04:39

It will not print anything on REPL 😛 (since it is not redirecting the output)

kokada21:04:36

I did find the :inherit option, but it wasn't really clear what it does by the explanation But looking at the examples it seems ok

kokada21:04:27

It is working fine, thanks @borkdude

🎉 2
kokada21:04:13

Have to say, porting some internal tools from my company from Bash/Python to Babashka

kokada21:04:15

It is awesome!

🎉 7
kokada21:04:18

Is there any logging library available in babashka :thinking_face: ?

borkdude21:04:46

@thiagokokada At the moment, no. But here is a tiny useful snippet perhaps: https://gist.github.com/borkdude/c97da85da67c7bcc5671765aef5a89ad

🙌 2
kokada22:04:29

It is printing the correct line but it always print the namespace user

borkdude22:04:16

Weird, the gist still seems to work for me where it prints the ns bar

kokada22:04:13

I am using the -m flag

kokada22:04:26

Since it is a full Clojure project (with src, etc)

kokada22:04:35

Maybe because of this :thinking_face:?

(ns user (:require [foo.core])) (apply foo.core/-main *command-line-args*)

kokada22:04:53

I was trying to create a new project to demonstrate, but this got to my attention

kokada22:04:00

(It is an exception btw)

borkdude22:04:07

Can you try this instead?

(defmacro log [& msgs]
  (let [m (meta &form)
        file *file*]
    `(binding [*out* *err*] ;; or bind to (io/writer log-file)
       (println (str ~file ":"
                     ~(:line m) ":"
                     ~(:column m))
                ~@msgs))))

borkdude22:04:39

pulling *ns* outside of the macro body might also work

kokada22:04:07

Yep, the one with *file* works

kokada22:04:37

BTW, if you want to reproduce it

kokada22:04:45

Run bb -m foo.core

kokada22:04:26

But this alternative with *file* seems even more useful to me

borkdude22:04:33

ok, you like file better than ns?

(ns logger)

(defmacro log [& msgs]
  (let [m (meta &form)
        ns *ns*]
    `(binding [*out* *err*] ;; or bind to (io/writer log-file)
       (println (str ~ns ":"
                     ~(:line m) ":"
                     ~(:column m))
                ~@msgs))))
this one also works, but let's go with the *file* one

kokada22:04:17

Yeah, now that I think about it maybe ns is better (the printed line is smaller)

kokada22:04:31

Don't know yet, I will do a experiment here

kokada22:04:35

But thanks anyway

borkdude22:04:07

ok, adapted the gist

kokada23:04:40

From my search I don't think there is a way, but asking anyway (since I didn't found anything for neither Clojure nor Java) Is there anyway to set an environment variable from Babashka?

👀 6
wilkerlucio02:04:06

if you mean to add variables when calling shell, you can use:

(shell {:extra-env {"SOME" "VAR"}} "your command")

kokada02:04:36

No, in this case I really need to overwrite the environment variables while the script is running

kokada02:04:49

Like doing a export ENV on shell

kokada02:04:25

For now my workaround is to use the #_(<shell code here>) trick described on Babashka's book (https://book.babashka.org/#_running_a_script) to edit the environment variables, but this is ugly

kokada02:04:32

Specially because I can't define a shell function, since this would cause an error because Clojure will try to interpret anything inside {} as a map (and fail to parse it

kokada02:04:54

BTW, it is also possible to change an environment variable in Python I found it curious that even the Java solutions involved doing some magic since it seems that Java itself doesn't have a method for it

borkdude07:04:47

AFAIK you cannot change env vars in a Java runtime