The OP wrote: "I would expect the following:"
> test:psk > ***** [APP NAME] Testapp
Without actually defining the psk task in the Test configuration, sbt will search for the psk task first in the Global configuration, and then in the order of the projects configurations , which by default is Seq(Compile, Runtime, Test, Provided, Optional) .
So, the following (and @Jacek Laskowski's answer) describes how you can deal with defining tasks in many areas without duplicating code. Customization can be limited to three axes (project, configuration, and task). Part of the project does not enter the game, so we will discuss the configuration and task here.
He recommended that task-specific settings be tied to the task in order to encourage reuse of keys. For example:
test in assembly := {}
The Test key above uses the assembly area to manage the tests that run before creating a thick JAR. You can define a "task-generator" method that will take the key and create a settings graph around it:
def assemblyTask(key: TaskKey[File]): Initialize[Task[File]] = Def.task { val t = (test in key).value val s = (streams in key).value Assembly((outputPath in key).value, (assemblyOption in key).value, (packageOptions in key).value, (assembledMappings in key).value, s.cacheDirectory, s.log) }
I use this to define assembly , packageScala and packageDependency .
lazy val baseAssemblySettings: Seq[sbt.Def.Setting[_]] = Seq( assembly := Assembly.assemblyTask(assembly).value, packageScala := Assembly.assemblyTask(packageScala).value, .... )
So far, baseAssemblySettings neutral.
If I wanted to use it in configurations like Compile and Test , I would call inConfig(conf)(settings) as follows:
lazy val assemblySettings: Seq[sbt.Def.Setting[_]] = inConfig(Compile)(baseAssemblySettings) ++ inConfig(Test)(baseAssemblySettings)
You now have several task schedules in several configurations.