SBT Resolver for plugin in local directory on Heroku - scala

I have an internal SBT plugin which sets up a lot of common aspects of my build. One of those is my setup to add my Artifactory credentials and resolvers. I typically publish the plugin locally so that my build can resolve it and then pull the remaining dependencies from my Artifactory repositories.
For deploying to Heroku, I planned to copy the published artifacts from my .ivy2 repo to a subfolder of the project. However, though I can get this to work locally using both Resolver.file and Resolver.url, I cannot get this to work once I push to Heroku. I even tried it as an unmanaged dependency but still unresolved in Heroku.
Does anyone know the magic spell for achieving this on Heroku?
I have attempted following in project/plugins.sbt:
Resolver.url.("local-plugins", url(s"file///${baseDirectory.value}/plugins"))(Resolver.ivyStylePatterns)
Resolver.file("local-plugins", file("plugins")(Resolver.ivyStylePatterns)
unmanagedBase := baseDirectory.value / "lib"

I recommend two different approaches:
Use the sbt-heroku plugin instead of deploying with Git. You can use local dependencies this way.
Deploy your plugin to BinTray. It's fairly easy, free, and worth the trouble.

I revisited this again today and the following worked:
In plugins.sbt:
resolvers += Resolver.file("local-plugins", file("local-plugins"))(Resolver.ivyStylePatterns)
My project also contains a local-plugins/ directory in the working folder which holds the published artifacts.

Related

How to add Github maven registry into build.sbt

I want to add a scala Library into my build.sbt dependencies. Here is the sample package, and it publishes in Github registry.
This library is not from the official maven repository, I could not find it in Maven repository. I think it could not install in there.
<dependency>
<groupId>gjuoun</groupId>
<artifactId>hellopackage_2.13</artifactId>
<version>0.1.6</version>
</dependency>
And then, I find it should belong to ghcr.io, so I add this line to my build.sbt.
resolvers += "hellopackage" at "http://ghcr.io/gjuoun/hellopackage"
It does not work at all. I could not use it. I am looking for a better to install this package by using resolvers without addSbtPlugin. (I don't want to use pom.xml if possible)
Thanks for any help.
You can use Daniel Spiewak's sbt plugin sbt-github-packages.
See details in http4s-request-signer_2.13 dependency is not downloaded from central repository
If you don't want to use sbt plugins and you're interested only in building your project but not publishing it (to Github registry) then you can just add to build.sbt
// specifying repo is optional: "_"
resolvers += "Another maven repo" at "https://maven.pkg.github.com/gjuoun/_"
credentials += Credentials(
"GitHub Package Registry",
"maven.pkg.github.com",
"_", // user is ignored
"ghp_YOUR_GITHUB_TOKEN"
)
libraryDependencies += "gjuoun" %% "hellopackage" % "0.1.6"
That's basically what the plugin does.
For security reasons it's better not to hardcode the token in build.sbt but for example put it into environment variable
credentials += Credentials(
"GitHub Package Registry",
"maven.pkg.github.com",
"_",
sys.env("GITHUB_TOKEN")
)
You can check that without credentials sbt will not be able to build your project.
The thing is that although manually you can download a JAR from Github in your browser without authentification (and put it into lib), this doesn't mean that Github allow reading, resolving, downloading programmatically via API (sbt, ivy, coursier) without authentification.
You need authentification only the first time. Then JAR will be cached locally in ~/.cache/coursier/v1/https/maven.pkg.github.com/gjuoun/_/gjuoun/hellopackage_2.13/0.1.6/ and will be taken from there further on.
Several quotes:
A valid Github token shouldn't always be mandatory #28
GitHub requires a token even for read-only access to packages.
Credentials should remain optional #34
So the problem I have with this is the fact that resolution from GitHub Packages also requires a token. You can't just download a package unauthenticated, meaning that credentials are necessary at all times regardless of whether or not you're publishing. Honestly, this is a thing that GitHub needs to fix.

sbt, couple questions: dependsOn

I have some questions about SBT:
1) I'm wondering why there is an option to use 'dependOn' clause. I fully understand that it joins projects.
lazy val projectA = Project("A", file("a"))
lazy val projectB = Project("B", file("b")).dependsOn(projectA)
What i don't like in this code: you can't specify version of projectA in projectB. it always aggregates latest condition of projectA. Why to split your application to multiproject if every subproject is tightly coupled with each other?
There is an another option. We can publish subproject in binary repository with version and add it as dependency in settings.
Why not to use this code:
lazy val projectA = project("A", file("a"))
lazy val projectB = Project("B", file("b")).settings(libraryDependencies ++= Seq("groupOfA" %% "A" % "versionOfA"))
Of couse, you need to have binary repository for this. But it's not a problem, you can install nexus locally (it supports almost everything and free to use), or use oss.sonatype.org.
2) This question is related to the first question, i don't understand why there is 'publishLocal' task. As i know SBT uses Ivy2 repository, but when you publish your project to nexus or oss.sonatype.org you publish it to maven2 repo. And the problem occurs when sbt detects locally published and cached from maven. It throws errors. I think this is sbt bug (https://github.com/sbt/sbt/issues/2687). I don't use publishLocal anymore, i don't understand why not to have installed binary repository on your machine if you want to split your application into mulpiple components.
As you noted, libraryDependencies is strictly more powerful than dependsOn for multi-project management, at the cost of increased complexity.
You don't even need to install a separate binary repository, your local repo is quite good enough to publish to with publishLocal.
Which brings us to your next question, that is why use publishLocal when it publishes to Ivy by default? Two things: first, set up the local publish to publish in Maven style: http://www.scala-sbt.org/0.13/docs/Publishing.html#Modifying+the+generated+POM (publishMavenStyle := true).
Second, regarding the problem when you have the same version locally published and cached from Maven Central. Short answer: don't do that. If you publish to Maven Central, you should be using local publishes for testing only, and should publishLocal only 'SNAPTSHOT' versions. You should be publishing only fixed version numbers to Maven Central. Then there's no conflict. It's how Maven was designed; version numbers should be immutable and 'SNAPSHOT's should be for testing only.

