使用Travis CI自动部署Github/Coding Pages博客

使用Hexo生成静态博客然后部署到Github/Coding Pages是目前我的博客的托管方式。
用起来是很爽,但是存在几个问题:

  1. Hexo的环境配置太麻烦,麻烦到几乎换台电脑就不能更新博客了
  2. 每次修改文章之后都要重新生成一遍
  3. 再加上提交博客源文件的话执行命令的次数太多了(主要是第一步)

在提交博文的时候浪费了很多时间,我优化了一下流程几乎可以全自动提交更新了。

按照上面的步骤,就算部署的环境已经配置好,但是最基本的修改/同步一篇文章还要经历以下几步:

1
2
3
4
5
6
修改文章
执行hexo d -g
# 下面是同步博客源文件
git add .
git commit -m "commit message"
git push origin master

如果说写的文章有谬误的话更正之后上面几步都要重来一遍,浪费了很多时间。
幸好最近发现了持续集成这个6的没边的部署方式我觉得可以把我的博客也部署一下使其能够尽可能地简化这些步骤。

其思想主要就是:当我推送新文件(代码)到Github仓库时触发一系列动作。我们可以设定一系列的指令来当我们添加/修改.md文章之后自动执行hexo d -g指令生成并部署到Github/Coding Pages仓库。

持续集成的产品我选择的是Travis CI,使用Travis CI的原因在于可以无缝集成Github和Public仓库免费。另外,因为Travis CI只能从Github导入仓库,而且目前coding.net也不支持Token,所以我们没办法直接在Travis上push到coding.net的仓库,需要我们折腾一下私钥的问题,这个暂时按下不表。

首先,你目前有一个已经部署成功hexo的仓库

假如是git@github.com:hxhb/blog.git,gh-pages,而你的博客源文件则在git@github.com:hxhb/blog.git,master

第一,打开Travis CI使用你的github账号登陆进去。

0

点击红框中的+号,选择你博客所在的仓库。

如果没有显示,点击右上角的“Sync account”按钮,就可以同步过来了。

1

然后返回主界面,就会看到你的所选的库已经在列表中了。

我这是已经部署成功过得,所以会显示绿色对号。

2

打开设置开启Build only if .travis.yml is presentBuild pushes

3

4

这两个选项代表的含义是:

  • Build only if .travis.yml is present:是只有在.travis.yml文件中配置的分支改变了才构建。
  • Build pushes:当推送完这个分支后开始构建。

其基本思路就是在博客源程序所在的下创建一个.travis.yml自己写好配置文件,等你往这个分支push之后Travis CI会检测到该库变动然后按照.travis.yml文件中配置的命令来进行操作。

但是这里有一个问题,如果往Github推送或者Coding推送是需要ssh私钥的,但是我们在Travis CI中创建的私钥没办法放到Github/Coding ssh-key中。现在Github支持token-key了,可以不需要ssh-key也能推送了,但是如果你想要把博客部署到不同服务商的仓库(Github Pages/Coding Pages)这样还不是一个通用的办法。

所以我的思路是,既然总要生成私钥,那么我直接把我VPS上的ssh私钥上传到Travis CI上后不就可以顺利部署了(VPS上公钥已添加至Github/Coding ssh-key),但是这样哪里还有安全性....

幸好我发现可以先加密私钥后push到博客的源文仓库中,然后在travis CI上clone下来该仓库后对私钥加密后的文件再解密,然后自己执行hexo d -g操作,最后再删除私钥,这样就解决了部分安全性的问题(push到博客源文件的私钥是加密后的,就算是public仓库也能保证安全性,唯一有安全漏洞的是需要把你的私钥放到travis上,这个需要你自己保证你的travis(Github)账户是安全的...)。

首先,先在你可以部署hexo的VPS(Linux环境)上安装Ruby环境(根据环境选择):

1
2
3
4
5
6
# For Debian, and other distributions using Debian style packaging the ruby development headers are installed by:
$ sudo apt-get install ruby-dev
# For Ubuntu the ruby development headers are installed by:
$ sudo apt-get install ruby-all-dev
# If you are using a earlier version of ruby (such as 2.2), then you will need to run:
$ sudo apt-get install ruby2.2-dev

然后安装gemtravis客户端:

1
2
3
4
# install gem
$ apt-get install gem
# install travis
$ gem install travis

安装完后使用下面的命令登陆到travis中:

