Fork me on GitHub

what does :default-deps actually mean? My understanding was you could use it to define some deps that could be overridden from e.g. ~/.clojure/deps.edn, but it doesn't seem to do that. Is it actually just meaning if no deps at all are defined in :deps then it will define some deps? The documentation is not helping my mental model so much


Default deps means any deps which don’t have a version declared will get that version


Think of it as roughly “managedDependencies” of maven or Lein


Use it by saying :deps {coord nil} in your base deps, then adding default deps with :default-deps {coord some-version} and applying via alias

🙌 1

:override-deps is how you override versions of deps -- it says "if this dependency is brought in, by anything, use this version regardless of how the dependency is declared"


and that's something you would put in your ~/.clojure/deps.edn ?


:default-deps is kind of weird. Like, you might think you could use it to provide a default version of Clojure if nothing else specifies it, but there are tooling contexts that do supply a specific version of Clojure and your default won't take effect.


I have :override-deps in my user deps.edn file so I can force a particular version of Clojure when running stuff:


That also allows me to do multi-version testing:

for v in 7 8 9 10 11; do clojure -M:test:runner:1.$v; done


(although these days I mostly run my tests via build.clj since that gives me more control over test setup and context)


I have never found :default-deps useful.


I use default deps to share and centrally manage directly-depended-on versions across modules. It’s great for this use case, but weird because deps doesn’t allow composing deps files (you have to generate them), and only lets this thing come in via an alias, and Alex said he didn’t have this in mind.


and override-deps only for fixing “bad” versions that our deps.edns don’t depend on directly


@U09R86PA4 Unless your defaulted dependency is top-level, you understand that if a more recent transitive version of your :default-depsis in the tree, it will take precedence?


(although I expect you're using :local/root deps for your modules?)


> Unless your defaulted dependency is top-level You mean unless I do :deps {lib nil}? Yes that’s exactly the intention and how we use it


to be clear, this is about a long standing back-and-forth issue we've had with setting cider-nrepl in a repo with many engineers. It's a struggle to support both people who have no idea about tooling and just want Calva to work out of the bat, and also to support people running e.g. a particular version of cider in emacs which might require a different version of nrepl. We recently switched to putting the cider-nrepl dep in a :default-deps map, but it turned out this wasn't tested properly and never worked — which made me wonder what the heck the point of them is. But it looks like you need to explicitly declare the version to be nil in your :deps map — which is a bit weird, but I guess it makes sense if it's been used historically for deps like org.clojure/clojure which will be there implicitly anyway


some specific built artifact may bring in a different dep transitively and :default-deps will have no affect, but that’s ok.


if it’s not ok (e.g. a CVE), use :override-deps


So you have it as a top-level dep and you have to use an alias to bring in the :default-deps? Where is your alias coming from if your top-level deps.edn file has the nil version?


i.e., how are you centrally managing a version via an alias across multiple top-level deps.edn files?


there’s a top-level “shared-deps.edn” which just has aliases in it, including the one with default-deps and override-deps. Each module then has a “module-deps.edn” which only has :deps and has {coord nil} for things it needs. We generate the concated deps.edn for each module (just adds the alias keys) and run each module with the required aliases


the concat is done with babashka.deps/merge-deps, which is a workalike to the tools.deps function that merges your user-deps and project deps together.


so it’s functionally like having (merge user-deps <shared-deps in the middle> project-deps), and I really wish that the cli could just do that so I don’t have to generate composed deps.edn. But we’ve strung enough makefile-foo over it and babashka makes it fast enough that it’s tolerable.


We gave up on that approach and switched to something very close to what Polylith does (and then, ultimately, to Polylith) -- based on discussions with Alex and his recommendations for a monorepo with multiple modules.


i.e., a master project deps.edn in the repo root and the modules as :local/root deps. The extra thing Polylith brought to the table was specific project deps.edn files in separate folders for the artifacts to build (and then depending on modules via :local/root deps).


that’s what we do, we just call those modules “services” (they’re applications not libraries), and they have only local-root dependencies on other modules.


and it is in one of these that we had the clojure nil problem


Then there should be no need to merge deps.edn files.


the merge is so they pick up the aliases


that have the default-deps and override-deps in them


When that discussion came up the other day, I didn't realize you were generating your deps.edn files on top of everything else... we tried that and it had horrible edge cases so we stopped doing it.


The thing that’s maybe different from what you describe is we don’t build one artifact, we build several


We build about 20 different artifacts from our monorepo.


then I’m not sure what’s different 🙂


did you alter the un-aliased :deps {…} map of in each module’s generated deps.edn?


because we don’t do that, we just require an alias. The cli literally cannot compute a classpath (blows up) without the alias


We moved away from aliases because it was often so hard to get tooling at large to respect them. Things have improved a bit but tooling still isn't very consistent.


We decided that the "complexity" of duplicating a certain number of dependencies between the :dev profile for Polylith and the various projects/*/deps.edn files was less than the complexity of trying to manage that with aliases and fighting with tooling... ¯\(ツ)