前言

  • 什么是持续集成?

持续集成(Continuous Integration,简称 CI)指的是只要代码有变更,就自动运行构建和测试,反馈运行结果。确保符合预期以后,再将新代码"集成"到主干。
持续集成的好处在于,每次代码的小幅变更,就能看到运行结果,从而不断累积小的变更,而不是在开发周期结束时,一下子合并一大块代码。
持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。

  • Travis CI简介

Travis
Travis CI 提供的是绑定 Github 上面的项目的持续集成服务,只要有新的代码,就会自动抓取。然后,提供一个运行环境,执行测试,完成构建,还能部署到服务器。

环境准备

  • 注册Travis

登录Travis官网,使用Github账户授权登录:
注册
登录成功即可看到你的个人主页:
个人主页

  • 关联仓库

在你的个人主页面板的下方可以看到你的所有的代码仓库,选择你需要持续集成的仓库,打开开关即可激活。
激活travis

  • 添加 .travis.yml

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

language: node_js
node_js:
    - 8.9.4
before_script: npm install
script: npm run test

上面代码中,设置了两个字段。language字段指定了默认运行环境,这里设定使用nodejs环境。node_js指定使用的Nodejs的版本,before_script指定了在执行脚本前需要执行的操作,script字段指定要运行的脚本,script: true表示不执行任何脚本,状态直接设为成功。

  • 运行流程

travis的完整生命周期如下:

before_install
install
before_script
script
aftersuccess or afterfailure
[OPTIONAL] before_deploy
[OPTIONAL] deploy
[OPTIONAL] after_deploy
after_script

这些生命周期都有对应的钩子:

before_install:install 阶段之前执行
before_script:script 阶段之前执行
after_failure:script 阶段失败时执行
after_success:script 阶段成功时执行
before_deploy:deploy 步骤之前执行
after_deploy:deploy 步骤之后执行
after_script:script 阶段之后执行

如果不想执行任何脚本可以直接设置:

script: true

同样地,如果不想安装任何环境也可以直接设置:

install: true
  • Travis CI客户端

如果不放心保密信息明文存在 Travis 的网站,可以使用 Travis 提供的加密功能。
但是首先,要按照Travis的客户端才能使用,安装 Ruby 的包travis:

gem install travis

安装成功会显示下列信息:
安装travis

环境变量

.travis.ymlenv字段可以定义环境变量。

env:
  - DB=postgres
  - SH=bash
  - PACKAGE_VERSION="1.0.*"

然后,脚本内部就可以使用$变量名使用这些变量了。
有些环境变量(比如用户名和密码)不能公开,这时可以通过 Travis 网站,写在每个仓库的设置页里面,Travis 会自动把它们加入环境变量。这样一来,脚本内部依然可以使用这些环境变量,但是只有管理员才能看到变量的值,可以在Environment Variables中进行设置。
定义变量

加密

  • 加密字符串

如果不放心保密信息明文存在 Travis 的网站,可以使用 Travis 提供的加密功能。在项目的根目录下,执行下面的命令。

travis encrypt TEST=testTravis

上面命令中,TEST是要加密的变量名,testTravis是要加密的变量值。执行以后,屏幕上会输出如下信息。
加密
现在,就可以把这一行加入.travis.yml

env:
  global:
    secure: "xxxxxxx"

然后,脚本里面就可以使用环境变量$TEST了,Travis 会在运行时自动对它解密。
travis encrypt命令的--add参数会把输出自动写入.travis.yml,省掉了修改env字段的步骤。

travis encrypt TEST=testTravis --add
  • 加密文件

使用下面的命令登入 Travis CI

travis login 

travis login
然后,进入项目的根目录,使用travis encrypt-file命令加密那些想要加密的文件。

travis encrypt-file bacon.txt
encrypting bacon.txt for rkh/travis-encrypt-file-example
storing result as bacon.txt.enc
storing secure env variables for decryption
Please add the following to your build script (before_install stage in your .travis.yml, for instance):
    openssl aes-256-cbc -K $encrypted_0a6446eb3ae3_key -iv $encrypted_0a6446eb3ae3_key -in bacon.txt.enc -out bacon.txt -d
Pro Tip: You can add it automatically by running with --add.
Make sure to add bacon.txt.enc to the git repository.
Make sure not to add bacon.txt to the git repository.
Commit all changes to your .travis.yml.

