User Stories: AutoPlugins
This document details the desired workflow/use cases of the sbt project natures feature. This is a loosely specified, poorly defined set of "stories" (or terminal outputs) that we hope show our goal towards improving the consumption and definition of plugins within the sbt ecosystem.
User opens project/plugins.sbt
and adds the line:
// Was here before.
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "1.0")
The user's build.sbt
file is unchanged. The pgp plugin's required natures should be detected on any default/play projects and added to these projects automatically.
Story: User wants to aggregate tasks on a project, but not have that project actually have any behavior.
User takes his existing build.sbt
file:
val lib = project
val web = project.addPlugins(Web, PlayPlugin).dependsOn(lib) // scala is default
And declares the root project to be a "non-ivy" project which aggregates the others:
val lib = project
val web = project.addPlugins(Web, PlayPlugin).dependsOn(lib)
val root = Project("root", file(".")).disablePlugins(IvyModule).aggregate(lib,web)
- The user declares a dependency from his plugin to the play plugin:
Note: This is in build.sbt
, not project/plugins.sbt
name := "my-play-build-plugin"
organization := "my.company"
version := "1.0"
sbtPlugin := true
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.0")
- The user declares his plugin settings via the
AutoPlugin
interface. This will ensure that the PlayPlugin is enabled for a project before adding its own settings.
src/main/scala/MyPlugin.scala
:
import play.PlayPlugin
object MyPlugin extends sbt.AutoPlugin {
def select = PlayPlugin
// These will only be added to projects that have the play plugin settings added as well.
def projectSettings = Seq(sbt.Keys.prompt := "awesome is enabled >")
}
- User add the sbt-pgp plugin to
project/plugins.sbt
:
addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "1.0")
User attempts to call a pgp task from a project where it is not enabled:
sbt> publishSigned
error: publishSigned is not defined on project 'root'.
This tasks is defined by the 'com.typesafe.sbt.SbtPgp' plugin but was not enabled.
To enable, please add the following plugin(s):
* sbt.plugins.IvyModule
- User creates a 'root' plugin representing the core C++ features:
object CppPlugin extends RootPlugin {
override def projectSettings = ...
override def globalSettings = ...
}
- Create a helper project instantiation.
def cppProject(name: String, dir: File): Project =
Project(name,file).disablePlugins(plugins.JvmModule).addPlugins(CppPlugin)
Currently the order of plugin defined in project/plugins.sbt
will be respected, except that plugins
which depend on other plugins will have their settings added after their dependencies.
In addition, you can use the following pattern:
We have a pipeline of tasks to perform in an order:
case class PipelineStage(priority: Int, task: Task[Unit])
object PipelinerPlugin extends RootPlugin {
val rawPipeline = settingKey[Seq[PipelineStage]]
val pipeline = taskKey[Unit]
override val projectSettings = Seq(
rawPipeline := Nil,
pipeline := (Def.taskDyn {
rawPipeline.value.sortBy(_.priority).map(_.task).join
}).value
)
}
object PipelineStageExamplePlugin extends AutoPlugin {
val stageExamplePriority = settingKey[Int]("my priority")
val stageExampleAction = taskKey[Unit]("my task to do stuff")
def select = PipelinerPlugin
override val projectSettings = Seq(
stageExamplePriority := 1,
stageExampleAction := println("THIS is an example stage")
rawPipeline += stageExamplePriority.value -> stageExampleAction.toTask.value
)
}