Fork me on GitHub
#babashka
<
2023-09-19
>
danm07:09:57

Is it possible for babashka test files to also be .bb instead of .clj? We've got some CI automation that runs on any \.clj[cs]? files that it finds in our repo, but it expects them to be usable via our standard deps.edn, whereas the babashka test files are using bb.edn and loading not using the standard clj runtime it's all built for. I tried changing the filename and the bb test:bb command from https://blog.michielborkent.nl/babashka-test-runner.html didn't seem to pick them up any more.

pesterhazy07:09:17

Not on my laptop but check this namespace. Does it know about bb files? (:require [clojure.tools.namespace.find :as find]

borkdude07:09:54

> Is it possible for babashka test files to also be .bb instead of .clj? Yes, the search order is .bb, .clj, .cljc

borkdude07:09:26

but tools.namespace probably doesn't search for that

borkdude07:09:35

so that's why the test runner doesn't do what you want

borkdude07:09:23

another solution to this is to split out the bb tests in a separate directory and then use the test runner on that directory instead

borkdude07:09:32

or use reader conditionals to make .clj files both jvm + bb compatible (and renaming them to .cljc)

danm08:09:56

I'm not sure what you mean by the separate directory bit? They're already in a separate directory within our repo. It looks like actually I could make this work if, before invoking cognitect.test-runner.api/test, I with-redefs'd clojure.tools.namespace.file/clojure-extensions to include .bb. I wonder if that's doable within :task in bb.edn

borkdude08:09:02

What I mean that instead of putting all your tests in test/... you put your bb-specific tests in test-bb and then use :paths ["test-bb"] + --dir test-bb in the test runner

borkdude08:09:09

so use a different classpath for bb

borkdude08:09:41

oh sure, you could do the with-redefs

danm08:09:28

With our CI actions I mean it recursively scans all the directories in the repo and every time it finds a 'clojure' file (based on extension) it marks that directory as one to be acted on, and adds it to the classpath when certain actions are run. So changing the directory to test-bb but containing .clj files would just mean test-bb got added to the classpath on CI 🙂

danm08:09:15

Woop woop! 🎉 Thank you!

➜ bb test:bb

Running tests in #{"test"}

Testing securityhub.core-test

Testing securityhub.finding-test

Testing securityhub.slack-test

Testing securityhub.url-test

Ran 14 tests containing 32 assertions.
0 failures, 0 errors.

➜ mv test/securityhub/core_test.clj test/securityhub/core_test.bb

➜ bb test:bb

Running tests in #{"test"}

Testing securityhub.core-test

Testing securityhub.finding-test

Testing securityhub.slack-test

Testing securityhub.url-test

Ran 14 tests containing 32 assertions.
0 failures, 0 errors.

danm08:09:29

{test:bb {:extra-paths ["test"]
                  :extra-deps {io.github.cognitect-labs/test-runner {:git/tag "v0.5.1" :git/sha "dfb30dd"}
                               org.clojure/tools.namespace {:mvn/version "1.3.0"}}
                  :requires ([clojure.tools.namespace.file :as file])
                  :task (with-redefs [file/clojure-extensions (list ".bb" ".clj" ".cljc")]
                          (exec 'cognitect.test-runner.api/test))
                  :exec-args {:dirs ["test"]}
                  :org.babashka/cli {:coerce {:nses [:symbol]
                                              :vars [:symbol]}}}}

👍 1
eval-on-point11:09:17

Sorry if this is covered somewhere, but is there a simple way to have println output to the same stream as babashka.process/shell when I am connecting to the babashka nrepl via Cider? Currently shell outputs to my terminal (since :inherit is the default :out stream), but println goes to *out* . Ideally, I would like to be able to do this via a Cider or babashka configuration rather than editing my babashka program, since this is only an issue at developement time that I want to apply to all babashka sessions in the future

borkdude11:09:50

Perhaps this is possible by changing babashka.process/defaults and setting :out to *out*

eval-on-point11:09:06

Yeah that would definitely do it. I think I will try to figure out how to do that via command line args to babashka so that I do not have to edit the script. Will report back if I figure it out. Thanks!

borkdude11:09:40

first try if this helps at all, before figuring out how to do it via the command line

borkdude11:09:57

that might save you some time in case it doesn't work ;)

eval-on-point12:09:31

Thanks for helping me think it through. I think what I really want is for :out :inherit to stream to my Cider REPL. I think this would probably require me to start the bb process from inside Emacs, which seems like too heavy of a lift for such a small issue

eval-on-point12:09:17

Looks like a possible route would be to use cider-jack-in with bb nrepl server and (setq cider-redirect-server-output-to-repl t) , but some additional logic from the cider-nrepl middleware would have to be added to the babashka nrepl-server

borkdude12:09:29

you can first try it with babashka.process on the JVM and regular nrepl middleware perhaps

stopa21:09:04

Hey team, noob question:

(defn set-version! [path v]
  (let [file (io/file path)
        json (json/parse-string (slurp file))
        updated (assoc json "version" v)
        saved (spit file (json/generate-string updated))]))
Here, I am trying to update some package.json files "version" properties. If I spit back updated though, it will reorder all the keys in the package.json file. Is there a way I can have it be a bit smarter, so I "only" update the part of the json I want?

lukasz21:09:09

This is giving me flashbacks :-) I did this with jq and sed in the past: • get current version by parsing json • search and replace the version string with new value (more or less)

lukasz21:09:51

Although I think since then jq gained the ability to update values while preserving order I think think_beret

borkdude21:09:49

you can parse this as yaml, yaml uses ordered collections so it might preserve stuff better

borkdude21:09:17

$ bb -e '(-> (clj-yaml.core/parse-string "{a: 1, b: 2}") (assoc :a 2) (clj-yaml.core/generate-string))'
"{a: 2, b: 2}\n"

borkdude21:09:41

With more than 8 kvs:

bb -e '(-> (cheshire.core/parse-string "{\"a\": 1, \"b\": 2, \"c\": 2, \"d\": 2, \"e\": 2, \"f\": 2, \"g\": 2, \"i\": 2}") (assoc :a 2) (cheshire.core/generate-string))'
"{\"d\":2,\"f\":2,\"e\":2,\"a\":1,\"i\":2,\"b\":2,\"g\":2,\"c\":2,\"a\":2}"
$ bb -e '(-> (clj-yaml.core/parse-string "{\"a\": 1, \"b\": 2, \"c\": 2, \"d\": 2, \"e\": 2, \"f\": 2, \"g\": 2, \"i\": 2}") (assoc :a 2) (clj-yaml.core/generate-string))'
"{a: 2, b: 2, c: 2, d: 2, e: 2, f: 2, g: 2, i: 2}\n"

borkdude21:09:42

if you replace the last call to cheshire.core/generate-string then it will also output valid json but still in the right order

borkdude21:09:12

but you can also just use npm version <new-version>:

borkdude@MBP2019 /tmp/proj $ npm version v0.1.2
v0.1.2
borkdude@MBP2019 /tmp/proj $ cat package.json
{
  "version": "0.1.2"
}
borkdude@MBP2019 /tmp/proj $ npm version v0.1.3
v0.1.3
borkdude@MBP2019 /tmp/proj $ cat package.json
{
  "version": "0.1.3"
}

1
borkdude21:09:43

you can do this from bb with: (babashka.process/shell "npm version" version)

stopa01:09:43

Thank you team!!

pesterhazy08:09:12

+1 on clj-yaml – it uses an ordered-map in the background to achieve this

pesterhazy08:09:04

Just briefly looked at it, seems like npm version simply deserializes and reserializes package.json

pesterhazy08:09:27

Which means key order is preserved (because unlike Clojure maps, JS objects preserve insertion order)

pesterhazy08:09:07

Indentation, however, is removed

pesterhazy08:09:22

Comments would be removed too, but fortunately JSON has no comments 🙂