1
2
# travis-ci.org
$ travis login --auto

注:如果使用travis-ci.com,则需要使用命令travis login --pro.

然后会提示你输入账号密码,在这里要使用Github账号。

登陆上之后我们就可以将我们的私钥加密之后放到博客源文件仓库中供Travis CI之后部署时解密使用了。

1
2
# 加密私钥id_rsa,注意要指定你自己的私钥位置,顺便也指定下仓库-r ${Repo_Name}
$ travis encrypt-file ~/.ssh/id_rsa --add -r /hxhb/blog

此时,travis-ci中的hxhb/blog仓库的settings中就会看到创建了两个环境变量$encrypted_1fc90f464345_key$encrypted_1fc90f464345_iv,两个环境变量所定义的内容别人是看不到的,因此也就保证了我们私钥的安全。用来解密我们的私钥。
EnvironmentVariables
然后还会在当前目录下生成.travis.yml/id_rsa.enc这两个文件,其中id_rsa.enc使我们把私钥加密后得到的文件,.travis.yml中通过上面的指令会在里面添加解密id_rsa.enc的指令,形式如同下面这样(注意每个人的都不同,不能照抄我这段代码):

1
2
- openssl aes-256-cbc -K $encrypted_1fc90f464345_key -iv $encrypted_1fc90f464345_iv
-in .travis/id_rsa.enc -out ~/.ssh/id_rsa -d

这条命令利用openssl和上面所定义的两个环境变量来解密私钥,然后将解密后的私钥存放在~/.ssh/id_rsa中。

然后我们要在.travis.yml加上设置私钥的权限的指令,使之有权限可读:

1
- chmod 600 ~/.ssh/id_rsa

然后将该私钥添加至系统中:

1
2
- eval $(ssh-agent)
- ssh-add ~/.ssh/id_rsa

随后将id_rsa.enc移动至.travis中:

1
mv id_rsa.enc .travis

因为当我们通过SSH 连接远程主机时,会检查主机的公钥。如果是第一次该主机,会显示该主机的公钥摘要,提示用户是否信任该主机,但是,我们在travis-ci持续集成过程中是不能输入yes的...所以如果直接push就会在这里卡住,解决方案是禁用SSH远程主机的公钥检查。

.travis下新建一个ssh_config文件,将下面的内容填入其中:

1
2
3
4
Host *
StrictHostKeyChecking no
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes

意思就是对于所有的主机都禁用SSH远程主机的公钥检查并指定私钥地址为~/.ssh/is_rsa

在travis中我会将其覆盖掉travis的默认ssh_config(/etc/ssh/ssh_config)。

然后将.travis.travis.yml移动到博客源文件中,其目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.deploy_git
.git
.travis
node_modules
public
scaffolds
source
themes
.directory
.gitignore
.travis.yml
README.md
_config.yml
package.json

打开.travis.yml将下面代码块中的内容填入其中,注意解密代码要改为你自己的参数。
注意:node_js版本不要填stable,近期nodejs更新到了7.0,与hexo的插件有不兼容,最好还是不要写stable,因为在travis上是使用nvm来管理node版本的,所以我们可以直接指定版本号。为了防止不必要的问题,我建议填5.9.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
language: node_js
node_js: 5.9.1
install:
- npm install
- npm install hexo-cli -g
script:
- hexo g
- hexo d
- rm -rf ~/.ssh
branches:
only:
- master
before_install:
- openssl aes-256-cbc -K $encrypted_1fc90f464345_key -iv $encrypted_1fc90f464345_iv
-in .travis/id_rsa.enc -out ~/.ssh/id_rsa -d
- chmod 600 ~/.ssh/id_rsa
- sudo cp .travis/ssh_config /etc/ssh/ssh_config
- sudo chmod 755 /etc/ssh/ssh_config
- eval "$(ssh-agent -s)"
- ssh-add ~/.ssh/id_rsa
- git config --global user.name "userName"
- git config --global user.email "userName@gmail.com"

可以看到,就类似于一台Linux主机上可以执行的bash命令,首先执行install的部分,然后执行before_install的部分,然后再执行script部分。本质就是将部署博客到GithubPages/CodingPages的环境在travis-ci上现搭一个并执行hexo d -g操作。

然后就可以将博客源文件推送到github仓库了(注意是博客源文件不是hexo g生成的public文件夹中的文件)

