Publishing into two repositories - scala

I want to be able to publish to 2 repositories.
One remote repository that I can publish to using sbt publish:
publishTo := Some("Remote repository" at "htpp://...")
One local repository (custom directory within project's root) that I can publish to using sbt publish-local. I couldn't find a way to override the default ${ivy.home}/local. I tried:
externalResolvers += Resolver.file("local", file("mydir"))
But that didn't work. I'm guessing that's because I append at the end of the sequence, so I'm not overriding the default one.
Any suggestions?
EDIT: I have a list of proxy repositories in ~/.sbt/repositories. So I want to keep them too.

To overwrite instead of appending to externalResolvers you could use
val remoteRepo = "my-public" at "http://my-nexus-server/content/groups/public/"
val localRepo = Resolver.file("local", file("mydir"))
externalResolvers := Seq(remoteResolver, localRepo)

Related

Scala library dependencies in internal artifactory pointing outside

We've got an internal artifactory server and one of my colleagues just put on there the get-coursier library I want to use.
But, when I try to install it through sbt in intellij, the dependencies it needs are trying to be pulled from an external repository, which I can't get to as I'm on an internal only network.
I'm pointing at our internal artifactory using a repositories file in my ~.sbt folder.
How would I define new paths for the dependencies so they would point at out internal artifactory server as well?
Any tips, greatly appreciated.
I add it to the build.sbtlike
val yourRepoRealm = "Artifactory Realm"
val yourRepoUrl = "http://yourhost.com/artifactory/libs-release-local"
Important is that you add this to the settings of the module where you need it:
lazy val sharedSettings: Seq[Def.Setting[_]] = Seq(
...
, resolvers ++= Seq(
yourRepoRealm at yourRepoUrl
, "jitpack" at "https://jitpack.io" // add other repos
), credentials += Credentials(new java.io.File(".credentials"))
, ...
)
This expects that you have your credentials in the project_root/.credentials. like
realm=Artifactory Realm
host=yourHost.com
user=username
password=yourPwd

In SBT, how to use addSbtPlugin with a Github URL?

Currently, I used a plugin like this:
addSbtPlugin("com.tuplejump" % "sbt-yeoman" % "0.7.1")
But then, I fork this plugin on github (let's say https://github.com/myname/play-yeoman.git) and make some changes, what would be an easier way to use my forked version of plugin? Do I really have to register this fork on a maven/ivy repository?
Thanks!
Using SBT 0.13.8, I was able to replace the following line in my ./project/plugins.sbt:
addSbtPlugin("net.ground5hark.sbt" %% "sbt-concat" % "0.1.8")
with the following two lines
lazy val root = (project in file(".")).dependsOn(concatPlugin)
lazy val concatPlugin = uri("https://github.com/ground5hark/sbt-concat.git#342acc34195438799b8a278fda94b126238aae17")
No other steps were necessary. Also, note that the git URI has a commit hash on the end. This is very useful for ensuring a known-to-work, specific version of the source is used in the project, rather than whatever the latest unknown state of the source is.
Follow this steps:
Add -SNAPSHOT suffix to the version of the plugin, i.e. version := "1.0.0-SNAPSHOT"
Run sbt publishLocal from the command line.
Reference the snapshot version from your plugins.sbt.

Cannot get sbt-concat to bundle styles from sbt-sass or sbt-less

(Example project provided) I cannot get sbt-concat to work as designed to find and concatenate stylesheets that result from styles that may be produced from preprocessor tasks. In my production app, I'm trying to use it to bundle select minified output files from sbt-sass. It does not work within the complex setup of that project, so I created an example project to see if I could get it to work at all. It does not work in the example project either. Here is a test project build.sbt that tries to create several bundles, with just about every possibility I can think of, just to see if any of them work (public Github repo, which you should be able to clone and immediately replicate the problem):
import com.typesafe.sbt.web.Import.WebKeys._
import com.typesafe.sbt.web.pipeline.Pipeline
name := """sbt-concat-test"""
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala, SbtWeb)
scalaVersion := "2.11.1"
libraryDependencies ++= Seq(
jdbc,
anorm,
cache,
ws
)
resolvers += Resolver.sonatypeRepo("releases")
includeFilter in (Assets, LessKeys.less) := "*.less"
excludeFilter in (Assets, LessKeys.less) := "_*.less"
val myPipelineTask = taskKey[Pipeline.Stage]("Some pipeline task")
myPipelineTask := { mappings => println(mappings); mappings }
pipelineStages := Seq(myPipelineTask, concat)
Concat.groups := Seq(
"style-group1.css" -> group(sourceDirectory.value ** "*.css"),
"style-group2.css" -> group(baseDirectory.value ** "*.css"),
"style-group3.css" -> group((sourceDirectory in Assets).value ** "*.css"),
"style-group4.css" -> group(target.value ** "*.css"),
"style-group5.css" -> group(Seq("core.css", "styles/core.css", "assets/styles/core.css", "app/assets/styles/core.css")),
"style-group6.css" -> group(Seq("lessStyle.css", "ui/lessStyle.css", "styles/ui/lessStyle.css", "assets/styles/ui/lessStyle.css", "app/assets/styles/ui/lessStyle.css")),
"style-group7.css" -> group(Seq("sassStyle.css", "ui/sassStyle.css", "styles/ui/sassStyle.css", "assets/styles/ui/sassStyle.css", "app/assets/styles/ui/sassStyle.css")),
"style-group8.css" -> group(Seq("**/*.css"))
)
I run ; clean; reload; stage from activator to test. I see asset source files copied over into the target folder, with the following results for the declared bundles:
style-group1.css does not exist
style-group2.css contains the contents of button.css and core.css
style-group3.css contains the contents of core.css and button.css
style-group4.css does not exist
style-group5.css contains only the contents of core.css
style-group6.css contains only the contents of compiled lessStyle.scss
style-group7.css contains only the contents of compiled sassStyle.scss
style-group8.css does not exist
I do not understand why the 2nd and 3rd cases do not pick up the preprocessor-produced css files, yet the tailor-made 6th and 7th cases do. Perhaps notably, the result of myPipelineTask shows PathMappings for all source files, as well as the derived css and sourcemaps from the Sass and Less tasks.
According to Typesafe support, the source of my woes is the fact that sbt-concat implements its PathFinder logic in such a way as to only pick up assets that are verbatim the same filename as in the source directory. The sequence of relative filenames works for files in the target directory, but has no pattern matching. This is rather unfortunate.
What does work is to construct a Seq of output files that will exist post-compilation by using a PathFinder on the source directory. So for .scss files, something like:
Concat.groups := {
// Determine the output names of the style files to bundle
// This is really roundabout because sbt-concat only offers 2 ways of
// specifying files, relative paths and using a PathFinder, and the
// latter approach restricts itself to source files instead of output files.
val sourceDir = (sourceDirectory in Assets).value
val scssFiles = (sourceDir ** "*.scss").getPaths
val scssRelativePaths = scssFiles.map(_.stripPrefix(sourceDir.getPath).stripPrefix("/"))
val outputRelativePaths = scssRelativePaths.map(_.stripSuffix(".scss") + ".min.css")
Seq("bundle.min.css" -> group(outputRelativePaths))
}
As a side note, another quirk of sbt-concat is that it doesn't put its new files in its own directory in web-assets:assetsTarget to separate them from artifacts of other pipeline stages. The Concat.parentDir is also unnecessary because you can simply anything you would place in that variable as a prefix for your bundle file name directly.

Publish zip created by sbt-native-packager

I am trying to publish to a repository the zip file generated by the sbt-native-packager plugin through universal:packageBin task.
I configured my project like this:
publishTo := Some("Repo" at "http://repo")
publishMavenStyle := true
packagerSettings
packageArchetype.java_application
I am struggling trying to create a new sbt task (named publishZip) using publish task and packageBin task to publish the zip file. How can I achieve this ?
Add the following line to your sbt build (around packagerSettings should be fine)
deploymentSettings
Depending on what you want to do you may not need to define the publishZip task you could run
sbt universal:publish which should only publish the zip
redefine publish so it depends on universal:publish which would publish all the projects artifacts
publish <<= publish.dependsOn(publish in config("universal"))
Then run sbt publish.
For completeness sake deploymentSettings (and packagerSettings) come from com.typesafe.sbt.SbtNativePackager which is useful to know if you use a scala build :)
The deploymentSettings worked however I wanted to refine the settings. It seems there were several issues going on. I and finally came up with the following solution:
//--use sbt-native-packager default java application
packageArchetype.java_application
//--a dummy task to hold the result of the universal:packageBin to stop the circular dependency issue
val packageZip = taskKey[File]("package-zip")
//--hard coded result of "universal:packageBin"
packageZip := (baseDirectory in Compile).value / "target" / "universal" / (name.value + "-" + version.value + ".zip")
//--label the zip artifact as a zip instead of the default jar
artifact in (Universal, packageZip) ~= { (art:Artifact) => art.copy(`type` = "zip", extension = "zip") }
//--add the artifact so it is included in the publishing tasks
addArtifact(artifact in (Universal, packageZip), packageZip in Universal)
//--make sure the zip gets made before the publishing commands for the added artifacts
publish := (publish dependsOn (packageBin in Universal)).value
publishM2 := (publishM2 dependsOn (packageBin in Universal)).value
publishLocal := (publishLocal dependsOn (packageBin in Universal)).value
The key pieces of this solution came from a comment from yanns and dgrandes

