在sbt中构建时传递版本号

时间:2017-12-22 20:08:40

标签: sbt sbt-native-packager

我有一个半复杂的SBT流程,因为我需要根据需要的构建类型有条件地包含不同的配置文件。我通过子项目解决了这个问题:

lazy val app = project
    .in(file("."))
    .enablePlugins(JavaAppPackaging)
    .settings(
      commonSettings // Seq() of settings to be shared between projects
      ,sourceGenerators in Compile += (avroScalaGenerateSpecific in Compile).taskValue
      ,(avroSpecificSourceDirectory in Compile) := new java.io.File("src/main/resources/com/coolCompany/folderName/avro")
    )

lazy val localPackage = project
    .in(file("build/local"))
    .enablePlugins(JavaAppPackaging)
    .settings(
      organization := "com.coolCompany",
      version := "0.1.0-SNAPSHOT",
      scalaVersion := "2.11.8",
      name := "my-neat-project",
      scalacOptions := compilerOptions, //Seq() of compiler flags
      sourceDirectory in Compile := (sourceDirectory in (app, Compile)).value,
      mappings in Universal += {
        ((sourceDirectory in Compile).value / "../../conf/local/config.properties") -> "lib/config.properties"
      }
    )
    .dependsOn(app)

val buildNumber = inputKey[String]("The version number of the artifact.")

lazy val deployedPackage = project
    .in(file("build/deployed"))
    .enablePlugins(JavaAppPackaging)
    .settings(
      organization := "com.coolCompany",
      buildNumber := {
        val args : Seq[String] = spaceDelimited("<arg>").parsed
        println(s"Input version number is ${args.head}")
        args.head
      },
      version := buildNumber.inputTaskValue + "-SNAPSHOT", //"0.1.0-SNAPSHOT",
      scalaVersion := "2.11.8",
      name := "my-cool-project",
      scalacOptions := compilerOptions,
      sourceDirectory in Compile := (sourceDirectory in (app, Compile)).value,
      mappings in Universal += {
        ((sourceDirectory in Compile).value / "../../conf/deployed/config.properties") -> "lib/config.properties"
      }
    )
    .dependsOn(app)

现在我需要允许在构建时通过构建工具传递版本号。您可以看到我已尝试执行的操作:我创建了一个名为inputKey的{​​{1}}任务,然后尝试在buildNumber定义中访问该任务。我可以运行version :=任务本身就好了:

buildNumber

所以我至少可以验证输入任务是否按预期工作。问题是,在运行我想要的实际$ sbt 'deployedPackage/buildNumber 0.1.2' Input version number is 0.1.2 步骤时,我无法弄清楚我是如何实际获得该输入值的。

我尝试了以下内容:

packageBin

所以它显然不明白如何处理版本号。我尝试了很多不同的输入变体,例如$ sbt 'deployedPackage/universal:packageBin 0.1.2' [error] Expected key [error] Expected '::' [error] Expected end of input. [error] deployedPackage/universal:packageBin 0.1.2 [...]packageBin buildNumber::0.1.2[...]packageBin -- buildNumber 0.1.2,所有这些变量都会出现错误或类似内容,表明它不明白我是什么我试图传入。

现在,最终,这些错误是有道理的。 [...]packageBin -- 0.1.2,任务,知道如何处理命令行值,但buildNumber没有。如何设置此任务或这些任务以允许传递版本号?

我已经看过this question,但答案链接到一个sbt插件,似乎比我想做的事情多做了100多件事,包括我需要找到一种明确禁用的方法。我希望版本号能够传入&amp;在神器中使用。

编辑/更新:我通过切换回Maven解决了这个问题。

3 个答案:

答案 0 :(得分:1)

  

我认为您对sbt设置的工作方式感到有点困惑。设置在sbt加载时设置,然后在重新加载会话之前无法更改。因此,无论你设置什么版本,它都将被修复,它不能是动态的,取决于用户输入或任务(对比度是动态的,每次调用时都会评估)。

这是事实。但是,您仍然可以首先计算 SettingKey值。我们使用环境变量来设置我们的构建版本。

version := "1." + sys.env.getOrElse("BUILD_NUMBER", "0-SNAPSHOT")

<强>解释

  • 1.是主要版本。根据需要手动增加
  • BUILD_NUMBER是一个环境变量,通常由CI设置,例如詹金斯。如果未设置,请使用0-SNAPSHOT作为版本后缀。

我们在公司中使用它来进行持续部署管道。

希望有所帮助, 缪奇

答案 1 :(得分:0)

我认为你对sbt设置的工作方式有点困惑。设置在sbt加载时设置,然后在重新加载会话之前无法更改。因此,无论你设置version,它都将被修复,它不能是动态的,取决于用户输入或任务(对比度是动态的,每次调用时都会评估)。

您有一个输入任务buildNumber,它取决于用户输入,并在每次调用时进行评估:

> show buildNumber 123
Input version number is 123
[info] 123
[success] Total time: 0 s, completed Dec 24, 2017 3:41:43 PM
> show buildNumber 456
Input version number is 456
[info] 456
[success] Total time: 0 s, completed Dec 24, 2017 3:41:45 PM

它会返回您提供的任何内容,并且不执行任何操作(除println之外)。更重要的是,无论如何都不会影响version设置(甚至在理论上也是如此)。

当您使用buildNumber.inputTaskValue时,您指的是输入任务本身,而不是其值(由于它取决于用户输入,因此未知)。您可以通过查看version设置值

来查看
> show version
[info] sbt.InputTask@6c996907-SNAPSHOT

所以这绝对不是你想要的。

我建议您一般性地检查一下您的方法并阅读更多的sbt文档,例如关于Task graph(以及整个入门章节)。

如果您仍然需要根据输入在sbt load上设置版本,则可以使用command进行设置。它看起来像这样:

commands += Command.single("pkg") { (state0, buildNumber) =>
  val state1 = Project.extract(state0).append(Seq(version := buildNumber + "-SNAPSHOT"), state0)
  val (state2, result) = Project.extract(state1).runTask(packageBin in (deployedPackage, universal), state1)
  state2
}

但你应该非常小心手动处理状态。我再次建议您检查一下您的方法,并将其更改为更具惯用性的方法。

答案 2 :(得分:0)

我建议您只在调用需要该版本的任务之前为deployPackage项目设置版本设置。这是设置版本的最简单方法,并且由于设置键具有范围,因此应按预期工作。

我在这个大型多模块项目中使用了类似的东西,其中一个项目的版本历史比其他项目多。