How to download sbt plugin depdendency without SBT version in the dependency URL? - sbt

I'm trying to use an sbt plugin that I've published in my private mavenrepository
The plugin is configured as following :
val buildSettings = Defaults.defaultSettings ++
Seq (organization := buildOrganization,
scalaVersion := buildScalaVersion,
version := buildVersion,
publishMavenStyle := true,
pomIncludeRepository := { _ => true },
scalacOptions ++= Seq("-deprecation", "-unchecked", "-encoding", "utf8"),
publishTo := Some("External" at "http://xx.yy.net/archiva/repository/external"),
credentials += Credentials(Path.userHome / ".sbt" / ".credentials")
)
With "sbt publish", the plugin is deployed here :
http://xx.yy.net/archiva/repository/external/templemore/sbt-cucumber-parent_2.10/0.8.0/sbt-cucumber-parent_2.10-0.8.0.pom
Then I use my plugin from another SBT app. In my plugins.sbt, I add :
addSbtPlugin("templemore" %% "sbt-cucumber-plugin" % "0.8.0")
But it fails because SBT (or Ivy) is looking at an URL with teh SBT version of the plugin (0.13) inside :
tried
[warn] http://xx.yy.net/archiva/repository/external/templemore/sbt-cucumber-plugin_2.10_0.13/0.8.0/sbt-cucumber-plugin-0.8.0.pom
1) How can I prevent SBT to add its version in the dependency URL?
2) Or, if 1 is not possible, how can I set my SBT plugin configuration to deploy the artifact to archiva with the right URL pattern?
Thanks :)

Based on your comment, you have to publish it with sbt-cucumber-plugin/publish, which will execute publish in a sub-project sbt-cucumber-plugin of the parent project.

Related

Sbt native packager doesn't create service script file

I've used native packager to deploy a play api as a RPM package. The package created lacks the /etc/init.d/ folder and script.
How can I debug this situation ?
Here is an extract from the build.sbt :
lazy val myApp = (project in file("api"))
.enablePlugins(PlayScala, RpmDeployPlugin, SonarPlugin)
.configs(IntegrationTest)
.settings(
organization := "com.organization",
scalaVersion := "2.11.12"
...)
libraryDependencies ++= Seq( etc...)
The problem I had was that I was missing SystemVplugin and RpmDeployPlugin (I used RpmPlugin only)
lazy val `my-api` = (project in file("my-api"))
.enablePlugins(PlayScala, RpmDeployPlugin, SystemVPlugin)
...

sbt aspectj with native packager

I'm attempting to use the sbt-aspectj plugin with the sbt native packager and am running into an issue where the associated -javaagent path to the aspectj load time weaver jar references an ivy cache location rather than something packaged.
That is, after running sbt stage, executing the staged application via bash -x target/universal/stage/bin/myapp/ results in this javaagent:
exec java -javaagent:/home/myuser/.ivy2/cache/org.aspectj/aspectjweaver/jars/aspectjweaver-1.8.10.jar -cp /home/myuser/myproject/target/universal/stage/lib/org.aspectj.aspectjweaver-1.8.10.jar:/home/myuser/myproject/target/universal/stage/lib/otherlibs.jar myorg.MyMainApp args
My target platform is Heroku where the artifacts are built before being effectively 'pushed' out to individual 'dynos' (very analogous to a docker setup). The issue here is that the resulting -javaagent path was valid on the machine in which the 'staged' deployable was built, but will not exist where it's ultimately run.
How can one configure the sbt-aspectj plugin to reference a packaged lib rather than one from the ivy cache?
Current configuration:
project/plugins.sbt:
addSbtPlugin("com.typesafe.sbt" % "sbt-aspectj" % "0.10.6")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.1.5")
build.sbt (selected parts):
import com.typesafe.sbt.SbtAspectj._
lazy val root = (project in file(".")).settings(
aspectjSettings,
javaOptions in Runtime ++= { AspectjKeys.weaverOptions in Aspectj }.value,
// see: https://github.com/sbt/sbt-native-packager/issues/598#issuecomment-111584866
javaOptions in Universal ++= { AspectjKeys.weaverOptions in Aspectj }.value
.map { "-J" + _ },
fork in run := true
)
Update
I've tried several approaches including pulling the relevant output for javaOptions from existing mappings, but the result is a cyclical dependency error thrown by sbt.
I have something that technically solves my problem but feels unsatisfactory. As of now, I'm including an aspectjweaver dependency directly and using the sbt-native-packager concept of bashScriptExtraDefines to append an appropriate javaagent:
updated build.sbt:
import com.typesafe.sbt.SbtAspectj._
lazy val root = (project in file(".")).settings(
aspectjSettings,
bashScriptExtraDefines += scriptClasspath.value
.filter(_.contains("aspectjweaver"))
.headOption
.map("addJava -javaagent:${lib_dir}/" + _)
.getOrElse(""),
fork in run := true
)
You can add the following settings in your sbt config:
.settings(
retrieveManaged := true,
libraryDependencies += "org.aspectj" % "aspectjweaver" % aspectJWeaverV)
AspectJ weaver JAR will be copied to ./lib_managed/jars/org.aspectj/aspectjweaver/aspectjweaver-[aspectJWeaverV].jar in your project root.
I actually solved this by using the sbt-javaagent plugin to adding agents to the runtime