1
2
3
4
$ git add .
$ git commit -m "add travis-ci"
$ git push origin master
# git@github.com:hxhb/blog.git,master

推送完毕之后打开travis-ci页面登陆进去就会看到它自己在后台部署了。

5

等部署成功之后去你GithubPages仓库看提交成功了没有或者等你的博客页面刷新,如果travis-ci报错,请认真核对下上面的流程。

我的_config.yml中写了两个仓库,hexo d时会推送到这两个仓库中(原本travis-ci只支持Github仓库)。

7

现在,更新博客文章只需要往博客源仓库(分支)推送.md的文章就行了,travis-ci会检测到更新然后持续集成自动部署更新我们的博客。

可能遇到的问题

最可能遇到的还是私钥/部署时的公钥检查的问题,注意在travis-ci中替换ssh_config之后一定要设置权限(我上面设置的是755),不然push时还是会检查公钥。

注意使用hexo d -g之前也一定要设置git全局变量user和email,不然hexo -d会提示你who are you?

1
2
- git config --global user.name "userName"
- git config --global user.email "userName@gmail.com"

仓库目录和配置文件具体可以参照我的博客源文件库(master分支)。travis-ci的配置主要依赖于.travis目录里的文件和.travis.yml文件。

6

后记
目前我博客的部署方式已经非常方便了,而且再也不需要自己手动生成并推送了。
我使用Dropbox同步了博客的源文件并同时部署在了VPS和我的电脑上,这样我每次在本地修改或添加文章之后就会立即同步到VPS上,我又写了一个shell脚本并添加至.bashrcalias,使用Xshell或者juiceSSH(Android)或者也可以使用Putty中的plink一键就可以登录到VPS上,只需要输入一条命令就会自动推送更新到我的Github上了(使用Xshell的快速指令集或者使用plink自动链接执行命令的脚本则一个字都不用输,点一下就执行了),而travis-ci则一直在监控我的Blog仓库,发现提交之后立即生成并推送至gh-pages分支。
现在的步骤就只是:

  1. 添加/修改文章(本地修改,通过dropbox会立即同步到VPS上)
  2. 执行自动提交脚本(在windows上启动plink快速连接到VPS并执行命令的脚本)

其实也可以写个程序让它运行在VPS上自动检测文章目录的变动然后执行快速提交的命令。这样就可以全自动化了。但是这样你就是修改一个字也会执行整个流程造成commit污染,等以后实在是懒了就这么搞吧...
后记:使用plink可以自动登录到VPS上并执行命令,真正实现一条指令都不需要输了,现有快速提交脚本如下:

1
2
3
4
5
# save to ~/blog
#!/usr/bin/env bash
git add .
git commit -m "quickly submit"
git push origin master

然后按照下面的语法执行就会执行时自动连接VPS并快速提交了:

1
2
3
plink -pw ${server-username-password} ${username@Host} -P ${portNum} "${order}"
# 连接到root@192.168.1.111上并执行快速提交命令
# plink -pw 123456abc root@192.168.1.111 -P 1111 "cd ~/blog&&sh ~/blog/quicklypush.sh"

plink也可以使用秘钥登陆的,但是plink需要使用puttygen生成的ppk私钥,因此我们需要把ssh的私钥使用puttygen打开然后另存为ppk私钥即可。
plink使用私钥自动登陆指令如下:

1
2
plink -i ${KeyPath}\puttygen.ppk ${username@Host} -P ${portNum} "${order}"
# plink -i C:\Users\visionsmile\.ssh\puttygen.ppk root@192.168.1.111 -P 1111 "cd ~/blog&&sh ~/blog/quicklypush.sh"

从而实现免密登陆的效果。

参考文章
用 Travis CI 自動部署網站到 GitHub
Travis CI Push 权限配置
教你使用Travis CI自动部署你的Hexo博客到Github上
禁用SSH远程主机的公钥检查

全文完,若有不足之处请评论指正。

扫描二维码,分享此文章

本文标题:使用Travis CI自动部署Github/Coding Pages博客
文章作者:ZhaLiPeng
发布时间:2016年10月21日 06时36分
本文字数:本文一共有3,108字
原始链接:https://imzlp.me/posts/42318/
许可协议: CC BY-NC-SA 4.0
转载请保留原文链接及作者信息,谢谢!
您的捐赠将鼓励我继续创作!