Sbt - Specify dependency extension - scala

i have troubles with Sbt.
In my local instance of JFrog Artifactory i have published a java library without the .pom file, so i have just the .jar file.
Configuration:
//build.sbt
libraryDependencies += "com.example" % "my-library" % "1.0" % "provided"
//build.properties
sbt.version = 1.3.0-RC2
Obliviously i have configured the resolvers properly.
Sbt fails with the following error:
not found: http://[Artifactory]/artifactory/maven/com/example/my-library/1.0/my-library-1.0.pom
The error is clear, indeed .pom file doesn't exists.
There is a way to specify, for a specific dependency, the extension ?

If for whatever reason you published the jar without a pom file on purpose, you can specify an explicit URL for the jar you want to depend on, e.g.
libraryDependencies += "slinky" % "slinky" % "2.1"
from "https://slinky2.googlecode.com/svn/artifacts/2.1/slinky.jar"
But if you just published the library ivy-style (so an ivy.xml file was published instead of a pom file), you just need to specify a right resolver for your repository, which will have ivy-style patterns.

When publishMavenStyle is true, a POM is generated by the makePom action and published to the repository.
Add this line in your build.sbt
publishMavenStyle := true
Configuring Artifact Resolution
To resolve artifacts through Artifactory, simply add the following code snippet to your build.sbt file:
resolvers += "Artifactory" at "http://<host>:<port>/artifactory/<repo-key>/"
Deploying Artifacts
To deploy sbt build artifacts to repositories in Artifactory, add the following code snippets to your build.sbt file.
For releases, add:
publishTo := Some("Artifactory Realm" at "http://<host>:<port>/artifactory/<repo-key>")
credentials += Credentials("Artifactory Realm", "<host>", "<USERNAME>", "<PASS>")
For snapshots, add:
publishTo := Some("Artifactory Realm" at "http://<host>:<port>/artifactory/<repo-key>;build.timestamp=" + new java.util.Date().getTime)
credentials += Credentials("Artifactory Realm", "<host>", "<USERNAME>", "<PASS>")
Where host and port are the host URL and port on which Artifactory is running, and repo-key is the Artifactory repository to which you are deploying artifacts.

Related

How to externalize protobuf files in JVM ecosystem?

I stumbled upon this Akka grpc tutorial which suggests that we can create a jar from a project that has .proto file under src/main/proto and add it as a dependency in client and server projects to build their respective stubs.
libraryDependencies += "com.example" %% "my-grpc-service" % "1.0.0" % "protobuf-src"
But this doesn't seem to work!! Are there any example projects that demonstrates how this would work in action? How can we externalize protobuf sources and use the same in a jvm based project?
I was able to figure out how to externalise protobuf files properly as per suggestion from akka-grpc docs.
The problem was that I was not adding sbt-akka-grpc plugin required by sbt to recognise .proto files and include them in the packaged jar. Without this plugin there won't be any .proto file made available in the packaged jar.
addSbtPlugin("com.lightbend.akka.grpc" % "sbt-akka-grpc" % "1.1.0")
Make sure to add organization settings in your build.sbt to prepare jar correctly.
organization := "com.iamsmkr"
Also, if you wish to cross-compile this jar to multiple versions add following entries in your build.sbt:
scalaVersion := "2.13.3"
crossScalaVersions := Seq(scalaVersion.value, "2.12.14")
and then to publish:
$ sbt +publishLocal
With appropriate jars published you can now add them as dependencies in your client and server projects like so:
libraryDependencies +=
"com.iamsmkr" %% "prime-protobuf" % protobufSourceVersion % "protobuf-src"
You can check out this project I am working on to see this in action.
Alternate Way
An alternate way I figured is that you can keep your .proto files in a root directory and then refer them in client and server build.sbt like so:
PB.protoSources.in(Compile) := Seq(sourceDirectory.value / ".." / ".." / "proto")
Checkout this project to see it in action.

Maven JAR file only includes HTML files, not Scala classes

