Fork me on GitHub

Perhaps a silly question, but why do npm and rust make lockfiles but maven, gradle, lein, deps, etc don’t? I assume its some limitation/property of the ecosystem, I just can’t intuit what


npm is also more flexile when it comes to declaring which version to use. e.g. you have the ^ prefix to specify any version greater than. i’m not sure either as to why other strategies don’t require lockfiles at all though


> npm is also more flexile when it comes to declaring which version to use. e.g. you have the `^` prefix to specify any version greater than. Not a fan of that kind of "flexibility" I just had a deployment fail because of a breaking change between two consecutive patch versions of a library (which I could have prevented if I didn't use the caret)


i’m not a fan either, just noting the difference above seems like you didn’t have a lockfile lol

😄 1

Yeah, lockfile wasn't on version control so it was partly my fault but still I don't see why you need to specify an approximate version


Maven lets you specify version ranges and also supports RELEASE and LATEST but they are all discouraged.


right but transitive dependencies are always kinda implicitly on a version range as to what gets resolved/picked

👍 1

so it still feels like there is a benefit?


package.json,`deps.edn` , etc are contracts. They communicate to the user which versions your library has been tested against. (in applications this doesn't matter as much because end users care less about your dependencies) So using version ranges in the way ^ does means either: • "I've tested every released version under the vX major version, including future minor/patch versions" which isn't very honest or • "I trust that every minor/patch version that will come out in the future will be compatible with my code" which is naive Is there a third interpretation?


@U3JH98J4R In Clojure, for a given set of specific top-level deps, everything is fixed -- all your transitive dependency versions are fixed too (you may not be able to predict them ahead of time but they won't change). If you want to force a specific version of something that is pulled in transitively, you just put it in your deps.edn file.


Well, as long as none of the deps you pull in behave badly and actually have a range of versions specified, of course.


On ranges and such, I made this a while ago

Alex Miller (Clojure team)14:01:20

not a silly question, these are different strategies for managing versions


> :default-deps provides a set of default coordinate versions to use if no coordinate is specified. The default deps can be used across a set of shared projects to act as a dependency management system:


(from the manual). How would this work in practice? Is there a way to get clj to read from deps.edn and from another file to provide those defaults? Our monorepo has 47 sub-modules and it's a pain to keep some things synchronized. Failing that, I'm working on a tool to make global updates to deps.edn files across the monorepo.

Alex Miller (Clojure team)16:01:11

not really, this is kind of an unfinished idea

Alex Miller (Clojure team)16:01:38

I mean, you can read from ~/.clojure/deps.edn but that's probably not really a good match for this need

Alex Miller (Clojure team)16:01:02

I think most people doing this kind of thing are doing some form of programmatic rewrite

Alex Miller (Clojure team)16:01:45

another dodge if they are all shared is to locate them in one common dep that the others all depend on but I assume they vary across your modules


Right. I'm debating whether to a) walk all the deps.edn files and make updates or b) generate the deps.edn files from a template (e.g., template has dependency on org.clojure/core.async, and a master file identifies the actual coord to use).

Alex Miller (Clojure team)16:01:24

I believe I've seen people doing both. I think the benefit of a) would be having the deps.edn files there and available to use with other tooling


Right, otherwise you are either a) having to check in genrated files to Git or b) having to generate the deps.edn files all the time in tooling or CI.


@hlship You can also do my idea which no one else likes and just have a singular local dependency per external dep


{:deps {org.apache/thing {:mvn/version "x.y.z"}}}

{:deps {org.apache/other {:mvn/version "x.y.z"}}}

{:deps {libraries/other {:local/root "../../libraries/other"}}}


yes, this leads to the world’s dumbest libraries folder


and no, we don’t do this at work, we don’t have nearly enough modules to justify it


but… it does solve the version pinning problem


Perhaps polylith can also be an option, @seancorfield is probably shortly going to mention that ;-)

😄 2

I wasn't going to mention Polylith specifically but I was going to point @hlship at and say "Take a look at my blog series about our monorepo and how we've evolved our use of deps.edn over time." 😛


(we started with a repo-based "user" deps.edn, switched to generated deps.edn files, and then switched to something fairly close to how Polylith does things -- and now we're actively migrating to Polylith proper)


@hlship I tried to address shortcomings with monorepo usage a while back, in a library called Interdep, but then took a hiatus from programming. Recently got back to it and did another iteration of way it could work.  I’m still experimenting with ideal use, but here it is in case you’re looking for an example to reference We unify all subdeps into a single config and then pass that as an “-Sdeps” argument. This approach is most transparent as you can keep the deps.edn files as is and you can run sub-projects independently without extra work. @borkdude the improvements in Babashka have made this a lot easier to manage 🙂


Right now I force aliases to be namespaced as it makes them easier to merge, but I’m considering just handling merging as it’d make it less restrictive and possibly be a simpler way to run multiple aliases (as right now we’re doing this via profiles as described in docs)


Which improvements specifically? Thanks for the feedback


bb.edn and the built-in clojure command before I was running my own script and starting a clojure process myself now I can just plug this into the bb config run (clojure (interdep/enhance-args *command-line-args*) and do bb run … to start my program with custom deps and aliases

👍 1

@alexmiller Do I take this "Add check to error on invocation of multiple exec functions" to mean that :exec-fn [f1 f2] is now detected/disallowed? 🙂


Does it specifically check it is a symbol (qualified or simple)?


I guess we could add that to clj-kondo as a check, but not sure how common that mistake is made (perhaps only by early adopters from when it was supported)


I didn't even know it was possible until very recently... ¯\(ツ)

Alex Miller (Clojure team)22:01:44

I don't think it's worth adding a check for it

Alex Miller (Clojure team)22:01:57

and maybe some day it will actually be a thing