clj-kondo

onetom 2025-01-10T11:45:45.748459Z

We have (top-level) function definitions annotated with :datomic/tx metadata across our codebase, like so:

(ns some.ns)

(defn ^:datomic/tx some-tx-fn [db-val ,,,]
  ,,,)
but we keep forgetting to register them with Datomic by mentioning the var's fully qualified symbol under the :allow key, in the the resources/datomic/ion-config.edn file. Q1, Would it make sense to utilize clj-kondo to check, whether some.ns/some-tx-fn is mentioned in the ion-config.edn? Q2, What approach should I take? Do I need to define a clj-kondo hook, just so I can report a lint issue with api/reg-finding!? Q3, Where should I put the latest contents of ion-config.edn so its accessible to the linting process? (to the sci interpreter presumably, which runs hooks?)

onetom 2025-01-10T11:52:42.105549Z

@mb did i depict our problem correctly?

borkdude 2025-01-10T11:56:43.480819Z

I think what you actually want is scan your codebase for functions that has certain metadata. I think this would be better done with a script, rather than a custom linting function as you can't currently read from the file system in custom linters. You can use the clj-kondo analysis for this and enable the meta option for var-definitions: https://github.com/clj-kondo/clj-kondo/tree/master/analysis#metadata You can do this with a #babashka script or JVM script (example will follow, but brb)

🙏 1
onetom 2025-01-10T11:56:52.069699Z

I think I see the answer to Q3. The hooks.md mentions api/*reload*

onetom 2025-01-10T12:00:38.600539Z

@borkdude thanks for the direction! sounds very much like what we need. it's actually not necessary to see it during code editing that a newly tx fn is not yet registered in the ion-config.edn. it's sufficient to take care of that registration sometime before we deploy the code, so we can just run a clj-kondo analysis as a git commit hook for example.

borkdude 2025-01-10T12:00:50.224979Z

yep

borkdude 2025-01-10T12:05:19.939289Z

Here is a small example using bb:

#!/usr/bin/env bb

(require '[babashka.pods :as pods])

(pods/load-pod 'clj-kondo/clj-kondo "2024.11.14")

(require '[pod.borkdude.clj-kondo :as clj-kondo])

(println
 (->> (clj-kondo/run! {:lint ["/Users/borkdude/dev/clj-kondo/src"] :config {:analysis {:var-definitions {:meta true}}}})
      :analysis :var-definitions (keep :meta) (take 10)))
This prints the first 10 vars that have metadata at all. You can figure out the rest probably

❤️ 1
onetom 2025-01-10T13:07:42.597849Z

this looks about right:

❯ time clj-kondo --lint src/ \
  --config '{
    :skip-lint true
   
    :analysis
    {:var-definitions
     {:shallow true 
      :meta [:datomic/tx :datomic.entity/pred]}}
:output {:format :edn}}' \
  | jet -t ':analysis :var-definitions 
     (filter (comp (some-fn :datomic/tx :datomic.entity/pred) :meta))
     (map #(symbol (str (:ns %)) (str (:name %))))' \
  | wc -l
68
clj-kondo --lint src/ --config   0.73s user 0.06s system 74% cpu 1.049 total
jet -t   0.39s user 0.02s system 38% cpu 1.056 total
wc -l  0.00s user 0.00s system 0% cpu 1.055 total

🎉 1
borkdude 2025-01-10T13:08:30.732749Z

cool