Table of Contents
- Story: User adds pgp plugin to the build.
- Story: User wants to aggregate tasks on a project, but not have that project actually have any behavior.
- User Story: User wants to create an sbt plugin that enhances play projects.
- User Story: User attempt to use a plugin which is not configured correctly.
- User Story: user wants to create a C++ workflow that does not include the Java workflow
- User Story: User wants to ensure the plugins contributing tasks can have users control the order.
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.
Story: User adds pgp plugin to the build.
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)
User Story: User wants to create an sbt plugin that enhances play projects.
- 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
AutoPlugininterface. 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 Story: User attempt to use a plugin which is not configured correctly.
- 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 Story: user wants to create a C++ workflow that does not include the Java workflow
- 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)
User Story: User wants to ensure the plugins contributing tasks can have users control the order.
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
)
}