1. 使用 sbt 设置 Travis CI

使用 sbt 设置 Travis CI 

Travis CI 是一款面向开源和私有项目的托管持续集成服务。许多托管在 GitHub 上的 OSS 项目使用 Travis CI 的开源版本 来验证推送和拉取请求。我们将讨论设置 Travis CI 的一些最佳实践。

设置 project/build.properties 

持续集成是检查代码是否在您的机器之外工作的绝佳方法。如果您还没有创建,请确保创建 project/build.properties 并显式设置 sbt.version 号码

sbt.version=1.9.8

您的构建现在将使用 1.9.8。

阅读 Travis 手册 

Travis 的 官方文档 中包含大量的 Travis 技巧。将本指南作为灵感,但请参阅官方来源以获取更多详细信息。

基本设置 

为 Travis CI 设置构建主要与设置 .travis.yml 相关。 Scala 页面指出基本文件可能如下所示

language: scala

jdk: openjdk8

scala:
   - 2.10.4
   - 2.12.18

默认情况下,Travis CI 执行 sbt ++$TRAVIS_SCALA_VERSION test。让我们显式指定这一点

language: scala

jdk: openjdk8

scala:
   - 2.10.4
   - 2.12.18

script:
   - sbt ++$TRAVIS_SCALA_VERSION test

有关 script 部分的更多信息,请参阅 配置您的构建

Scala 页面所述,Travis CI 使用 paulp/sbt-extras 作为 sbt 命令。当您想覆盖 JVM 选项时,这一点变得很重要,我们将在稍后看到。

插件构建设置 

对于 sbt 插件,无需在 Scala 上进行交叉构建,因此以下所有内容都是您需要的

language: scala

jdk: openjdk8

script:
   - sbt scripted

另一个获取良好信息的来源是阅读 Travis CI 本身输出的内容,以了解虚拟环境是如何设置的。例如,从以下输出中,我们了解到它正在使用 JVM_OPTS 环境变量来传递 JVM 选项。

$ export JVM_OPTS=@/etc/sbt/jvmopts
$ export SBT_OPTS=@/etc/sbt/sbtopts

自定义 JVM 选项 

默认的 sbtJVM 选项由 Travis CI 人员设置,应该适用于大多数情况。如果您确实决定对其进行自定义,请首先阅读他们当前使用的默认值。由于 Travis 已经使用环境变量 JVM_OPTS,我们可以改为创建一个文件 travis/jvmopts

-Dfile.encoding=UTF8
-Xms2048M
-Xmx2048M
-Xss6M
-XX:ReservedCodeCacheSize=256M

然后使用 -jvm-opts 选项写出 script 部分

script:
   - sbt ++$TRAVIS_SCALA_VERSION -jvm-opts travis/jvmopts test

进行更改后,请确认 Travis 日志以查看标志是否生效

# Executing command line:
java
-Dfile.encoding=UTF8
-Xms2048M
-Xmx2048M
-Xss6M
-XX:ReservedCodeCacheSize=256M
-jar
/home/travis/.sbt/launchers/1.9.8/sbt-launch.jar

似乎有效。设置所有参数的一个缺点是,当环境更新并且默认值在未来提供更多内存时,我们可能会落后。

以下是如何添加几个 JVM 选项

script:
   - sbt ++$TRAVIS_SCALA_VERSION -Dfile.encoding=UTF8 -J-XX:ReservedCodeCacheSize=256M -J-Xms1024M test

sbt-extra 脚本将任何以 -D-J 开头的参数直接传递给 JVM。

同样,让我们检查 Travis 日志以查看标志是否生效

# Executing command line:
java
-Xms2048M
-Xmx2048M
-Xss6M
-Dfile.encoding=UTF8
-XX:ReservedCodeCacheSize=256M
-Xms1024M
-jar
/home/travis/.sbt/launchers/1.9.8/sbt-launch.jar

注意:这将按预期复制 -Xms 标志,这可能不是最好的做法。

缓存 

您可以通过使用 Travis CI 的 缓存 功能来加快 Travis CI 上的 sbt 构建速度。

以下是一个您可以使用的示例 cache: 配置

cache:
  directories:
    - $HOME/.cache/coursier
    - $HOME/.ivy2/cache
    - $HOME/.sbt

