手摸手教你搭建 Travis CI 持续集成和自动化部署

很早之前我就在用 Travis CI 做持续集成了,虽然只是停留在 zhuang bi 的阶段,但或多或少也保证了代码的提交质量。最近在写一个 《JavaScript API 全解析》系列的 Book,需要经常把文章部署到服务器上,手动部署实在是烦,索性花了一天时间研究了一下自动化部署。这篇文章是对 Travis CI 持续集成和自动化部署的总结,以飨社区。

前戏

Travis CI 目前有两个网站,一个是 travis-ci.com,另一个是 travis-ci.org. 前者用于企业级和私有仓库,后者用于开源的公有仓库。实际上 free plan 也可以使用 travis-ci.com,但优先级很低,跑个自动化动辄两个小时,因此我们使用 travis-ci.org.

首先打开 Travis CI 官网,并用 GitHub 账号登录,授权后 Travis CI 会同步你的仓库信息。接下来把需要做自动化的工程授权给 Travis CI.

手摸手教你搭建 Travis CI 持续集成和自动化部署_第1张图片

最好有一台 Linux 的服务器,我的是 Cent OS 7.6.x 64bit.

我们点开一个工程,再切到设置,可以看到在 push 代码和 PR 时都会触发持续集成,当然可以根据需求手动配置。

手摸手教你搭建 Travis CI 持续集成和自动化部署_第2张图片

持续集成

为了让持续集成像那么回事儿,我们先在 master 上切一个 develop 分支,再在 develop 上切一个 featur/ci 分支。

接着我们再用 Jest 写几个测试用例,注意如果项目中没有测试脚本而 .travis.yml 文件里面包含 yarn test,自动化 一定 报错。关于 Jest 这里不详细说,只贴出几个示例代码。

import * as utils from '../utils/util';

test('should get right date', () => {
  expect(utils.formatJSONDate('2019-03-10T04:15:40.629Z')).toBe(
    '2019-03-10 12:15:40',
  );
});

test('should get right string', () => {
  expect(utils.upperFirstLetter('AFTERNOON')).toBe('Afternoon');
  expect(utils.upperFirstLetter('YANCEY_LEO')).toBe('Yancey Leo');
});

然后我们在工程的根目录下新建一个文件 .travis.yml,并复制下面的代码。

language: node_js
node_js:
  - 8
branchs:
  only:
    - master
cache:
  directories:
    - node_modules
install:
  - yarn install
scripts:
  - yarn test
  - yarn build

简单解释一下,工程使用 Node.js 8.x,并且只在 master 分支有变动时触发 自动化部署(正常的提交、PR 都会正常走持续集成),接着将 node_modules 缓存起来(你懂的),最后安装依赖、跑测试脚本、在沙箱部署。

因此,理论上只要跑通这套流程,我们就可以放心的部署到真实环境了。

提交一下代码,并 pull request 到 develop 分支。在此过程中我们触发了 push 和 PR,所以会跑两个 CI。待到两个都成功跑完后,我们就可以放心的合到 develop 分支了。(这里我还做了代码质量检测,有兴趣可以戳 Codacy)

手摸手教你搭建 Travis CI 持续集成和自动化部署_第3张图片

最后我们回到 Travis CI 的官网,可以看到一套完整的构建流程:安装依赖 -> 测试 -> 沙箱部署

手摸手教你搭建 Travis CI 持续集成和自动化部署_第4张图片

持续部署

创建 rsa 对,并给予权限

首先登录你的服务器,一般来讲我们不会直接在 root 上操作,所以这里新增一个 caddy 的用户 。具体怎样在 Linux 新建用户请自行谷歌。

接下来 cd 到 ~/.ssh,看看有没有一对 id_rsa 和 id_rsa.pub,如果没有就用 ssh-keygen 生成。

给予 .ssh 文件夹 700 权限,给予 .ssh 里的文件 600 权限。(看下面这张图,你的文件夹里可能暂时没有 authorized_keys、 known_host、config 这三个文件,后面会说到。)

$ sudo chmod 700 ~/.ssh/