How can I configure Scalatra (sbt) to find the webapp folder in a different source folder than "main" [duplicate]

By default, Scalatra expects the "webapp" directory to be at src/main/webapp. How could that be changed to, e.g., content/doc-root?
sbt allows for customizing its default directories using something like the following:
scalaSource <<= (baseDirectory)(_ / "src")
So I assume it's just a matter of knowing the right "configuration key" to use...
#Kelsey Gilmore-Innis has the right answer, but since it's not accepted let's break it, break it, break it down.
First, I'm assuming you're following Getting started guide to install Scalatra using g8. Hopefully the same version I just got.
g8 scalatra/scalatra-sbt
What that g8 template did was to set up an sbt 0.13 build which uses scalatra-sbt 0.3.2 plugin:
addSbtPlugin("org.scalatra.sbt" % "scalatra-sbt" % "0.3.2")
This plugin internally uses JamesEarlDouglas/xsbt-web-plugin 0.4.0 to do the webapp-related settings.
xsbt-web-plugin 0.4.0
This is why xsbt-web-plugin becomes relevant even though you just want to change Scalatra's setting. The setting you need to rewire is called webappResources in Compile. How does that work?
rewiring webappResources
To rewire the setting, open project/build.scala. Add
import com.earldouglas.xsbtwebplugin.PluginKeys.webappResources
to the import clauses. Then change settings as follows:
lazy val project = Project (
"foo",
file("."),
settings = Defaults.defaultSettings ++ ScalatraPlugin.scalatraWithJRebel ++ scalateSettings ++ Seq(
organization := Organization,
name := Name,
version := Version,
scalaVersion := ScalaVersion,
resolvers += Classpaths.typesafeReleases,
webappResources in Compile := Seq(baseDirectory.value / "content" / "doc-root"),
...
)
)
Now move src/main/webapp to content/doc-root, reload sbt, and that should be it.
The resource folder is a Jetty property. If you're running embedded Jetty, it's specified here. You can edit it manually or override by setting the PUBLIC environment variable.
You also can override it in your SBT build file. It uses the xsbt-web-plugin to run, and you can override that plugin's settings.
For newer version of xsbt-web-plugin (1.0.0 as of writing) the way of changing source path is different.
First of all corresponding settings were moved to XwpPlugin.webappSettings. And you needs these two
webappSrc in webapp <<= (baseDirectory in Compile) map { _ / "content" / "doc-root" },
webappDest in webapp <<= (baseDirectory in Compile) map { _ / "content" / "doc-root" },
If you dont want to change the sbt settings, you can also do it programmatically by overriding serveStaticResource and using forward
override protected def serveStaticResource(): Option[Any] = {
// check to see if we need to alter the path to find the TRUE disk url
val incUrl = request.getRequestURI
if(incUrl.startsWith("/otherDir")) {
servletContext.resource(request) map { _ =>
servletContext.getNamedDispatcher("default").forward(request, response)
}
} else {
val trueUrl = "/otherdir" + incUrl
Option(servletContext.getRequestDispatcher(trueUrl).forward(request, response))
}
}
Disclaimer: You should also check that it doesn't go into an infinite loop.