I followed this guide to release a Scala / SBT JAR file in Maven.
I ran the sbt publishSigned and sbt sonatypeRelease for the spark-fast-tests 0.11.0 release and the JAR file was correctly built. See here. These commands come from the sbt-sonatype plugin.
For some reason, when I did the 0.12.0 release, the Maven JAR file only includes HTML files and images. For example, the downloaded JAR file contains this file com/github/mrpowers/spark/fast/tests/DatasetComparer.html, but doesn't include DatasetComparer.class.
The target/scala-2.11/spark-fast-tests_2.11-2.3.0_0.12.0.jar file also only includes the HTML files (either sbt publishSigned or sbt sonatypeRelease must have generated this JAR file).
When I run sbt package, the JAR file that's generated includes the Scala classes like com/github/mrpowers/spark/fast/tests/DatasetComparer.class, as expected.
spark-fast-tests is an open source project and here is the build.sbt file.
How can I include my project classes in the JAR file that's uploaded to Maven? Any tips / tricks on how to debug this better?
Analysing spark-fast-tests build.sbt I would make the following recommendations:
Add sbt-release to plugins.sbt to enable release process customisation:
addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.8")
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.0")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0")
Create version.sbt at project root and move version setting out of build.sbt:
version in ThisBuild := "0.12.1-SNAPSHOT"
Create sonatype.sbt at project root and move the following settings out of build.sbt:
homepage := Some(url("https://github.com/mrpowers/spark-fast-tests/"))
scmInfo := Some(
ScmInfo(
url("https://github.com/mrpowers/spark-fast-tests/"),
"git#github.com:mrpowers/spark-fast-tests.git"
)
)
developers := List(
Developer(
"mrpowers",
"Matthew Powers",
"matthewkevinpowers#gmail.com",
url("https://github.com/mrpowers/spark-fast-tests/")
)
)
licenses += ("MIT", url("http://opensource.org/licenses/MIT"))
publishMavenStyle := true
Add the following release settings to build.sbt:
import sbtrelease.ReleaseStateTransformations._
publishTo := Some(
if (isSnapshot.value) { Opts.resolver.sonatypeSnapshots }
else { Opts.resolver.sonatypeReleases }
)
releasePublishArtifactsAction := PgpKeys.publishSigned.value
releaseProcess := Seq[ReleaseStep](
checkSnapshotDependencies,
inquireVersions,
runClean,
runTest,
setReleaseVersion,
commitReleaseVersion,
tagRelease,
publishArtifacts,
setNextVersion,
commitNextVersion,
releaseStepCommand("sonatypeReleaseAll"),
pushChanges
)
Release to Maven Central with sbt release
For a working example have a look at build configuration of sbt-sonatype itself.
A little late to the party, but I had the same problem with spark-testing-base.
It stems from the way you modify the artifactName:
artifactName := { (sv: ScalaVersion, module: ModuleID, artifact: Artifact) =>
artifact.name + "-" + module.revision + "." + artifact.extension
}
which is probably copied from the official SBT docs.
Note that the docs have the following hint below the code though:
(Note that in practice you rarely want to drop the classifier.)
My solution for spark-testing-base is the following:
artifactName := { (sv: ScalaVersion, module: ModuleID, artifact: Artifact) =>
Artifact.artifactName(sv, module, artifact).replaceAll(s"-${module.revision}", s"-${sparkVersion.value}${module.revision}")
}
This should make sure to keep the classifier (and whatever additional things might go into the artifactName) and solved the problem of JAR files containing documentation instead of class files.

"Filename too long" in sbt assembly inside a docker container