上面的代码对文件bacon.txt进行加密,加密后会生成bacon.txt.enc,该文件需要提交到代码库。此外,该命令还会生成一个环境变量$encrypted_0a6446eb3ae3_key,保存密钥,储存在 Travis CI,文件解密时需要这个环境变量。你需要把解密所需的openssl命令,写在.travis.ymlbefore_install字段里面。这些都写在上面的命令行提示里面。
注意:被加密的文件不能提交到代码库!!

before_install:
  -  openssl aes-256-cbc -K $encrypted_0a6446eb3ae3_key -iv $encrypted_0a6446eb3ae3_key
  -  in bacon.txt.enc -out bacon.txt -d

--add参数可以自动把环境变量写入.travis.yml

travis encrypt-file bacon.txt --add
encrypting bacon.txt for rkh/travis-encrypt-file-example
storing result as bacon.txt.enc
storing secure env variables for decryption
Make sure to add bacon.txt.enc to the git repository.
Make sure not to add bacon.txt to the git repository.
Commit all changes to your .travis.yml.

如果时加密多个文件的时候,注意不能一个个地单独travis encrypt-file,这样在travis CI上跑测试地时候会提示:bad decrypt,可以把多个文件在加密前打包成.tar文件,然后解密后再解压,例如加密文件foobar

$ tar cvf secrets.tar foo bar
$ travis encrypt-file secrets.tar
$ vi .travis.yml
$ git add secrets.tar.enc .travis.yml
$ git commit -m 'use secret archive'
$ git push

然后

before_install:
  - openssl aes-256-cbc -K $encrypted_5880cf525281_key -iv $encrypted_5880cf525281_iv -in secrets.tar.enc -out secrets.tar -d
  - tar xvf secrets.tar

自动部署到远程服务器

首先在本地或开发服务器上生成密匙,在命令行里输入:

ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/demo/.ssh/id_rsa): 
# 这里的密码一定要留空
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/demo/.ssh/id_rsa.
Your public key has been saved in /home/demo/.ssh/id_rsa.pub.
...

接下来你需要将你开发环境生成的密匙拷贝到你的部署服务器上。关于如何进行免密登录和把密钥拷贝到远程服务器,可以参考我的另外一篇博客:SSH原理以及实现远程免密登录

之所以进行这一步是为了实现免密码登录ssh,因为travis-ci自动执行命令是不支持交互式输入密码的。

将目录切换到项目根目录下,也就是 .travis.yml目录下。因为我们需要让 travis 远程登录自己的服务器,所以需要将本地保存着的 SSH 私钥进行加密处理

travis encrypt-file ~/.ssh/id_rsa --add

这个时候去看一下当前目录下的 .travis.yml,会多出几行

before_install:
  - openssl aes-256-cbc -K $encrypted_d89376f3278d_key -iv $encrypted_d89376f3278d_iv
  - in id_rsa.enc -out id_rsa -d

将输出的目录改为(不然待会执行的时候找不到/home/travis/.ssh/id_rsa文件)

in id_rsa.enc -out ~/.ssh/id_rsa -d -d

为保证权限正常,多加一行设置权限的 shell

before_install:
  - openssl aes-256-cbc -K $encrypted_d89376f3278d_key -iv $encrypted_d89376f3278d_iv
  - in id_rsa.enc -out ~/.ssh/id_rsa -d
  - mv id_rsa ~/.ssh/id_rsa
  - chmod 600 ~/.ssh/id_rsa

还有一点可能会用上,因为 travis 第一次登录远程服务器会出现 SSH 主机验证,这边会有一个主机信任问题。官方给出的方案是添加 addons 配置:

addons:
  ssh_known_hosts: your-ip

写部署脚本,如下是一个简单参考:

#!/bin/bash
cd /path/to/your-project
git pull origin master
echo 'travis build done!'

.travis.yml 配置文件中写:

after_success:
  - ssh your-user@your-ip -p yourport -o StrictHostKeyChecking=no "./script"

注意ssh登录以后执行地命令或者文件都是在远端服务器

添加标志

只要你每次在本地修改了代码,然后push到了Github上之后,travis就会自动监听变化然后开始测试
travis login
这是您编写的测试用例的测试结果:
travis login
在测试项目名字的右边有一个测试是否通过的标志,我们可以复制这个标志的地址添加到自己的Github的仓库上面。

参考