Условно включают предоставленные зависимости от объема с sbt и универсальным плагином

У меня есть проект, который представляет собой API scala и scalatra. У меня есть два дистрибутива, которые я создаю с помощью sbt-native-packager -

  • Установка RPM и DEB для локальных установок
  • Установка героя для облачных установок

В настоящее время я использую зависимости provided для объектов, которые мне нужно вручную управлять с помощью подхода RPM/DEB - библиотеки баз данных, которые я не могу связывать и распространять из-за ограничений лицензии.

"mysql" % "mysql-connector-java" % "5.1.30" % "provided",
"com.microsoft" % "sqlserver.jdbc" % "4.1" % "provided",
..etc..

Это отлично работает. Я использую универсальный плагин и задачу dist, несколько массируемую, а затем подключаю некоторые скрипты сборки пакетов.

Теперь я создаю установку heroku, и я не знаю, как добавить обратно в эти предоставленные зависимости. Я использую универсальный плагин и запускаю задачу stage. Однако, если зависимости отфильтровываются, и я бы хотел, чтобы они были включены при запуске stage, потому что у меня больше нет ограничений на лицензии в heroku.

Параметры, которые, я думаю, у меня есть...

  • Добавьте mapping, чтобы добавить обратно в предоставленные зависимости в рамках задачи stage, но не во время задачи dist
  • Drop предоставил область полностью и вручную исключает эти зависимости из процесса упаковки во время dist

У меня есть некоторые сопоставления, подобные этому,

//add webapp dir to zip
mappings in Universal ++= directory("src/main/webapp")

//add db dir to zip, but move it into /lib/db instead of /db
mappings in Universal ++= (directory("src/main/resources/db").map{t => 
    (t._1, "lib/"+t._2)
  }
)

Таким образом, я чувствую, что, вероятно, могу выяснить, как добавить/исключить, если я действительно попытался, но у меня проблемы с поиском какой-либо документации для этого материала. Примеры здесь не очень помогают, или я недостаточно понимаю.

Спасибо заранее!

Ответ 1

Это интересный вопрос. Некоторое время назад мы добавили возможность добавить произвольные артефакты из пути сборки. (См. scaladocs)

Вариант 1 может выглядеть так. Обратите внимание, что это не работает так, как я ожидаю, поскольку некоторые сопоставления не точно подобраны native-packager:

// `show universal::stage:mappings` works properly
mappings in (Universal, stage) ++= {
  // calculate provided dependencies.
  val compileDep = (managedClasspath in Compile).value.toSet
  val runtimeDep = (managedClasspath in Runtime).value.toSet
  val provided = compileDep -- runtimeDep

  // create mappings
  fromClasspath(provided.toSeq, "jar", artifact => true)
}

Я предлагаю вариант варианта 1, предоставив среду сборки и решил, какие сопоставления добавить.

mappings in Universal ++= {
  // a build environment
  val env = buildEnv.value

  // calculate provided dependencies.
  val compileDep = (managedClasspath in Compile).value.toSet
  val runtimeDep = (managedClasspath in Runtime).value.toSet
  val provided = compileDep -- runtimeDep

  // create mappings, depending on build environment
  fromClasspath(provided.toSeq, "jar", _ => env == BuildEnv.Stage)
}

// add the dependencies to the start script as well
scriptClasspath ++= { /* similar code as above */}

Что я хотел бы сделать

Я надеялся, что смогу сделать что-то вроде этого

libraryDependencies += "com.google.guava" % "guava" % "19.0" % "provided"

mappings in (Universal, stage) ++= fromClasspath(
   (managedClasspath in Compile).value,
   "jar",
    artifact => artifact.scope == "provided"
)

Это было невозможно, так как sbt Artifact не имеет доступа к области плюща (или я его не нашел).

Затем я попытался сделать это

libraryDependencies += "com.google.guava" % "guava" % "19.0" % "provided" extra("heroku" -> "true")

mappings in (Universal, stage) ++= fromClasspath(
   (managedClasspath in Compile).value,
   "jar",
    artifact => artifact.extra.find(_ == "heroku")
      .map(_.toBoolean)
      .getOrElse(false)
)

который тоже не работал, поскольку, как кажется, SBT не передает атрибуты extra из ModuleID в Artifact. Это оставило меня с описанным выше решением.