SBT depend on specific snapshot version - scala

I have artifactory with multiple snapshots versions such as artifact-0.1-20120831.103456-5.
My project depends on specific snapshot version.
If I tell SBT to download 0.1-20120831.103456-5 version instead of 0.1-SNAPSHOT it fails on update task.
// build.sbt
libraryDependencies ++= Seq(
"com.example" % "smith" % "0.1-20120906.110133-36")
// sbt update
[warn] ==== My Repo snapshots: tried
[warn] http://repo.localhost/snapshots/com/example/smith/0.1-20120906.110133-36/commons-0.1-20120906.110133-36.pom
How to make SBT search artifacts in http://repo.localhost/snapshots/com/example/smith/0.1-SNAPSHOT directory but use unique snapshot version?

Addition Apart from the unique version plugin, sbt also has the aether-deploy plugin (see below).
There is the unique version plugin which lets you resolve your artifacts like you want. Quote from the page:
How to point at it
"0.1.0" or "0.1.0-20120602-073010" you can always use the static version number.
"0.1.0-+" selects the latest 0.1.0 snapshot.
"latest.integration" selects the latest revision regardless of its status.
"latest.milestone" selects the latest revision with either Milestone or Release status.
"latest.release" selects the latest with the Release status.
But you also have to publish with this plugin, since the artifacts are published in a different manner regarding the version: In your example, the artifact won't be stored under 0.1-SNAPSHOT directory but under 0.1-20120831.103456-5
Addition
There is also the aether-deploy plugin which uses Aether (Aether offers a standard way of interacting with Maven repositories). Problem is that this plugin currently works for deploying only (as the name of the plugin suggests). Maybe the author has plans to extend it so that it works for resolving as well (sounds like a useful feature to me). If you can't publish with the unique version plugin (e.g. if the snapshots are not owned by you), then you could ask that at the sbt forum.
So I can't offer a solution that works precisely as maven does for your use case, but hopefully it gives some useful info for you and others.

An ugly workaround would be to install the snapshot artefact in your own groupId (say smith.external) NOT as a SNAPSHOT, using install:instal-file
and declare the desired version number instead of declaring the usage of snapshot.
As you don't expect the version to change, you can rely on this, until you get it to work with a provided stable version (and the regular groupId)

Not the best solution but you may try to use conflict managers provided by Ivy (see apache docs). For example, 'latest-revision' is used by default and 'latest-compatible' manager should disallow any dependency conflicts.
It doesn't look easy to set up though, someone on google sbt group posted the following rule:
def addConflictManager(org: String, name: String, conflictManager: String) =
ivyModule <<= (ivyModule, streams) map { (module, s) =>
module.withModule(s.log) { (ivy, desc, _) =>
import _root_.org.apache.ivy.{core, plugins}
import core.module.id.ModuleId
import plugins.matcher.PatternMatcher
desc.addConflictManager(
ModuleId.newInstance(org, name),
ivy.getSettings.getMatcher(PatternMatcher.EXACT),
ivy.getSettings.getConflictManager("latest-compatible"))
module
}
}

Related

Scala, Sbt - download wrong version of library even if it is set in build.sbt

I have a weird problem with Sbt. I have a Scala zio version set to 1.0.12 in build.sbt:
val zio = "1.0.12"
But when I ran application with sbt it downloaded zio in version 2.x (screen):
I have no idea why. I removed .ivy2 and .sbt directories from user directory. I restarted intellij many times, invalided cached. Even with clear project it always downloads version 2.0.0. Whole code is inspected with this version.
Other zio related lib's versions I use:
val scalaVersion = "2.13.8"
val zio = "1.0.12"
val zioInteropCats = "3.2.9.0"
val zioInteropLog = "1.0.1"
Do you have any ideas why it works like this? I do not need to use ZIO in newest version.
I see in your comment you already solved this, but here's how you'd solve it in general:
This kind of thing is caused when two of your dependencies require different versions of a library. Your explicitly-set version is being "evicted" in favor of a higher version that something else requires
You can find this info by running sbt evicted. If your sbt version is recent (as of 2022), it should be able to use the versionScheme for scala libraries (if they are versions published after the feature was added) in order to alert you with an error when an eviction is likely to be incompatible.
The solution as you've found is to locate the dependency which is bringing in the incompatible version and then resolve the conflict by changing the version of either that dependency or the others

Dependency upgrade along with transitive dependencies

