SBT: compile & package -- "working tree not clean" - scala

I am working on a Scala extension for NetLogo (repo). I am following both the Extension API example and NetLogos Sample-Scala-Extension.
I am seeing:
[info] Done packaging.
To compare two paths outside a working tree:
usage: git diff [--no-index] <path> <path>
[warn] working tree not clean when packaging; target not created
[success] Total time: 6 s, completed Jan 29, 2019, 6:22:00 PM
The .jar that is generated does not contain modifications I made to the extension. I think it has something to do with "[warn] working tree not clean...".
Is this the case?
What is the solution?
File hierarchy:
Scala-Plume-Model
build.sbt
src
PlumeModelExtension.scala
build.sbt
enablePlugins(org.nlogo.build.NetLogoExtension)
name := "plume-scala"
version := "0.1"
scalaVersion := "2.12.0"
netLogoExtName := "plume-scala"
netLogoClassManager := "PlumeModelExtension"
netLogoZipSources := false
scalaSource in Compile := baseDirectory.value / "src"
scalacOptions ++= Seq("-deprecation", "-unchecked", "-Xfatal-warnings", "-encoding", "us-ascii")
netLogoVersion := "6.0.4"

The short answer: add isSnapshot := true to your build.sbt and then the package sbt task should start creating the output jar and zip files regardless of the current status of git.
Longer answer: The NetLogo Extension SBT plugin has some expectations about when packaging will occur. If isSnapshot is false or unset, the plugin assumes you're trying to do a "production" release. But for a production release you probably do not want to compile and package off of a dirty repository. So it warns you and does not create the artifacts.
The normal workflow would be to keep isSnapshot := true while you're in development, then once you have all your commits done and are ready for a release, add a commit to set isSnapshot := false (maybe along with a version bump for the extension), package and tag the release, then add a commit setting isSnapshot := true right away.

Related

sbt plugin: add an unmanaged jar file

