如何让两个SBT任务按顺序执行,使一个在另一个之后执行,前提是两者都被指定要执行?

后端开发 2026-07-10

我有一个SBT项目,其中包含一个自定义任务,该任务根据外部资源的最新状态(本例中是一个外部数据库)重新生成用于测试的文件。

lazy val regenTestResource = taskKey[Unit]("regenerate src/test/resources/my_file.txt")
regenTestResource := {
  // Calls a separate shell script which regenerates the resource
  s"${baseDirectory.value.getAbsolutePath}/regen_test_resource.sh" !
}

这个任务只有在开发人员希望更新该文件时才会手动运行,例如如果外部资源以可能影响测试的方式发生变化。生成的文件会被保存在版本控制中,因此不需要在每次构建时重新生成。

如果我想同时重新生成资源和测试,我可以在同时运行这两个任务的情况下使用SBT:

sbt regenTestResource test

这个方法的问题在于,在 regenTestResource 运行并完成之前,我不希望测试运行(regenTestResource 可能需要一段时间才能完成)。

我可以让 regenTestResource 成为 test 的依赖来确保顺序,但我相信那样会在执行 test 的任何情况下都让它被执行,这也不是我想要的。

我正在寻找的是SBT对应Gradle排序规则 mustRunAfter 的等价实现,在Gradle中它确保如果两者都要执行,则一个任务必须始终在另一个任务之后执行,但仍然允许任一任务在没有对方时单独执行。

如果两者都被指定要执行,怎样才能让一个任务始终在另一个任务之前执行,但如果只指定执行第二个任务就不运行第一个任务呢?

解决方案

你可以定义一个新的聚合任务,让 regenTestResourcetest 之前按顺序执行,只有在你想让两者一起执行时才使用这个聚合任务。

lazy val regenTestResource =
  taskKey[Unit]("regenerate src/test/resources/my_file.txt")

regenTestResource := {
  s"${baseDirectory.value.getAbsolutePath}/regen_test_resource.sh" !
}

lazy val regenAndTest = taskKey[Unit](
  "Regenerate test resource then run tests"
)

regenAndTest := Def.sequential(
  regenTestResource,
  test in Test
).value
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章