不可否认的是,GitHub的行动在科技界引起了很大的反响,许多项目正在从其他持续集成系统(如Circle CI或Travis 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中更清楚地看到哪些任务正在运行。
结论
这篇文章的主要目的是为了展示travis仍然有很多东西要做。Github Actions无疑是很酷的,但通常没有银弹来解决所有问题,与其他工具的组合可能更合适。
另外,这也让使用travis的人可以改进他们的构建,而不必改变一切。然后,一旦你分好了任务,如果你还想转移到Github Actions,应该会更容易。
如果你感到好奇,这是我使用这个travis配置的项目:shlinkio/shlink-web-client。