In a project I'm working on, I wanted to copy a fat jar to a remote machine for testing.
The sbt-assembly plugin is handy for making a fat jar, but I didn't find any convenient plugins for just copying the jar somewhere. (SBT's built-in publish mechanism is overkill for what I need.)
It turns out that this is an almost trivial task to write. Unfortunately, figuring out exactly how to tie the pieces together isn't exactly straightforward.
I found this set of slides, while not comprehensive, to be about 100x more enlightening than the official sbt documentation. Starting with this slide especially, I "got" how the task could fall together.
The main sticking point for me was trying to figure out how to get the jar filename in my task. As the slides point out, operators that begin with <
create a dependency on other values. Specifically, <<=
:
declares a dependency and passes the right-hand value or method result to the setting represented by the left-hand key
I started from scratch, not worrying about the jar filename yet, just creating a stub task. The canonical "hello world" task is easily accomplished by adding two lines to build.sbt:
val helloTask = TaskKey[Unit]("hello", "Print hello") helloTask := println("hello world")
(Note that I'm using SBT 0.13.)
Take note that :=
in the definition of helloTask means that it's not
dependent on any other settings. If we redefine it as follows, it will
depend on the assembly task, and the assembly task's value (a
java.io.File
) will be available in the hello task:
val helloTask = TaskKey[Unit]("hello", "Print hello") helloTask <<= assembly map { (asm) => println(s"hello ${asm.getName}") }
Now when you run hello
at the sbt prompt, it will run all the tasks
required to generate the assembly jar, and then print the name of the
jar in the hello message.
Armed with this (still shallow!) knowledge, and cribbing from this (obsolete) recipe to accomplish the same goal with an older SBT, let's get dangerous and add this task to build.sbt:
val deployTask = TaskKey[Unit]("deploy", "Copies assembly jar to remote location") deployTask <<= assembly map { (asm) => val account = "user@example.com" // FIXME! val local = asm.getPath val remote = account + ":" + "/tmp/" + asm.getName println(s"Copying: $local -> $account:$remote") Seq("scp", local, remote) !! }