并行运行Travis CI构建的几个步骤

196 阅读4分钟

不可否认的是,GitHub的行动在科技界引起了很大的反响,许多项目正在从其他持续集成系统(如Circle CITravis CI)过渡。

就我个人而言,在过去的几年里,我一直在使用Travis,用于我所有的OSS项目,我已经非常习惯它了。

然而,人们似乎正在 "放弃 "Travis而选择GitHub Actions,原因各不相同。"它更快","我可以并行地运行更小的任务",等等。

在我看来,我已经把一些非常特殊的任务转移到了travis,因为travis已经成为一个瓶颈,但我仍然对配置一些GitHub Actions所需的非常冗长的基于yaml的配置,与更简洁的travis相比,有不同的感受。

在这篇文章中,我将解释我是如何改进travis的构建,使其能够以并行作业的方式运行几个较小的任务,而不需要完全脱离它。

初始状态

这个项目的travis配置相对简单。它是用来为网络浏览器构建一个JS项目的,它必须运行接下来的任务。

  • 提示代码,以确保它符合项目的编码标准。
  • 运行单元测试。
  • 运行突变测试。
  • 构建docker镜像,以确保没有任何新的改动破坏它。
  • 有条件地在GitHub上发布一个版本,并附上一个dist文件,如果正在为git标签运行构建。
dist: bionic

language: node_js

branches:
  only:
    - /.*/

cache:
  directories:
    - node_modules

services:
  - docker

node_js:
  - '12.16.3'

install: npm ci

before_script:
  - echo "Building commit range ${TRAVIS_COMMIT_RANGE}"
  - export MUTATION_FILES=$(git diff ${TRAVIS_COMMIT_RANGE:-origin/main} --name-only | grep -E 'src\/(.*).(ts|tsx)$' | paste -sd ",")

script:
  - npm run lint
  - npm run test:ci
  - npm run mutate:ci
  - docker build -t project:test .

after_success:
  - node_modules/.bin/ocular coverage/clover.xml

before_deploy: npm run build ${TRAVIS_TAG#?}

deploy:
  - provider: releases
    api_key:
      secure: <key>
    file: "./dist/project_${TRAVIS_TAG#?}_dist.zip"
    skip_cleanup: true
    on:
      tags: true

这种方法的问题

这或多或少是可以的,但script 中的最后两个命令可能相对较慢,会延迟整个过程。

另外,特别是突变测试,目前无论结果如何都被认为是成功的,会使构建达到travis所允许的最大运行时间,使整个构建错误地失败。

before_script 步骤的原因是为了确定哪些源代码文件发生了变化,并只对它们进行突变测试,以减少这种情况。

除此以外,构建配置定义了 "全局 "定制,实际上只用于某些任务。

  • 运行npm ci ,不需要docker build 任务。
  • 获取docker 服务不是任何其他任务所需要的。
  • 确定更改的文件只被mutation tests 任务使用。

使用作业

travis支持的一个很酷的功能是使用作业构建矩阵,它可以让你定义多个作业,作为同一构建的一部分并行运行,并让它们中的每一个做不相关的任务。

利用这个功能,可以改进.travis.yml 文件,使其看起来像这样。

dist: bionic

language: node_js

branches:
  only:
    - /.*/

cache:
  directories:
    - node_modules

node_js:
  - '12.16.3'

jobs:
  fast_finish: true
  allow_failures:
    - name: 'Mutation tests'
  include:

    - name: 'Lint'
      install: npm ci
      script: npm run lint

    - name: 'Unit tests'
      install: npm ci
      script: npm run test:ci
      after_success:
        - node_modules/.bin/ocular coverage/clover.xml

    - name: 'Mutation tests'
      install: npm ci
      before_script:
        - echo "Building commit range ${TRAVIS_COMMIT_RANGE}"
        - export MUTATION_FILES=$(git diff ${TRAVIS_COMMIT_RANGE:-origin/main} --name-only | grep -E 'src\/(.*).(ts|tsx)$' | paste -sd ",")
      script: npm run mutate:ci

    - name: 'Build docker image'
      services:
        - docker
      install: skip
      script: docker build -t project:test .

    - name: 'Publish release'
      if: tag IS present
      install: skip
      script: skip
      before_deploy: npm run build ${TRAVIS_TAG#?}
      deploy:
        - provider: releases
          api_key:
            secure: <key>
          file: "./dist/project_${TRAVIS_TAG#?}_dist.zip"
          skip_cleanup: true
          on:
            tags: true

这种方法引入了所有这些好处。

  • 现在提示、测试、突变测试和构建docker镜像并行运行,使构建提前完成。
  • 突变测试步骤允许失败,由于有fast_finish 标志,travis甚至不会等待它完成,一旦其他步骤通过,就认为构建成功。
  • 只对某些作业有意义的配置被定义在作业本身,而不是全局。
  • 由于if: tag IS present ,"publish release "作业只有在构建标签时才有条件地运行。(更多关于travis中条件作业的信息)。
  • 只要任何一个任务失败,整个构建就会失败,你就不必继续等待。在这之前,如果第三个任务失败了,你仍然需要等待前两个任务的完成。
  • 每个作业都可以有一个名字,这使得在travis UI中更清楚地看到哪些任务正在运行。

image.png

结论

这篇文章的主要目的是为了展示travis仍然有很多东西要做。Github Actions无疑是很酷的,但通常没有银弹来解决所有问题,与其他工具的组合可能更合适。

另外,这也让使用travis的人可以改进他们的构建,而不必改变一切。然后,一旦你分好了任务,如果你还想转移到Github Actions,应该会更容易。

如果你感到好奇,这是我使用这个travis配置的项目:shlinkio/shlink-web-client