Skip to content

Server Build level API

Josh Suereth edited this page Jan 15, 2014 · 6 revisions

The server aspects to sbt build will be exposed to build/plugin authors as follows:

1. Build Keys

A new key available which can be used to interact with the server:

val uiContext = taskKey[sbt.UIContext]("All user interaction should be driven through this interface.")

Custom tasks and plugins will be able to interact with sbt clients via the uiContext in Global setting. All interaction with users should occur over the UIContext. Tasks should no longer attempt to read from System.in, as this will begin to throw exceptions.

TODO - Should we attempt for System.in compatibility for a bit?

2. A UI interface

package sbt
sealed trait UIContext {
  /** Prompts the user for input, optionally with a mask for characters. */
  def readLine(prompt: String, mask: Boolean): Option[String]
  /** Ask the user to confirm something (yes or no) before continuing. */
  def confirm(msg: String): Boolean

  // TODO - Ask for input with autocomplete?

  /** Sends an event out to all registered event listeners. */
  def sendEvent[T: Format](event: T): Unit
  def sendGenericEvent(data: JsValue): Unit
}
private[sbt] abstract class AbstractUIContext extends UIContext

This interface represents all the interaction that can be done with users. Interaction with sbt clients can consist of the following:

  • Reading a single line of input (potentially where you hide the user keystrokes).
    Example(s): Reading the PGP passphrase when needed, or selecting the main class to run.
  • Prompting the user to confirm before continuing. _Example(s): Ensuring the user wants to create a tag before continuing the release script.
  • Sending structured events to sbt clients. Example(s): Notifying your own Intellij Plugin the progress of your integration tests.

3. Plugin API

Plugins will, additionally, have the ability to tell the server how their build values can be serialized to interested clients. While many clients are expected to just listen to toString values, it is expected that some plugins may wish for their own rich tooling support. In this event, e.g. an IDE plugin could receive the complete structured data that results when a task is run.

trait Plugin {
  ...
  def serializers: Seq[(AttributeKey[_], Format[_])] = Nil

  // Example types for keys....
  //  TaskKey[T] =>  AttributeKey[Task[T]] -> Format[T]
  //  SettingKey[T] => AttributeKey[T] -> Format[T]
  //  InputKey[T] => AttributeKey[InputTask[T]] -> Format[T]
}