I have a scala Play project and I need to create a fat jar in the docker build time but I get this error:
[warn] Error extracting zip entry [...] (File name too long)
I tried adding the option scalacOptions ++= Seq("-Xmax-classfile-name","72") in build.sbt but doesn't works. I tried also appending -Xmax-classfile-name=72 to sbt assembly with the same result.
As I need to do it in docker build time, I can't use a mounted volume as mentioned here https://github.com/sbt/sbt-assembly/issues/69#issuecomment-196901781
What do I need to do to fix this?
In /project/plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.13.0")
and in build.sbt
assemblyJarName in assembly := "jarname.jar"
target in assembly := baseDirectory.value
Then run command "assembly" from project root and should generate the jar file.

sbt not resolving dependency; path correct except ${package.type} extension

sbt (0.13.8) is failing to resolve the dependency in the following extremely simple build.sbt:
organization := "edu.umass.cs.iesl"
name := "nn-depparse"
version := "0.1-SNAPSHOT"
scalaVersion := "2.11.7"
resolvers += "IESL snapshot repository" at "https://dev-iesl.cs.umass.edu/nexus/content/repositories/snapshots/"
libraryDependencies += "cc.factorie" %% "factorie" % "1.2-SNAPSHOT"
parallelExecution := true
For some reason it resolves the following path:
https://dev-iesl.cs.umass.edu/nexus/content/repositories/snapshots/cc/factorie/factorie_2.11/1.2-SNAPSHOT/factorie_2.11-1.2-20151007.170205-28.${package.type}
Rather than the correct path to the jar:
https://dev-iesl.cs.umass.edu/nexus/content/repositories/snapshots/cc/factorie/factorie_2.11/1.2-SNAPSHOT/factorie_2.11-1.2-20151007.170205-28.jar
It seems as though ${package.type} is being interpreted as a literal file extension rather than whatever the contents of the variable package.type, but I have no idea why; I am using the simplest possible build configuration! As far as I know, I don't have any weird sbt configurations lying around (or any at all -- I checked ~/.sbt, and I have tried running on multiple machines).
As #kawty says it does look like the pom in question is malformed, but in terms of fixing your sbt script, you can change you dependency line to:
libraryDependencies += "cc.factorie" %% "factorie" % "1.2-SNAPSHOT" artifacts( Artifact("factorie", "", "jar"))
to manually specify the extension of the artifact that you want.
A following line found in factorie_2.11-1.2-20151007.170205-28.pom:
<packaging>${package.type}</packaging>
I suppose sbt uses this setting to get the artifact.
In the previous .pom file, it has:
<packaging>jar</packaging>
So, maybe it's a broken build.

How to add a github java dependency in sbt config?

I've added this code to my Build.scala.
lazy val root = Project("root", file(".")) dependsOn(jbcrypt)
lazy val jbcrypt = RootProject(uri("https://github.com/jeremyh/jBCrypt.git"))
But sbt fails with the error:
[error] (root/*:update) sbt.ResolveException: unresolved dependency: default#jbcrypt_2.11;0.1-SNAPSHOT: not found
How to tell sbt that it is Java not Scala?
How to reference to a specific branch or tag?
Thank you.
Building a project from source is only possible if the referenced project is a sbt project. sbt doesn't know of all the different build systems out there, so how is it supposed to know how to build a non sbt project?
It is possible to add support for other build systems through a sbt plugin but this may be a lot of work.
Your referenced project is a simple Maven project, which means that you can easily create a sbt project from it. Just fork the repo and create a build.sbt with the following content:
scalaVersion := "2.11.5"
projectDependencies += "junit" % "junit" % "3.8.1" % "test"
publishTo := {
val nexus = "https://oss.sonatype.org/"
if (isSnapshot.value) Some("snapshots" at nexus + "content/repositories/snapshots")
else Some("releases" at nexus + "service/local/staging/deploy/maven2")
}
This is the minimal code that was necessary to get it up and running. sbt seems to require that a publish repo is specified, it also seems to require an explicit Scala version. The dependency is already specified by your linked Maven project.
Of course, you know need to change the URI of RootProject to point to the location of your fork.
To your second question: You can reference a commit/tag/branch by appending it to the URI, separated with a # sign:
uri("git://github.com/your/repo#<commit-hash/tag/branch>")