Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to publish to multiple repositories in SBT?

Tags:

scala

sbt

I am in the middle of upgrading Nexus version. As part of the process I've set up a new Nexus instance which will run in parallel with the older Nexus instance.

While migrating to the new instance I want to thoroughly test and vet the new instance before pulling the plug on older instance. This requires me to temporarily modify the publish workflow in such a way that sbt publishes the artifacts to both the Nexus instances.

I highly doubt the following code will actually work:

    publishTo <<= (version) {
       version: String =>
       if (version.trim.endsWith("SNAPSHOT")) Some("snapshots" at "http://maven1.dev.net:8081/nexus/content/" + "repositories/snapshots/")
       else Some("releases" at "http://maven1.dev.net:8081/nexus/content/" + "repositories/releases/")
    },
    credentials += Credentials("Sonatype Nexus Repository Manager", "maven1.dev.net", "release-eng", "release"),

    publishTo <<= (version) {
       version: String =>
       if (version.trim.endsWith("SNAPSHOT")) Some("snapshots" at "http://maven2.dev.net:8081/nexus/content/" + "repositories/snapshots/")
       else Some("releases" at "http://maven2.dev.net:8081/nexus/content/" + "repositories/releases/")
    },
    credentials += Credentials("Sonatype Nexus Repository Manager", "maven2.dev.net", "release-eng", "release"),

I also tried looking into a plugin called sbt-multi-publish but I couldn't compile and use it, either.

like image 805
naugustine Avatar asked Jan 08 '14 01:01

naugustine


People also ask

What is ThisBuild in sbt?

Typically, if a key has no associated value in a more-specific scope, sbt will try to get a value from a more general scope, such as the ThisBuild scope. This feature allows you to set a value once in a more general scope, allowing multiple more-specific scopes to inherit the value.

What is publishLocal?

The publishLocal action is used to publish your project to your Ivy local file repository, which is usually located at $HOME/. ivy2/local/ . You can then use this project from other projects on the same machine.

How do I clear my sbt cache?

You can use Pretty Clean to clean the all of dev tools caches including SBT. PrettyClean also cleans the SBT project's target folder.


2 Answers

With Commands and How to change a version setting inside a single sbt command? I could define a new command - myPublishTo - that changes publishTo setting before executing the original publish task:

def myPublishTo = Command.command("myPublishTo") { state =>
  val extracted = Project.extract(state)
  Project.runTask(
    publish in Compile,
    extracted.append(List(publishTo := Some(Resolver.file("file", target.value / "xxx"))), state),
    true
  )
  Project.runTask(
    publish in Compile,
    extracted.append(List(publishTo := Some(Resolver.file("file", target.value / "yyy"))), state),
    true
  )
  state
}

commands += myPublishTo

With this, execute myPublishTo as any other command/task.

You could also define a couple of aliases - pxxx, pyyy and pxy - in build.sbt that would execute a series of commands using ;.

addCommandAlias("pxxx", "; set publishTo := Some(Resolver.file(\"file\", target.value / \"xxx\")) ; publish") ++
addCommandAlias("pyyy", "; set publishTo := Some(Resolver.file(\"file\", target.value / \"yyy\")) ; publish") ++
addCommandAlias("pxy", "; pxxx ; pyyy")

In sbt console you can execute them as any other commands/tasks.

[sbt-0-13-1]> alias
    pxxx = ; set publishTo := Some(Resolver.file("file", target.value / "xxx")) ; publish
    pyyy = ; set publishTo := Some(Resolver.file("file", target.value / "yyy")) ; publish
    pxy = ; pxxx ; pyyy
[sbt-0-13-1]> pxy
[info] Defining *:publishTo
[info] The new value will be used by *:otherResolvers, *:publishConfiguration
[info] Reapplying settings...
[info] Set current project to sbt-0-13-1 (in build file:/Users/jacek/sandbox/so/sbt-0.13.1/)
...
[info]  published sbt-0-13-1_2.10 to /Users/jacek/sandbox/so/sbt-0.13.1/target/xxx/default/sbt-0-13-1_2.10/0.1-SNAPSHOT/sbt-0-13-1_2.10-0.1-SNAPSHOT-javadoc.jar
[success] Total time: 1 s, completed Jan 9, 2014 11:20:48 PM
[info] Defining *:publishTo
[info] The new value will be used by *:otherResolvers, *:publishConfiguration
[info] Reapplying settings...
...
[info]  published sbt-0-13-1_2.10 to /Users/jacek/sandbox/so/sbt-0.13.1/target/yyy/default/sbt-0-13-1_2.10/0.1-SNAPSHOT/sbt-0-13-1_2.10-0.1-SNAPSHOT-javadoc.jar
[success] Total time: 0 s, completed Jan 9, 2014 11:20:49 PM
like image 164
Jacek Laskowski Avatar answered Oct 11 '22 10:10

Jacek Laskowski


This is an old question, but the problem persists. I tried to revive sbt-multi-publish, but it's really old (sbt-0.12) and uses some sbt internals that are hard to deal with. So I took another approach and wrote a new plugin: sbt-publish-more.
It doesn't involve any on-the-fly settings changing or custom commands like the other answer.

After you add the plugin, just set resolvers you want to publish to (taking your code as an example):

publishResolvers := {
  val suffix = if (isSnapshot.value) "shapshots" else "releases"
  Seq(
    s"Maven1 ${suffix}" at s"http://maven1.dev.net:8081/nexus/content/repositories/${suffix}/",
    s"Maven2 ${suffix}" at s"http://maven2.dev.net:8081/nexus/content/repositories/${suffix}/"
  )
} 

And call publishAll task, it will publish to both repositories. You can also publish to different repositories with different configurations. Check usage docs for details.

like image 32
laughedelic Avatar answered Oct 11 '22 09:10

laughedelic