【问题标题】:Pass in version number when building in sbt在构建 sbt 时传入版本号
【发布时间】:2018-06-05 10:08:48
【问题描述】:

我有一个半复杂的 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)

现在我需要在构建时允许构建工具传入版本号。您可以看到我已经尝试做的事情:我创建了一个名为buildNumberinputKey 任务,然后尝试在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 知道如何处理命令行值,但packageBin 不知道。如何设置此任务或这些任务集以允许传入版本号?

我见过this question,但答案链接到一个 sbt 插件,它似乎比我希望它做的事情多 100 件,包括我需要找到一种明确禁用的方法。我希望版本号能够传入并在工件中使用。

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

【问题讨论】:

    标签: sbt sbt-native-packager


    【解决方案1】:

    我认为您对 sbt 设置的工作方式有些困惑。设置在 sbt 加载时设置,然后在重新加载会话之前无法更改。因此,无论您将版本设置为什么,它都将是固定的,它不能是动态的,并且取决于用户输入或任务(相比之下,它是动态的,并且每次调用它时都会进行评估)。

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

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

    说明

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

    我们在公司中将其用于我们的持续部署管道。

    希望对您有所帮助, 渚

    【讨论】:

    • 如果你使用 git flow,使用https://github.com/sbt/sbt-releasehttps://github.com/sritchie/sbt-gitflow 也很有用
    【解决方案2】:

    我认为您对 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 加载时设置版本,您可以使用 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
    }
    

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

    【讨论】:

    • 我做错了并不奇怪。这种事情有起点吗?对于我认为非常常见的用例,我能找到这么少的资源让我感到惊讶。
    • 我已经在答案中链接了 sbt 文档。不幸的是,没有太多可阅读的内容。也可以在Gitter channel上提问,解决一些小问题。
    【解决方案3】:

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

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

    【讨论】:

    • 我会将其改写为实际答案或将其发布为评论。目前看来,这个问题可能被认为不是答案,因此会被相应地标记。
    猜你喜欢
    • 2011-07-16
    • 2013-08-24
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 2017-05-31
    • 2011-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多