a better approach would be to create an alias in the project deps.edn
: https://github.com/seancorfield/dot-clojure/blob/develop/deps.edn#L66
i'm a cursive user myself and this is how i start a socket repl server in the terminal ( clojure -O:socket
) and connect cursive (a socket repl client) to it by creating a remote socket repl run configuration in intellij idea.
I can set up my deps.edn at the root so that it includes a "module" (that has its own deps-edn) like this:
:aliases {:dev {:extra-deps {env/dev {:local/root "environments/dev"}}}
:test {:main-opts ["-m" "polylith.clj.core.cli.poly" "test"]}}
Then I can run:
clj -A:test:dev
...and it will run my tests (that is what the 'test' alias does for me).
But the deps.edn under environments/dev contains its own aliases with some :extra-paths that I want to include also. Is that possible? I imagine that I need to do something like this (which doesn't work):
clj -A:test:dev:dev/local-alias
...where local-alias is defined as an alias in environments/dev/deps.edn:
:aliases {:local-alias {:extra-paths ["../../components/help/src"]}
Okay, but here I suggest to use existing aliases that lives in environments/dev/deps.edn, that we "import" from deps.edn at the root. Then we don't "mess up things from the outside" just selecting aliases within that "imported" deps.edn. If I "cd environents/dev" first, then I have access to all those aliases which have the purpose to add :extra-paths which I need. But here I have several "sub modules" (not just the one in this example) and wants to do the same from the root deps.edn without having to manually merge all those deps.edn files into one huge deps.edn at the root.
As I said @tengstrand "That would be kind of dangerous".
:local/root
isn't special -- it's just another way to identify a dependency. You're asking for dependencies that include deps.edn
to have their aliases combined with the current project. That's not a practical way to deal with reproducibility in project builds.
Then I guess I need to solve it with code generation or create my own REPL or similar.
What we do at work, with our 100k+ line monorepo containing 30+ subprojects, is that we have a special subproject (called versions
) that contains the "master" deps.edn
that has all the aliases needed by all projects, including :defaults
which brings in all the :override-deps
to pin versions etc, and then all the other subprojects really just have :deps
and an alias for :test-deps
to add anything needed for testing that subproject (`versions/deps.edn` has a :test
alias for all the common testing infrastructure). Then we use CLJ_CONFIG=../versions clojure -...aliases
in each subproject.
CLJ_CONFIG
lets you treat a specific folder as if it contains your user-level deps.edn
(and so any actual ~/.clojure/deps.edn
file is ignored -- which is good: the monorepo then control all dependencies and aliases!)
Thanks for the information, can be very useful!
There's no way to prevent clj
from reading deps.edn
in the current directory, is there?
@p-himik don't think so.
Thanks. That's seems a bit inconvenient because if I want to run some tool with -Sdeps
(like Capsule in my particular case) within my project, I cannot really do it without mixing two different classpaths.
it's fairly annoying, I've had scripts that temporarily move deps.edn out of the way because of this...
deps.clj, an unofficial re-implementation of the clj script does have an option to choose a different deps.edn file than the one in the current directory
I think setting :paths
in aliases to replace source path from deps.edn is as close as it gets to what you want
and :deps
it's also possible to remove deps from the classpath in an alias: https://github.com/borkdude/babashka/issues/152
see https://clojure.org/reference/deps_and_cli#_aliases (“-A” section)
But then I'd have to restructure my whole deps.edn
just to make some thirdparty tool happy. That's not good.
not sure I’m following, can you put that third-party tool as a user-level alias?
you can also manually construct the classpath (using a script) and pass it to -Scp
that way you don’t touch your project’s deps.edn
at all
The tool itself - yes. The thing is, it must be run in the presence of deps.edn
. But it would be best to not let clj
(and I run the tool using clj
) also interpret deps.edn
.
The tool itself is used via -Sdeps
, so it's not in the deps.edn
.
Oh, it's now possible to use :deps
in aliases. There's hope!
That overrides the base deps?
Yep, seems like it.
So basically I should be able to mimic an empty deps.edn
. Will experiment later today.
note that you will still have clojure and spec on the cp by default
Hmm, right. But that should've really interfere with tools that are already meant to be run with clj
.
I also use deps.edn for babashka projects, the extra deps don't hurt, but they can make searching the classpath a tad slower (like a few ms maybe)
In my case, they don't anything really bad as well, but I really want to get rid of those slf4j warnings.
yes, using :deps / :paths in an alias is what we call "tooling" and will replace the project :deps/:paths (for the purpose of using a tool that shouldn't use the project classpath)
until yesterday, you could only use those via -A, but as of the latest dev release yesterday, tooling -T is now a thing
Awesome, thanks!
more to come on that and other changes in latest, just been kind of busy with ... other things :)
Hi, I am getting FileAlreadyExistsException while trying to build an uberjar
Here is my deps.edn
file
{:paths ["src" "resources"]
:deps {io.appium/java-client {:mvn/version "7.3.0"}
org.clojure/data.xml {:mvn/version "0.0.8"}
metosin/reitit-ring {:mvn/version "0.5.1"}
metosin/reitit-middleware {:mvn/version "0.5.1"}
metosin/reitit-spec {:mvn/version "0.5.1"}
mount {:mvn/version "0.1.16"}
ring/ring-jetty-adapter {:mvn/version "1.7.1"}
org.slf4j/slf4j-simple {:mvn/version "1.7.30"}}
:aliases {:dev {:extra-paths ["dev"]
:extra-deps {org.clojure/tools.namespace {:mvn/version "1.0.0"}}}
:uberjar {:extra-deps {seancorfield/depstar {:mvn/version "1.0.94"}}
:main-opts ["-m" "hf.depstar.uberjar"]}}}
Here is the command that I am running clj -A:uberjar my-app.jar
Building uber jar: my-app.jar
Execution error (FileAlreadyExistsException) at com.sun.nio.zipfs.ZipFileSystem/createDirectory (ZipFileSystem.java:422).
META-INF/versions/9/
Am I missing anything obvious here?
What are folks using to store / set their project's version number so it makes it into the generated pom.xml
(in an automated way; think CD pipeline, not hand-editing the pom.xml
)?
I'm treating the pom.xml
as the "system of record" for the version number and deriving it elsewhere from the POM file.
(and that's the workflow that I use for all my deps.edn
-based projects that get deployed to clojars -- note that Contrib libs such as core.cache, core.memoize, tools.cli that I maintain already follow this workflow with "Maven Release" process in CI editing the pom.xml
to change the version number explicitly based on the version you enter in that Jenkins form)
@seancorfield OK, thanks. What tools do you use to read / bump it in the POM file? Curious if you have anything resembling the lein release
workflow going there.
there are maven plugins for that although it's all pretty tedious
the mvn release / deploy infrastructure does a lot for you but you have to buy pretty far into it all the way for it to be worth doing
(but it's a lot less fragile than the lein release stuff)
Thanks Alex. lein release
can indeed be fragile. 🙂
the idea to put the version inside a file was probably bad from the beginning
@cap10morgan For my clojars-deployed stuff, I just update it as part of my general release process where I'm updating the README and the CHANGELOG and I update both the <version>
and the <tag>
fields in the pom.xml
file all at the same time.
(so I grep for <old-version>|<new-version>
so I can see all the places that refer to the current release and what will be the next one, and then I can visually verify that all references get changed)
In most of my libs, that includes several places in the README and usually in the documentation files as well that refer to installation/getting started and when new features were introduced.
I've automated that step on some libs :)
I still have artisanal documentation 🙂
hey @cap10morgan, we're treating git tags as the source of truth for versions. When we deploy, the version in the generated pom.xml is made to be in sync with "git describe". Since the pom.xml is only ever needed for the deploy action, the pom.xml doesn't actually have to be checked in.
Note that for http://clojars.org and also for http://cljdoc.org there's an expectation that pom.xml
contains a lot more than just the dependencies and the version, so having it as a "loose" file outside git would be... ill-advised if the generation process doesn't include all that information (which lein
does put there, but clojure -Spom
does not, so I'm talking about deps.edn
projects -- note that clj -A:new
would generate initial pom.xml
files with all the appropriate fields for http://clojars.org and http://cljdoc.org)
Ya, our process is still using lein
for the pom.xml generation. That's super interesting @seancorfield - I was probably going to hit this in the near term as I had been planning on migrating to use clojure -Spom
. Thanks!
clojure -Spom
is fine for updating <dependencies>
in an existing pom.xml
file but it only generates a very bare-bones version if no file exists. That's why I added a full-featured pom.xml
to the templates that clj-new
uses for app
, lib
, and template
.
When git describe is the source of truth for version maybe we'd compose clojure -Spom
to update the dependencies, with a git-describe->pom-version
, and keep a clj-new generated pom.xml checked in.
It sounds like a checked in pom.xml might currently be the best place to version the extra metadata that clj-new adds.
clj-new
creates a baseline pom.xml
. It never updates it after that.
clojure -Spom
updates an existing pom.xml
with the latest dependencies (from deps.edn
) so as long as you always do it prior to a build/deploy cycle, I guess those changes don't really matter.
Your git describe
update also seems to be "do it before build/deploy" but don't really care about the changes.
However, a lot of people would be very confused by a pom.xml
file in a repo that didn't match the dependencies in deps.edn
and/or didn't seem to reflect the current released version 🙂
So whether you check it in or not after those changes probably depends on whether it's going into a public repo I suppose 🙂
Ya, I agree. It could be confusing to see a pom.xml with a weird version. You'd almost want the checked in copy to have a version of :project-uses-git-tags
, and maybe have an empty dependencies, so it appears to be there just to define the extra maven stuff that you can't derive from elsewhere.
I don't mind having a file with the correct version, I was more just trying to avoid the commits that go along with those workflows.
Our unit tests and commit messages are the signals the produce Tags, and Tags are the signals that create new publishes to maven repos.
(from a CI/CD perspective)
Yup. I think internal CI/CD processes are under different constraints and, unless you are publishing every successful build to (public) Maven Central / Clojars and also publishing every version to a (public) GitHub repo or similar, for internal releases you can definitely just keep a baseline pom.xml
under version control and update that as needed for each build to your repo (and throw it away afterward).