$ sudo chmod 600 ~/.ssh/*

手摸手教你搭建 Travis CI 持续集成和自动化部署_第5张图片

将生成的公钥添加到受信列表

进入到 .ssh 文件夹里,执行下面的命令,可以看到公钥被添加到受信列表。

$ cat id_rsa.pub >> authorized_keys

$ cat authorized_keys

测试登录

.ssh 目录下创建一个文件 config,输入如下代码并保存。

Host test
HostName 当前服务器的IP
User 当前用户名
IdentitiesOnly yes
IdentityFile ~/.ssh/id_rsa

因为 authorized_keysconfig 文件都是新增的,它们还没被赋予 600 权限,所以重新执行一遍 sudo chmod 600 ~/.ssh/*.

然后我们输入 ssh test,不出意外会重新登录 ssh。如果你的公钥从来没有被使用过,会提示 Are you sure you want to continue connecting (yes/no)? ,输入 yes 后也会正常重新登录,并且在.ssh 文件夹下还会生成一个 known_hosts 文件.

安装 Ruby

因为 Travis 客户端是用 Ruby 写的,所以我们得先安装 Ruby.

首先安装需要的依赖包:

$ yum install gcc-c++ patch readline readline-devel zlib zlib-devel \
   libyaml-devel libffi-devel openssl-devel make \
   bzip2 autoconf automake libtool bison iconv-devel sqlite-devel

接下来安装 RVM,并载入 RVM 环境。RVM 是 Ruby 的版本管理工具,类似于 Node 的 NVM.

$ gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3

$ \curl -sSL https://get.rvm.io | bash -s stable

# 载入 rvm 环境
$ source ~/.rvm/scripts/rvm

安装完之后输入 rvm -v 做下检查,如果有 rvm 1.29.1 (latest) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin [https://rvm.io/] 的字样证明安装成功。

最后安装 Ruby,这里选择 v2.4.1 版本,安装需要一段时间,完成后记得将此版本设为默认。

$ rvm install 2.4.1

$ rvm 2.4.1 --default

执行一下 ruby -vgem -v,如果和下图差不多证明安装成功。

安装 ruby 成功

安装 Travis 客户端

执行下面的命令以安装 Travis 客户端。

$ gem install travis

安装完成后执行 travis,它会让你安装相应的 Shell, 输入 yes 即可。

手摸手教你搭建 Travis CI 持续集成和自动化部署_第6张图片

配置免密登录

将你的工程克隆下来,并进入到工程目录,然后登录你的 GitHub 账号。

$ travis login --auto

手摸手教你搭建 Travis CI 持续集成和自动化部署_第7张图片

执行下面这句,它会利用服务器的私钥加密成一个叫做 id_rsa.enc 的文件,这个文件被用于 travis 登录你服务器的凭证,从而达到免密的目的。

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

手摸手教你搭建 Travis CI 持续集成和自动化部署_第8张图片

我们执行一下 ll,可以看到根目录下多出一个 id_rsa.enc 文件来,并且 cat .travis.yml,发现多出了 before_install.

为了更好地组织代码,我们在项目的根目录新建一个文件夹 .travis,然后将 id_rsa.enc 放到里面。

手摸手教你搭建 Travis CI 持续集成和自动化部署_第9张图片

配置 after_success 钩子

在写这一小节之前,我们先看一看 Travis 的生命周期:

  1. before_install 安装依赖前
  2. install 安装依赖时
  3. before_script 执行脚本前
  4. script 执行脚本时
  5. after_success 或 after_failure 执行脚本成功(失败)后
  6. before_deploy 部署前
  7. deploy 部署时
  8. after_deploy 部署后
  9. after_script 执行脚本后

因此 after_success 可用在成功通过测试脚本之后执行部署相关的脚本。当然细一点可以使用 deploy 相关的钩子,这里不做太复杂。

打开 .travis.yml文件,直接上全部代码。

language: node_js
sudo: true
node_js:
  - 8
branchs:
  only:
    - master
# 这里填写服务器的ip,若端口号不是22,后面要注明端口号
addons:
  ssh_known_hosts:
    - 你的服务器IP
cache:
  directories:
    - node_modules
before_install:
  # 因为我们把 id_rsa.enc 移到了.travis 文件夹下,所以 -in 后面要改成 .travis/id_rsa.enc
  # 其次,-out 后面自动生成的是 ~\/.ssh/id_rsa,要把 \ 去掉,否则会编译失败
  - openssl aes-256-cbc -K $encrypted_XXXXXXXXXXXX_key -iv $encrypted_XXXXXXXXXXXX_iv -in .travis/id_rsa.enc -out ~/.ssh/id_rsa -d
  # 开启 ssh-agent,即允许使用 ssh 命令
  - eval "$(ssh-agent -s)"
  # 给予 id_rsa 文件权限,避免警告
  - chmod 600 ~/.ssh/id_rsa
  # 将私钥添加到 ssh
  - ssh-add ~/.ssh/id_rsa
install:
  - yarn install
scripts:
  - yarn test
  - yarn build
after_success:
  # 登录服务器,执行部署脚本,其实最好把后面一串写成 shell 文件
  - ssh caddy@你的服务器IP -o StrictHostKeyChecking=no 'cd /var/www/jsapi/JavaScript-APIs-Set && git pull && yarn install && yarn build'

走一遍正式的流程

至此,搭建 Travis CI 持续集成和自动化部署就算完成了,可能不太严谨,但基本是这么一个思路。下面我们梳理一遍流程。

  1. 我们先在 feature/ci 分支修改一段代码,提交分支,并 PR 到 develop,此时会运行两个 CI。当两个 CI 都跑通了,我们可以放心的 merge request 到 develop 分支。
  2. 接下来让 develop PR 到 master,此时会运行两个 CI(一个是 develop 分支,一个是测试合并到 master 的 CI)。当两个 CI 都跑通了,我们可以放心的 merge request 到 master 分支。
  3. merge request 之后会跑最后一个流程, 也就是自动部署,部署成功后线上代码就会更新了。

加入徽章

别忘了把 build passing 徽章添加到你的 README.md 文件中。

手摸手教你搭建 Travis CI 持续集成和自动化部署_第10张图片

最后

不知道你有没有发现,Travis CI 支持 LGBT...

手摸手教你搭建 Travis CI 持续集成和自动化部署_第11张图片

以上、よろしく。

参考

How to Encrypt/Decrypt SSH Keys for Deployment

Travis-CI 自动化测试并部署至自己的 CentOS 服务器

CentOS 7 使用 rvm 安装 ruby 搭建 jekyll 环境

你可能感兴趣的:(持续集成,自动化部署,前端工程化,前端,travis-ci)