【问题标题】:How to publish only when on master branch under Travis and sbt 0.13如何仅在 Travis 和 sbt 0.13 下的主分支上发布
【发布时间】:2026-01-11 14:25:02
【问题描述】:

我正在使用 Travis 进行持续构建和集成。

after_success:
- sbt publish

虽然我们希望 Travis 构建我们所有的分支和拉取请求,但我们只希望它在 master 分支上时用于 publish

publishTo <<= version { (v: String) =>
  val nexus = s"asdf"
  /* Don't let Travis publish when building pull requests.
   * $TRAVIS_PULL_REQUEST == "false" if it's not a pull request.  So we wan't publishTo to be
   * None when TRAVIS_PULL_REQUEST != false.
   */
  if(Try(sys.env("TRAVIS_PULL_REQUEST")).getOrElse("false") != "false")
    None
  /* Don't let Travis publish except when building master. */
  if(Try(sys.env("TRAVIS_BRANCH")).map(_ != "master").getOrElse(false))
    None
  else if(v.trim.endsWith("SNAPSHOT"))
    Some("snapshots" at nexus + "snapshots")
  // don't let Travis publish releases, either
  else if(Try(sys.env("TRAVIS")).getOrElse("false") == "true")
    None
  else
    Some("releases"  at nexus + "releases")
})

这种方法的问题是 Travis 编译了两次分支,因为它在最后一步发布失败。

如何才能完全阻止 Travis 在非master 分支上运行sbt publish

【问题讨论】:

  • 是的,我们使用的是 sbt 0.13。

标签: sbt travis-ci


【解决方案1】:

您可以考虑在发布脚本之外处理此问题:

after_success:
  - test $TRAVIS_PULL_REQUEST == "false" && test $TRAVIS_BRANCH == "master" && sbt publish

【讨论】:

  • 这是一个更简单的答案,IMO。
  • 值得一提的是,这个解决方案不会在发布失败的情况下使构建失败......这并不总是好的。
【解决方案2】:

我会为它创建一个新任务,并在 Travis 中调用它。

val publishMasterOnTravis = taskKey[Unit]("publish master on travis")

def publishMasterOnTravisImpl = Def.taskDyn {
  import scala.util.Try
  val travis   = Try(sys.env("TRAVIS")).getOrElse("false") == "true"
  val pr       = Try(sys.env("TRAVIS_PULL_REQUEST")).getOrElse("false") == "true"
  val branch   = Try(sys.env("TRAVIS_BRANCH")).getOrElse("??")
  val snapshot = version.value.trim.endsWith("SNAPSHOT")
  (travis, pr, branch, snapshot) match {
    case (true, false, "master", true) => publish
    case _                             => Def.task ()
  }
}

publishMasterOnTravis := publishMasterOnTravisImpl.value

publishTo := {
  val nexus = s"asdf"
  if (version.value.trim.endsWith("SNAPSHOT")) 
    Some("snapshots" at nexus + "snapshots") 
  else
    Some("releases" at nexus + "releases")
}

这里的关键是使用Def.taskDyn,它可以让我在尾部位置调用publish,而不需要依赖它。 publishTo 将是简单的逻辑。

【讨论】:

  • 很好的答案,尤金。很多东西可以学习。由于使用了 sbt 0.13,我有点担心publishTo &lt;&lt;= version {} 构造,而不是内部的:=version.value。这是故意的还是只是复制问题正文的剩余部分?
  • 我故意将publishTo 保留为老派风格,因为 OP 看起来他已经熟悉它了。我会向新手推荐:= esp,但我不会妖魔化&lt;&lt;=
  • 我认为当您和其他人在答案中使用“老派风格”作为准备复制和粘贴的解决方案时,它的使用时间会更长。我认为应该禁止它以更好地理解 sbt(并避免让新手感到困惑)。
  • @JacekLaskowski 更新到 sbt 0.13 语法。
  • 非常感谢!我认为它最终会得到回报。