个人博客主要用于技术探索与试用,服务器是在阿里云上购买的,操作系统是 ubuntu 16.04. 痛点是每次有新的提交都要远程连接到阿里云服务器,首先从 git 上拉取最新代码,然后再进行打包构建。在有多次提交的情况下,反复登陆云服务器感觉有点不胜其烦,所以想搞一个自动化部署。
构建和测试的自动化工具层出不穷。Travis CI 就是这类工具之中,市场份额最大的一个。
从 0 开始配置的过程很繁琐,也遇到了一些大大小小的坑,所以把过程记录下来便于回看,同时如果看文章的你也遇到类似问题,希望能有所帮助。
开始之前,我们有如下假设:
在云服务器上配置大致分为以下三步:
安装 travis 及其依赖 -> travis 环境及参数配置 -> 引入自动化脚本
apt-get install ruby
apt install unzip
wget https://rubygems.org/rubygems/rubygems-2.6.12.zip
cd rubygems-2.6.12
sudo ruby setup.rb
// 更新 gem 到最新版本
gem update --system
gem install travis
我在第一次 install 时遇到了如下报错:
根据官方文档给出的答案:对于 Ubuntu 16.04 及以上版本,应安装 ruby-dev.
sudo apt-get install ruby-dev
之后再重新 gem install travis 成功!
travis login
在此过程中会要求用户输入 github 用户名和密码,如果成功会看到如下输出:
注意:从信息提示也可以看到用户名密码还是通过 github 验证,所以是安全的。
切换到本地仓库的根目录 (即 package.json 所在目录),建立一个 .travis.yml 文件,第一版可以比较简单,我是这样的:
language: node_js
node_js:
- '8.11.1'
cache:
directories:
- node_modules
注意:我缓存了一下 node_modules 以加快构建
travis encrypt-file ~/.ssh/id_rsa --add
before_install:
- openssl aes-256-cbc -K $encrypted_92c453e01dfa_key -iv $encrypted_92c453e01dfa_iv
-in id_rsa.enc -out ~/.ssh/id_rsa -d
上述含义就是:使用travis加密ssh私钥,结果为id_rsa.enc文件。这个enc文件需要提交到 github 远程项目中。.travis.yml 中增加的脚本是解密命,把加密私钥解密到 ~/.ssh/id_rsa 目录。~/.ssh/id_rsa 不是服务器中的目录,而是远程的travis容器。因为执行构建工作是远程的 travis 容器(travis 官网)
所以本质是远程实施持续集成 Travis 容器需要获得 github 生成的私钥,以获得相应的执行权限。服务器上安装的 travis 并不做持续集成,而是加密 github 的私钥,将其通过 github 项目提交后由远程 Travis 使用
为保证文件权限正常,再加一行设置权限的脚本:chmod 600 ~/.ssh/id_rsa
before_install:
- openssl aes-256-cbc -K $encrypted_92c453e01dfa_key -iv $encrypted_92c453e01dfa_iv
-in id_rsa.enc -out ~/.ssh/id_rsa -d
- chmod 600 ~/.ssh/id_rsa
id_rsa.enc 生成在 github 本地仓库根目录下,也需要和 .travis.yml 一起提交至远程 github
对于 .travis.yml 中自动生成的 openssl 命令,需要把 -out ~ /.ssh/id_rsa -d 中的 “~” 去掉,否则travis 在集成时会报错.
这个问题有人提过 Issue: openssl no such file or directory #555. 可能和我使用的 ubuntu 操作系统有关。
travis 第一次登录远程服务器会出现 SSH 主机验证,这边会有一个主机信任问题。官方给出的方案是在 .traivs.yml 中添加 addons 配置
addons:
ssh_known_hosts: xxx.xx.xx.xx (your ip)
将最新的 .travis.yml 和 id_rsa.enc 提交到git后,自动触发远程travis,如果 build 成功,说明 travis 和你的服务器打通了!
持续集成自动脚本与服务器无法交互,所以用sshpass可以解决密码输入的问题。
关于 sshpass 的脚本部分如下:
# ...
sudo: required
before_install:
- sudo apt-get install -y sshpass
after_success:
- sshpass -e ssh -o stricthostkeychecking=no [email protected] "bash /usr/blog/blog-frontent-vue3.0/build.sh"
上述脚本有四个注意点:
服务器本机设置环境变量:
travis encrypt DEPLOY_USER = [your username]
travis encrypt DEPLOY_PASS = [password]
执行后,在 .travis.yml 文件中发现增加如下配置:
env:
global:
- secure: "..."
- secure: "..."
远程 travis 容器 setting 中直接设置环境变量
我采用的是在远程 travis 容器中直接设置。设置好以后,在 .travis.yml 脚本中就可以直接引用环境变量了:
after_success:
- export SSHPASS=$DEPLOY_PASS
- sshpass -e ssh -o stricthostkeychecking=no $DEPLOY_USER@[my ip] "bash myProject/build.sh"
脚本比较简单,只要脚本中的日志在 travis 中成功打印,说明 travis 容器通过 sshpass 运行服务器脚本成功!
#!/bin/bash
cd myProject
echo 'pull from git'
git pull origin master
echo 'pull from git done!'
echo 'start building'
npm install
npm run build
echo 'travis build done!'
注意点:
最初运行脚本时总是报错 bash: npm : command not found
。而我自己在服务器终端运行确是好的。最后在服务器终端全局安装 node 可以解决这个问题:
apt-get install -y npm
到目前为止,博客的自动化部署完成了。每当我 push 改动到 Git 时,Travis 会被触发完成一系列的构建安装部署工作。