SBT library dependency on Github released JAR

I have a project on Github and I have set a release with a Jar for that project. I want to include this Jar in another project as an SBT dependency. How do I set up the resolvers to look for my jar in the github repo.
You want to release your jar into a repository. One option I would recommend is bintray, see bintray-sbt which is an sbt plugin for publishing to bintray, and details how to setup your second project to fetch the publish artifact.

Can sbt be used to access a none-scala github repo to read into a scala project?

I'm dealing with two repos:
- A github repo that contains a bunch of text files.
- A scala project that would like to read those text files.
I would like to use SBT to download the contents of the github repo as a build dependency.
I wouldn't mind if SBT supplied either a path (into the ivy repo?) for the project to use or build them into the projects available resources - or any other way that will just work. I'm aiming for something automatic; clearly there are ways I could do this manually.
If you talk about a bunch of text files like *.property for example that used as dependency for your project (do you really want download them every time?) you may use sbt.IO.download(url: URL, to: File). Just create task and add to project definition compile <<= (compile in Compile) dependsOn myDownloadTask After that you may process them as regular local files ;-).
IMHO you understand that you may add custom logic like caching or page parsing or REST request to GitHub to your project definition. At last you may create your own SBT plugin - there are few video tutorials "How to create SBT plugin in 5 minutes" on YouTube.

How do I let jenkins and m2eclipse share the same maven repository

How do I configure m2eclipse ( maven plugin for eclipse ) to use a centralized maven repository that is also used in jenkins.
The default user settings in m2eclipse is something like "home/user/.m2"
How can we do something like "ssh user#192.168.1.200:/var/lib/jenkins/.m2"?
A neat and easy way to do it is to use a repository manager. Sonatype's Nexus seems to be the most popular, but there are others (e.g. JFrog Artifactory and Apache Archiva). They run as HTTP servers, and you can change your Maven configuration (both locally and for Jenkins) to use it as a mirror for any Maven repository (e.g. the Central Maven repo), or use it to host your own repositories.
There is no need to do that. Your POM files list dependencies and they list repositories. Maven will then resolve your dependencies against all known repositories (the listed ones and the "build-in" ones, like Maven central).
Maven will do this in m2eclipse, when running a Maven build. Maven will also do that when running the build on Jenkins. So if both machines can connect to all the repositories listed in your POM files, both will retrieve the same artifacts and both will do the same builds.
You should really not try to share the local copy of the artifacts. That is as bad as if I and you try to share our Maven artifacts using a network share. Maven is designed to find and manage those artifacts and you are trying to do its job with this question.