scalaplayframeworksbtsbt-native-packager

Clarification on scope delegation of dockerExposedPorts with sbt-native-packager


I am using the sbt-native-packager plugin that comes with Scala Play:

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.8")

I would like to know why the dockerExposedPorts setting isn't set for the root project when using:

name := """scala-play-react-seed"""
version := "1.0-SNAPSHOT"

lazy val root = (project in file("."))
  .enablePlugins(PlayScala)
  .settings(
    Docker / dockerExposedPorts := Seq(9000), // <-- 1. doesn't work
  )

Docker / dockerExposedPorts := Seq(9000), // <-- 2. also doesn't work
$ sbt show root/dockerExposedPorts
[info] * 

However, it works if i remove the Docker config part:

  .settings(
    dockerExposedPorts := Seq(9000), // <-- 3. works
  )
$ sbt show root/dockerExposedPorts
[info] * 9000

As far is i understand sbt's scope delegation, case 1. is scoped as root / Docker / Zero / dockerExposedPorts, which should be more specific than case 3. root / Zero / Zero / dockerExposedPorts. What am i missing here?


Solution

  • Yes, Docker / dockerExposedPorts is more specific than Zero / dockerExposedPorts. But unlike what you seem to assume, it's the more specific scopes that delegate to the less specific ones, not the other way around. The manual says so:

    This feature allows you to set a value once in a more general scope, allowing multiple more-specific scopes to inherit the value.

    And in fact, this is the only way it could be, because you might define e. g. both Docker / dockerExposedPorts and Universal / dockerExposedPorts. Which one of these would Zero / dockerExposedPorts delegate to? There's no sensible answer to that, hence delegation goes in the other direction.