a better approach for project-internal dependencies #2968
mberndt123
started this conversation in
Ideas
Replies: 1 comment
-
Somewhat related: sbt/sbt#7480 and coursier/sbt-coursier#490. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Problem Statement
I'd like to discuss a limitation of coursier's current dependency mechanism. The issue occurs in projects that publish multiple artifacts which keep a stable public API but have an unstable internal API that they use among themselves. This means that it is generally safe to upgrade from one minor version to the next for users of the public api, but not for users of the internal API, and consequently different versions of the different artifacts produced by such projects must not be mixed, because they use the internal API.
Notable examples include Jackson and Pekko.
It is unfortunately very easy to create such a situation. Suppose your project depends on
jackson-module-scala 2.13.2
, which depends onjackson-databind 2.13.2
. So far, so good. One day you decide to addavro 1.11.3
to your dependencies. It has a dependency onjackson-databind 2.14.2
. Because2.14.2
is newer than2.13.2
, sbt will evict the old version ofjackson-databind
and you end up withjackson-module-scala 2.13.2
andjackson-databind 2.14.2
on the classpath, and now your program will crash at runtime.@lefou suggested that this is an issue with Jackson's dependency specification:
jackson-module-scala 2.13.2
shouldn't depend onjackson-databind 2.13.2
but on the version rangejackson-databind [2.13.2, 2.14.0)
(original discussion on Matrix) According to him, this should lead to an error in version reconciliation, giving the user an opportunity to fix the problem by adding an explicit dependency onjackson-module-scala 2.14.2
. However, things don't seem to work this way: I've created an sbt project to simulate this situation, and the dependencies for themain
project can still be resolved. (to reproduce, runjacksonDatabindOld/publishLocal; jacksonDatabindNew/publishLocal; jacksonModuleScala/publishLocal; avro/publishLocal; show main/update
in your sbt prompt).As far as I can tell, there is currently no way to fix this other than manually specifying all your transitive Jackson (or Akka) dependencies in the same version – but that defeats the purpose of using a dependency resolver in the first place.
Proposed solution
I think to solve this problem it's necessary to extend the dependency model. A library
x
should have the possibility to specify in its pom file that it depends on another libraryy
, and thatx
andy
must always be the same version. This information should then be used by coursier to pull in a newer version ofx
if a newer version ofy
is pulled in as a (transitive) dependency via some other path.Thoughts?
Beta Was this translation helpful? Give feedback.
All reactions