# 一、什么是持续集成

持续集成,Continuous Integration,简称CI

Martin Fowler 对持续集成是这样定义的:持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成的问题,让团队能够更快的开发内聚的软件。

即持续集成强调开发人员每次提交代码之后,立刻对代码进行构建、(单元)测试。同时根据测试结果来判断新代码和原有代码能否集成在一起。每次代码的小幅变更,就能看到运行结果,从而不断累积小的变更,而不是在开发周期结束时,一下子合并一大块代码。

# 二、Travis CI

为了提高软件开发的效率,自动化工具构建和测试层出不穷。Travis CI 就是其中对一个,它会同步你在 GitHub 上托管的项目,每当你 Commit Push 之后,就会在几分钟内根据项目根目录下的配置文件(.travis.yml)的执行步骤测试部署你的项目。

# 2.1 开始

  1. 用你的 GitHub 账号登录 Travis CI (opens new window),确认接受访问 GitHub 的权限。
  2. 登录之后,Travis-CI 就会同步你 GitHub 账号的仓库。然后打开账户页面 (opens new window)并给你想要构建的项目启用 Travis-CI。

  1. 添加 .travis.yml 文件到你项目根目录下,Travis CI 会按照 .travis.yml 里的内容进行构建。

# 三、.travis.yml

Travis CI 要求项目的根目录下面,必须有一个.travis.yml文件。这是配置文件,指定了 Travis CI 的行为。该文件必须保存在 Github 仓库里面,一旦代码仓库有新的 Commit,Travis CI 就会去找这个文件,执行里面的命令。

这个文件采用 YAML 格式。下面是本博客的.travis.yml文件。

language: node_js
node_js:
  - lts/*
branches:
  only:
  - master
cache:
  yarn: true
  directories:
    - "node_modules"
install:
  - yarn install
script:
  - yarn docs:build
after_success:
  - curl -LO http://gosspublic.alicdn.com/ossutil/1.6.7/ossutil64
  - chmod +x ossutil64
  - ./ossutil64 config -e $ENDPOINT -i $ACCESS_KEY_ID -k $ACCESS_KEY_SECRET
  - ./ossutil64 cp -rf docs/.vuepress/dist oss://zulu-wang

上述代码分别告诉 Travis CI 项目代码所需的语言环境、版本,参与构建的分支,用于加速构建的缓存,安装依赖,构建项目以及构建成功之后所做的操作。这里构建成功之后的操作是使用阿里云的相关工具将打包的文件上传到阿里云的 OSS 存储中。

# 四、工作生命周期

Travis CI 的工作由两个主要部分组成:

  • 安装:安装项目所需的依赖项
  • 脚本:运行构建脚本

# 4.1 安装依赖阶段(install)

例如 安装 package.json 里列出的所有依赖

install:
  - yarn install

也可以使用自定义脚本

install:
  - ./install-dependencies.sh

您还可以设置多个步骤,比如同时安装 PHP 和 Node 依赖

install:
  - composer install
  - yarn install

当安装命令其中有一条命令失败时,构建将立即停止并标记为 error。 如果不需要安装,即跳过安装阶段,通过设置

install: skip

# 4.2 构建阶段(script)

构建的命令和项目以及语言有关系 例如 本项目中的构建命令为

script:
  - yarn docs:build

同时构建命令也可以设置多个步骤

script:
  - command1
  - command2

不同于 install 阶段的是,如果其中一条命令失败,后续的命令将会继续执行,不会受其影响,但是构建的结果将被标记为 failure 如果command2只有在command1成功后才能执行,就要写成下面这样。

script:
  - command1 && command2

# 4.3 最小示例

Node 项目的 .travis.yml 可以写成下面这样。

language: node_js

Node 项目的 install 和 script 阶段都有默认脚本,可以省略。

# 4.4 生命周期

完整的生命周期如下:

  1. OPTIONAL Install apt addons
  2. OPTIONAL Install cache components
  3. before_install:install 阶段之前执行
  4. install
  5. before_script:script 阶段之前执行
  6. script
  7. OPTIONAL before_cache (for cleaning up cache)
  8. after_success or after_failure:script 阶段成功时执行 或者 script 阶段失败时执行
  9. OPTIONAL before_deploy:deploy 步骤之前执行
  10. OPTIONAL deploy
  11. OPTIONAL after_deploy:deploy 步骤之后执行
  12. after_script:script 阶段之后执行

# 4.5 部署阶段

部署阶段在 Travis CI 的工作生命周期中属于可选阶段。可以通过使用 Travis CI 的持续部署将代码部署到其所支持的服务提供商,如 HerokuAmazon。如果构建中断将会跳过部署阶段。 由于其只支持特定的服务提供商,所以这里不做赘述,具体相关操作可以参考相关文档 (opens new window)

# 4.6 构建中断

如果生命周期的前四个阶段中的任何命令返回非零退出码,则构建将被中断:

  • 如果 before_installinstallbefore_script 返回一个非零退出代码,构建将立即停止。
  • 如果 script 返回非零退出代码,则构建会失败,但会继续运行,然后标记为 failed。 after_successafter_failureafter_scriptafter_deploy 的命令退出码不会影响构建结果。但是,如果这些阶段某一阶段超时,将会导致构建标记为 failed。

# 4.7 运行状态

Travis CI 每次运行,可能会返回四种状态。

  • passed:运行成功,所有步骤的退出码都是0
  • canceled:用户取消执行
  • errored:before_install、install、before_script有非零退出码,运行会立即停止
  • failed :script有非零状态码 ,会继续运行

# 五、缓存

Travis CI 可以缓存不经常更改的内容,以加快构建过程。

# 5.1 构建阶段

Travis CI script 在构建阶段之后,但在 after_successafter_failure 之前上传缓存。

# 5.2 缓存依赖项和目录

例如

cache:
  yarn: true
  directories:
    - "node_modules"

上述配置将会缓存 $HOME/.cache/yarn 以及 node_modules 目录。 想要关闭缓存可以使用如下配置

cache:
  yarn: false

同时也可以缓存任意目录,例如 Gradle,Maven,Composer 和 npm 缓存目录,比如上述配置就缓存了 node_modules 目录。

# 5.3 缓存是如何工作的

Travis CI 的缓存文件并不存储于本地,而是使用类似于亚马逊云 S3 的存储服务,所以当缓存的文件太大时,可能并不能在速度上得到很大的提升。

  • 在构建之前,Travis CI 会检查是否存在缓存的存档,如果有则将其下载并解压到指定位置
  • 构建完成之后,Travis CI 会检查相关更改,并将更改后的文件重新打包上传

# 参考

  1. Continuous Integration (opens new window)
  2. The Product Managers’ Guide to Continuous Delivery and DevOps (opens new window)
  3. 持续集成服务 Travis CI 教程 (opens new window)