I have quite a big Play/Akka project on Scala 2.11 with literally dozens of dependencies, for which we need to migrate to all new stack: newest Play, Akka, Scala etc.
But along the upgrade way, our team constantly facing unexpected issues after certain lib update that another lib has transitive dependency on it, which was evicted and suddenly starting to crash in runtime somewhere in internals. E.g. play-pac4j has transitive dependency on Play, which we forgot to upgrade properly after Play upgrade from 2.5 to 2.7.
Question: is there any sbt plugin, which can say in advance which dependencies I need to change to which version version, if I want to update dependency group % name from version-x to version-y?
I'm aware of sbt-dependency-graph plugin and we are using, but I want some automation. Meaning: sbt-dependency-graph has whatDependsOn command, but I don't want to manually verify which version is compatible with transitive dependency i want to go to.
Thank you.

Sbt to publish to both Sonatype and Bintray

I have a scala library that I just converted from gradle to sbt.
By default it works by publishing to Sonatype upon release. However I also want to publish it to Bintray. The problem is that Bintray sbt plugin is overwriting the original publish to Sonatype.
I know I can sync to Sonatype and Maven central repository via Bintray. However I still like the way Sonatype handle the validation and check before I really can release it to Maven central.
How do I publish to both Sonatype and Bintray from my release server (not relying on Bintray to sync for me)?
I ran into the same problem and found a setup that works.
sbt-bintray supports a JVM property flag sbt.sbtbintray, When it is set to false, sbt-bintray will not overwrite the publishTo setting (and a few others). So to publish to both sonatype, just run the sbt publish once with the flag set to true and once to false.
However, I also use the sbt-ci-release plugin, which also overrides the publishTo setting (after bintray), but does not offer a flag to disable this. To workaround this, copy what sbt-bintray does into your own build:
publishTo := {
val old = publishTo.value
val p = (publishTo in bintray).value
if (BintrayPlugin.isEnabledViaProp) p
else old
}
Also see the build:
https://github.com/JetBrains/intellij-compiler-indices/tree/master/sbt-idea-compiler-indices

Is there a way to define the required sbt version in build.sbt?

In the build.sbt definition of a Scala project, is it possible to define the minimum version of sbt that is required to build the project?
project/build.properties allows you to force sbt to use particular version. If current version of installed sbt is different - sbt itself will download (if needed) the version you've specified there:
sbt.version=0.12.0
See, Hello for instance. So actually you may have installed several versions of sbt in your system - it's just jars, that placed in .sbt/boot/scala-{scala.version required by this sbt}/org.scala-sbt/sbt/{sbt.version} folder. Sbt executable actually looks for version specified in project/build.properties or (if it's not specified) highest version installed in the system.
P.S. From sbt-launcher perspective, sbt is only one dependency with small non-intersecting others like ansi.jar, so specifying the range of versions like [0.13.1, 0.13.8] have no much sense as it would be efective only for conflicting transitive deps. Otherwise it's enough to specify higher possible version (which would compile) - you may even choose some version that you already have (and update project's sbt that way).

sbt constructs wrong path for specific / timestamped snapshot versions

Background
I am developing a Play 2.2.3 application; the Play build system uses sbt.
I am using Sonatype Nexus OSS to manage various libraries built and deployed by Maven. At the moment, I am deploying snapshot versions of those libraries. For instance:
<groupId>myGroup</groupId>
<artifactId>myArtifact</artifactId>
<version>0.1-SNAPSHOT</version>
The Play application depends on snapshot versions of those libraries.
Intention
In the Play project, I want to use a specific (thus, "timestamped") snapshot version of a dependency -- say 0.1-20140509.053703-1 -- instead of the latest one as specified by 0.1-SNAPSHOT.
Issue
While the latter works perfectly well, sbt seems to be unable to resolve the specific version. At least sbt constructs the URL pointing to that specific version faultily: The name of the directory that contains the artifact ends with the actual timestamp instead of string SNAPSHOT.
Example
I created a new Play application and added the following dependency in file build.sbt: libraryDependencies += "myGroup" % "myArtifact" % "0.1-20140509.053703-1"
When resolving that dependency, sbt constructs URLs ending with myGroup/myArtifact/0.1-20140509.053703-1/myArtifact-0.1-20140509.053703-1.pom.
Note that the 3rd path component is 0.1-20140509.053703-1. Thus, the directory containing artifact myArtifact incorrectly contains the timestamp as well.
The correct directory name would be 0.1-SNAPSHOT; thus, using SNAPSHOT instead of the actual timestamp. The complete correct URL would thus end with myGroup/myArtifact/0.1-SNAPSHOT/myArtifact-0.1-20140509.053703-1.pom.
Referring to the latest snapshot version instead by using dependency entry libraryDependencies += "myGroup" % "myArtifact" % "0.1-SNAPSHOT" works. The URLs end with 0.1-SNAPSHOT/myArtifact-0.1-SNAPSHOT.pom.
Question
How could I persuade sbt to download a specific snapshot version?