How to successfully import a CrossProject sbt build into eclipse using sbt-eclipse

I've used sbt-eclipse in the past to successfully import a simple sbt project into eclipse. I'm now trying to leverage the CrossProject mechanism of sbt to use the Scala-JS environment (makes 2 subprojects in sbt--one for Javascript and one for JVM code). The recommendation (see SBT docs link here) is to add the setting 'EclipseKeys.useProjectId := true' in the build.sbt file to support importing (now) 2 projects into one eclipse project. I then give the 'eclipse' command in a running SBT session to create my eclipse project and then launch eclipse and attempt to import this new project. When I do this, the import dialog wizard in eclipse does show me two sub-projects, but when I try to finish the import, eclipse complains that the project already exists and I get two strange looking links in my eclipse project that seem to do nothing.
What is the correct procedure for getting a CrossProject sbt build into eclipse?
Ok, so it seems eclipse did not like that I had only one 'name' for the project that was in the shared settings area of the build.sbt I had this:
lazy val sp = crossProject.in(file(".")).
settings(
version := "0.1",
name := "SJSTut",
scalaVersion := "2.11.7"
).
jvmSettings(
// Add JVM-specific settings here
libraryDependencies ++= Seq(...)
).
jsSettings(
// Add JS-specific settings here
libraryDependencies ++= Seq(...)
)
and what I should have done was this:
lazy val sp = crossProject.in(file(".")).
settings(
version := "0.1",
scalaVersion := "2.11.7"
).
jvmSettings(
// Add JVM-specific settings here
name := "SJSTutJVM",
libraryDependencies ++= Seq(...)
).
jsSettings(
// Add JS-specific settings here
name := "SJSTutJS",
libraryDependencies ++= Seq(...)
)
Note the removal of the 'name' assignment from settings and instead, placements into both the jvmSettings and jsSettings area with uniquely different names.
Now I'm able to pull this into eclipse (as 2 separate projects). If anyone else has a better setup, I'd love to hear about it.

Publish sbt artifact to filesystem

I have an internal maven repository located at file:///some/path/here. I would like to publish my sbt artifacts to this location. I gleaned that the following should work.
publishMavenStyle := true
publishTo <<= version { (v: String) =>
val path = "file:///some/path/here/"
if (v.trim.endsWith("SNAPSHOT"))
Some("snapshots" at nexus + "maven-snapshots")
else
Some("releases" at nexus + "maven")
}
However, this fails with the following exception.
[info] delivering ivy file to .../target/scala-2.9.2/ivy-1.0-SNAPSHOT.xml
java.lang.UnsupportedOperationException: URL repository only support HTTP PUT at the moment
at org.apache.ivy.util.url.BasicURLHandler.upload(BasicURLHandler.java:202)
at org.apache.ivy.util.FileUtil.copy(FileUtil.java:150)
at org.apache.ivy.plugins.repository.url.URLRepository.put(URLRepository.java:84)
How can I publish artifacts using sbt to a repository specified by a file path?
Use this format to publish to a local file path:
publishTo := Some(Resolver.file("file", new File("/some/path/here")))

How do "transitive resolvers" work with SBT?

I have the following project build:
import sbt._
import Keys._
object ProjectBuild extends Build {
val buildVersion = "0.1-SNAPSHOT"
val delvingReleases = "Delving Releases Repository" at "http://development.delving.org:8081/nexus/content/repositories/releases"
val delvingSnapshots = "Delving Snapshot Repository" at "http://development.delving.org:8081/nexus/content/repositories/snapshots"
val delvingRepository = if (buildVersion.endsWith("SNAPSHOT")) delvingSnapshots else delvingReleases
lazy val root = Project(
id = "basex-scala-client",
base = file(".")
).settings(
organization := "eu.delving",
version := buildVersion,
resolvers += "BaseX Repository" at "http://files.basex.org/maven",
libraryDependencies += "org.basex" % "basex" % "7.2.1",
libraryDependencies += "org.specs2" %% "specs2" % "1.7.1" % "test",
publishTo := Some(delvingRepository),
credentials += Credentials(Path.userHome / ".ivy2" / ".credentials"),
publishMavenStyle := true
)
}
When I include the resulting library in another project, like so:
"eu.delving" %% "basex-scala-client" % "0.1-SNAPSHOT"
and I try to build that project, I get an error prompting me that the "org.basex % basex % 7.2.1" library referenced by that project cannot be found.
I have to go and add the resolver in the "client" project in order for the library to be found. Is there a way to avoid this?
There's no transitive resolvers, so the build user needs to know all the resolvers of all the transitive library dependencies. The benefit of this approach is that on the opensource projects, it encourages projects to publish to one of the known repositories connected to the known resolvers.
For corporate usage, you can prevent your traffic from going to unknown places introduced by some dependencies down the graph.
To share resolver settings within the organization, you can create an org-wide plugin.
Has this situation changed in the last 7 years, 10 months? I have a transitive library dependency at a custom repository. For its immediate client, I specify a resolver and the repository is written to the client's pom file when published. The client's client does not seem to use that information to find the transitive library. I have to "add the resolvers upstream by hand".

Resources