I'm trying to create a relatively simple sbt plugin to wrap grpc-swagger artifact.
Therefore, I've created a project with the following structure:
projectDir/
build.sbt
lib/grpc-swagger.jar <- the artifact I've downloaded
src/...
where build.sbt looks like the following:
ThisBuild / version := "0.0.1-SNAPSHOT"
ThisBuild / organization := "org.testPlugin"
ThisBuild / organizationName := "testPlugin"
lazy val root = (project in file("."))
.enable(SbtPlugin)
.settings(name := "grpc-swagger-test-plugin")
According to sbt docs, that's all I have to do in order to include an unmanaged dependecy, that is:
create a lib folder;
store the artifact in there;
However, when I do execute sbt compile publishLocal, the plugin published lacks of that external artifact.
So far I've tried to:
set exportJars := true flag
add Compile / unmanagedJars += file(lib/grpc-swagger.jar") (with also variations of the path)
manual fiddling to libraryDependecies using from file("lib/grpc-swagger.jar") specifier
but none so far seemed to work.
So how am I supposed to add an external artifact to a sbt plugin?
The proper solution to this problem is to publish the grpc-swagger library. If for whatever reason this can't be done from that library's build system, you can do it with sbt. Just add a simple subproject whose only job it is to publish that jar. It should work like so:
...
lazy val `grpc-swagger` = (project in file("."))
.settings(
name := "grpc-swagger",
Compile / packageBin := baseDirectory.value / "lib" / "grpc-swagger.jar",
// maybe other settings, such as grpc-swagger's libraryDependencies
)
lazy val root = (project in file("."))
.enable(SbtPlugin)
.settings(name := "grpc-swagger-test-plugin")
.dependsOn(`grpc-swagger`)
...
The pom file generated for the root project should now specify a dependency on grpc-swagger, and running the publish task in the grpc-swagger project will publish that jar along with a pom file.
That should be enough to make things work, but honestly, it's still a hack. The proper solution is to fix grpc-swagger's build system so you can publish an artifact from there and then just use it via libraryDependencies.

cross-build artifacts being built but not with `releaseCrossBuild := true`

I'm trying to release a version of https://github.com/guardian/marley cross-built for Scala v2.11 & v2.12. All code dependencies are satisfied, and both +test and +publishLocalSigned work as expected, the latter definitely producing artifacts for Scala v2.11 & v2.12. Unfortunately, executing sbt release with the sbt-sonatype plugin only uploads artifacts for Scala v2.12 - it makes no attempt to upload artifacts for Scala v2.11 to the sonatype staging repository.
Here are the relevant sbt settings from the build.sbt file (full version in the repo on GitHub):
scalaVersion in ThisBuild := "2.12.4"
crossScalaVersions in ThisBuild := Seq(scalaVersion.value, "2.11.12")
import ReleaseTransformations._
releaseCrossBuild := true // true if you cross-build the project for multiple Scala versions
releaseProcess := Seq[ReleaseStep](
checkSnapshotDependencies,
inquireVersions,
runClean,
runTest,
setReleaseVersion,
commitReleaseVersion,
tagRelease,
releaseStepCommand("publishSigned"),
setNextVersion,
commitNextVersion,
releaseStepCommand("sonatypeReleaseAll"),
pushChanges
)
Here's a full copy of the sbt release command output: https://gist.github.com/rtyley/5f9f832fabe2bdcfc2d561a36c29f993 - you can see that even though [info] Setting scala version to 2.11.12 occurs (twice) - only Scala 2.12 artifacts are uploaded.
I think the issue is the releaseStepCommand("publishSigned") in your release process.
I think either:
it needs to be releaseStepCommand("+publishSigned"); or
you need to instead set releasePublishArtifactsAction := PgpKeys.publishSigned.value, and switch back to publishArtifacts (instead of using releaseStepCommand)
The README documents the releasePublishArtifactsAction way.

Sbt native packager not finding SystemdPlugin

I'm trying to get an rpm built that uses the Systemd archetype. However, I'm getting errors on my import in build.sbt. I am using sbt version 0.13.11 Specifically, I am seeing:
build.sbt:3: error: object systemloader is not a member of package com.typesafe.sbt.packager.archetypes
I'm trying to use version 1.1.4 of sbt-native-packager. Here is my plugins.sbt:
// The Typesafe repository
resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
// The Sonatype snapshots repository
resolvers += "Sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/"
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.1.4")
My build.sbt:
import com.typesafe.sbt.packager.linux.LinuxSymlink
import com.typesafe.sbt.packager.rpm.RpmPlugin.autoImport._
import com.typesafe.sbt.packager.archetypes.systemloader._
scalaVersion := "2.11.7"
name := "systemdtest"
organization := "myTestOrg"
enablePlugins(JavaServerAppPackaging, RpmPlugin, SystemdPlugin)
version := "1.0"
// RPM SETTINGS
rpmVendor := "me"
packageSummary in Linux := "A summary"
packageDescription := "Do some stuff"
rpmRelease := "1"
rpmBrpJavaRepackJars := false
rpmLicense := Some("Copyright this project")
rpmGroup := Some("mygroup")
rpmPrefix := Some("/opt/mypath")
I am getting the error when I try to run
sbt stage
or
sbt rpm:packageBin
The documentation for 1.1 on the native packager site (http://www.scala-sbt.org/sbt-native-packager/archetypes/systemloaders.html) says to use an auto-plugin called SystemdPlugin.
However, this does not exist in the 1.1 branch, and was introduced in the 1.2 branch that is (at time of this post, is 1.2.0M3), and not yet GA.
The correct convention is to add an assignment in your build.sbt called "serverLoading."
In my case, to use with an RPM, I needed to change my build.sbt to the following:
import com.typesafe.sbt.packager.rpm.RpmPlugin.autoImport._
import com.typesafe.sbt.packager.archetypes.ServerLoader
scalaVersion := "2.11.7"
name := "systemdtest"
organization := "myTestOrg"
enablePlugins(JavaServerAppPackaging)
version := "1.0"
// RPM SETTINGS
rpmVendor := "me"
packageSummary in Linux := "A summary"
packageDescription := "Do some stuff"
rpmRelease := "1"
rpmBrpJavaRepackJars := false
rpmLicense := Some("Copyright this project")
rpmGroup := Some("mygroup")
rpmPrefix := Some("/opt/mypath")
//THIS IS THE KEY PIECE!!
serverLoading in Rpm := ServerLoader.Systemd
I found my solution reading through the comments on this issue. https://github.com/sbt/sbt-native-packager/pull/785
sbt native-packager 1.2.0 i s almost released (Nov. 2016) and Muki Seiler details this new feature coming form PR 785:
Systemloaders are AutoPlugins now
Previously, the Java Server Application Archetype provided a setting serverLoading where you could define your system loader like this:
import com.typesafe.sbt.packager.archetypes.ServerLoader
serverLoading in Rpm := ServerLoader.Upstart
This adds the necessary configuration files and maintainer scripts (postinst, postun, etc. ) in order to register and start your application.
The biggest problem with the tight coupling between the server archetype and the systemloaders is that it’s hard to add systemloader specific settings without changing a lot in the server archetype.
It’s also a lot harder to reason about the code and the output.
With extra systemloader plugins we open the possibility to
easily extend a single systemloader
have a place to put generic systemloader functionality ( there is a SystemLoaderPlugin which takes care of common settings )
test systemloaders in isolation
better developer experience
You enable a systemloader by enabling a concrete systemloader plugin
enablePlugins(SystemdPlugin)

publish jar files with sbt (3rd party)

Hello I have 5 jar files and tried to publish them to a local repository with sbt.
But when I place them in unmanagedBase directory like lib/ they won't get copied with publishLocal. Is there an easy way to include them in the publishing process?
Currently maven has a similar solution here:
http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
One option is to define a subproject for each jar that you want published. Have your main project depend on each. Give each subproject an appropriate name, version, and organization. For each subproject, put its jar somewhere not on the classpath and make the output of packageBin be that jar.
For example (sbt 0.13 build.sbt),
lazy val main = project.dependsOn(subA)
lazy val subA = project.settings(
name := "third-party",
organization := "org.example",
version := "1.4",
packageBin in Compile := baseDirectory.value / "bin" / "third-party.jar",
// if there aren't doc/src jars use the following to
// avoid publishing empty jars locally
// otherwise, define packageDoc/packageSrc like packageBin
publishArtifact in packageDoc := false,
publishArtifact in packageSrc := false,
// tell sbt to put the jar on main's classpath
// and not the (empty) class directory
exportJars := true,
// set this to not add _<scalaBinaryVersion> to the name
crossPaths := true
)
This approach allows you to change the jar in subA/bin/third-party.jar and have it be used immediately and a subsequent publishLocal will publish it locally.
If you prefer separately publishing it locally, so that it isn't part of the project, define subA as a standalone project instead.

How does sbt choose which Scala version to use?

I have multiple projects in my sbt build. I'm trying to upgrade to Scala 2.10 from 2.9.1, so in my build.sbt file I put
scalaVersion := "2.10.0"
This seemed to work, because in my top-level project in sbt I get:
> scala-version
[info] 2.10.0
However, when I switch to one of the other projects:
> project web-client
[info] Set current project to web-client (in build file:/C:/Users/...
[web-client] $ scala-version
[info] 2.9.1
You see the version has now changed back to 2.9.1! How do I force the same Scala version to be used across all my projects?
I found out scoping the scalaVersion to ThisBuild will set it for all sub-projects. Details are here: http://www.scala-sbt.org/release/docs/Getting-Started/Multi-Project.html at the bottom, but here is what it says:
To set it only once, it is enough to write, in the main build.sbt file, the following line:
scalaVersion in ThisBuild := "2.10.0"
SBT has a default Scala version. You need to add the scalaVersion setting to all subprojects if you wish to change it. The most common way of doing that is having a "common settings" value that is added to all projects at the root level, through project/Build.scala.