注意:Coursier 使用不同的 缓存位置,具体取决于操作系统,因此对于 macOS 或 Windows 映像,上述内容需要相应更改。

您还需要以下代码段来避免不必要的缓存更新

before_cache:
  - rm -fv $HOME/.ivy2/.sbt.ivy.lock
  - find $HOME/.ivy2/cache -name "ivydata-*.properties" -print -delete
  - find $HOME/.sbt        -name "*.lock"               -print -delete

结合上述更改,Travis CI 将压缩缓存目录并将其上传到云存储提供商。总的来说,使用缓存应该可以节省每个作业几分钟的构建时间。

构建矩阵 

我们已经看到了 Scala 交叉构建的示例。

language: scala

jdk: openjdk8

scala:
   - 2.10.4
   - 2.12.18

script:
   - sbt ++$TRAVIS_SCALA_VERSION test

我们还可以使用环境变量形成一个构建矩阵

env:
  global:
    - SOME_VAR="1"

  # This splits the build into two parts 
  matrix:
    - TEST_COMMAND="scripted sbt-assembly/*"
    - TEST_COMMAND="scripted merging/* caching/*"

script:
   - sbt "$TEST_COMMAND"

现在将创建两个作业来构建此 sbt 插件,同时运行不同的集成测试。该技术在 在虚拟机之间并行执行您的构建 中进行了描述。

通知 

您可以配置 Travis CI 来 通知您

默认情况下,电子邮件通知将发送给提交者和提交者,如果他们是仓库的成员[……]。

默认情况下,它会在以下情况下发送电子邮件,在给定分支上

  • 构建刚刚被破坏或仍然处于破坏状态
  • 以前已损坏的构建刚刚修复

默认行为看起来很合理,但如果您愿意,我们可以覆盖 notifications 部分以在构建成功时也向您发送电子邮件,或使用其他通信渠道,例如 IRC。

# Email specific recipient all the time
notifications:
  email:
    recipients:
      - [email protected]
  on_success: always # default: change

现在可能也是时候了解一下使用命令行 travis 工具进行 加密 了。

$ travis encrypt [email protected]

处理不稳定的网络或测试 

对于更容易发生不稳定网络或测试的构建,Travis CI 创建了一些技巧,如 我的构建超时 页面中所述。

如果返回代码为非零,则使用 travis_retry 启动命令会重试该命令三次。使用缓存,希望不稳定网络的影响会减少,但这仍然是一个有趣的技巧。以下是一些来自文档的警告词语

建议谨慎使用 travis_retry,因为过度使用它会导致构建时间延长,而此时可能存在更深层次的根本问题。

有关 Travis 的另一个小细节是输出超时

我们的构建有一个全局超时和一个基于输出的超时。如果构建 10 分钟内未收到任何输出,则认为它因未知原因停滞,随后将其终止。

有一个名为 travis_wait 的函数可以将此扩展到 20 分钟。

更多内容 

您还可以执行更多操作,例如 设置数据库安装 Ubuntu 包持续部署

Travis 提供了并行运行测试的功能,还对构建施加了时间限制。如果您的插件的脚本测试套件运行时间特别长,您可以在目录中运行脚本测试的子集,例如

    - TEST_COMMAND="scripted tests/*1of3"
    - TEST_COMMAND="scripted tests/*2of3"
    - TEST_COMMAND="scripted tests/*3of3"

将创建三个块,并分别为 tests 目录运行每个块。

示例设置 

以下是一个将它们全部放在一起的示例。请记住,大多数部分都是可选的。

language: scala

jdk: openjdk8

env:
  # This splits the build into two parts
  matrix:
    - TEST_COMMAND="scripted sbt-assembly/*"
    - TEST_COMMAND="scripted merging/* caching/*"

script:
  - sbt -Dfile.encoding=UTF8 -J-XX:ReservedCodeCacheSize=256M "$TEST_COMMAND"

before_cache:
  - rm -fv $HOME/.ivy2/.sbt.ivy.lock
  - find $HOME/.ivy2/cache -name "ivydata-*.properties" -print -delete
  - find $HOME/.sbt        -name "*.lock"               -print -delete

cache:
  directories:
    - $HOME/.cache/coursier
    - $HOME/.ivy2/cache
    - $HOME/.sbt