Hexo的自动构建与发布

Hexo简介

Hexo是一个基于Node.js的快速、简洁且高效的博客框架,自从2015年开始,我就把blog迁移到了Hexo,使用两年有余,发觉再也回不去Wordpress了。Hexo通过Markdown来记录每一篇blog日志,非常方便的通过Git来进行版本控制(这对于程序员来说,是再爽不过的事情了),而且能够构建出完全静态的blog页面,不用依赖于任何的数据库,以及动态的脚本语言,只需要一个简单的HTTP Server,比如用 Caddy Server 就能够host起来,非常的方便。

基于Hexo自动构建与发布流程

Hexo在每发布一篇blog文章过后,需要重新构建一次,然后再发布,这种过程稍显繁琐,那么,能不能把这一过程自动化呢?当然可以!

我们可以使用日常来自动构建软件项目的经验,来自动构建和发布基于Hexo的blog。之前写过一篇《Octopress的自动生成与部署》,看起来稍显麻烦。其实,构建Hexo的过程大同小异,这一次,我会尽量把自动化的构建过程再简化一些。

Hexo的自动构建与发布过程大致如下:

1
2
3
新建Markdown日志->Git仓库: git push
Git仓库->构建服务器: webhook事件通知
构建服务器->HTTP服务器: 构建与发布

将Blog使用一个远程Git仓库管理起来,充分利用Git的版本管理特性,对每一篇Blog进行版本控制。每次新建或者更新一篇Blog后,都将改动push到远程Git仓库中。在Git仓库中,设置webhook通知地址,指向构建服务器提供的接口,这样,每次对blog的改动,都能触发构建服务器进行一次新的构建和发布流程。在构建服务器上,配置好HTTP服务器的访问权限,这样,每次构建出来的静态blog,都能自动发布到HTTP服务器上。这个HTTP服务器,其实也就是最终host你的blog的服务器了。

开始搭建

理解了这样的流程和原理,我们就直接开始搭建吧…… 还记得哥之前的那个Gen8服务器么,这台服务器,主要是放在家里下载高清电影的,这次,打算把它充分利用一下,也用来作为我的Hexo blog的构建服务器。

构建环境准备

首先,需要在这台构建服务器上,clone一下blog的Git仓库,并且需要配置构建环境,安装对应版本的node,以及构建blog所需要的所有node modules。这台构建服务器,可以是家中的某个机器,也可以是一台在公网中可以访问的VPS,不过构建Hexo的blog,对内存有一些要求,尤其是在blog日志数量够多的情况下,VPS的内存如果过低,会在构建过程中,引起构建进程被kill掉的情况。

最后,准备好构建环境之后,可以先试试hexo generate,如果能成功构建出blog并没有任何错误,表明构建服务器的环境已经配置好了。

监听webhook事件

接下来,如何让构建服务器能够接受到来自远程Git仓库的webhook通知呢?我们需要一个工具:webhook,这是一个基于Go实现的webhook处理工具,它能够在某个端口监听webhook通知消息,并根据设置,执行指定的脚本和命令。webhook的安装也很方便,直接在releases中,下载编译好的可执行文件即可。

webhook的运行,还需要一个hooks.json配置文件,大致指定了hook的id,以及收到webhook通知后需要执行的脚本,这里给出一个参考:

1
2
3
4
5
6
7
[
{
"id": "blog",
"execute-command": "/home/timothy/xiaozhou/build.sh",
"command-working-directory": "/home/timothy/xiaozhou"
}
]

配置文件中,指定了一个hook的id叫blog,执行的命令,指向了blog目录下的一个叫build.sh的脚本,并且把执行脚本时候的工作目录,也指向了我blog的目录,嗯,就这么简单!

接下来,直接运行webhook:

1
2
3
4
5
6
7
8
→ ./webhook -hooks hooks.json -verbose
[webhook] 2017/12/17 20:22:47 version 2.6.7 starting
[webhook] 2017/12/17 20:22:47 setting up os signal watcher
[webhook] 2017/12/17 20:22:47 attempting to load hooks from hooks.json
[webhook] 2017/12/17 20:22:47 found 1 hook(s) in file
[webhook] 2017/12/17 20:22:47 loaded: blog
[webhook] 2017/12/17 20:22:47 serving hooks on http://0.0.0.0:9000/hooks/{id}
[webhook] 2017/12/17 20:22:47 os signal watcher ready

从输出可以看到,webhook已经加载了一个叫blog的hook配置,默认情况下,webhook会监听9000端口。这样,webhook也准备好了。

通过http://0.0.0.0:9000/hooks/blog就可以访问到我们所配置的webhook处理程序了。

Tips: 如果想让webhook在后台持续运行,可以考虑nohup方式,或者用supervisor/upstart/systemd。

编辑构建脚本

构建脚本,也即webhook程序收到webhook通知过后,需要执行的一些命令,在这里,也就是专门用来构建和发布blog的命令,下面提供我的构建脚本

作为参考:
1
2
3
4
5
6
7

```bash
#!/bin/bash

rm -rf build.log
git pull origin master | tee /home/timothy/xiaozhou/build.log
hexo g --deploy 2>&1 | tee /home/timothy/xiaozhou/build.log

构建脚本需要做的事情,跟我们平时手动构建Hexo的过程差不多,pull最新的改动,hexo生成blog并发布。在这里,把构建命令的输出重定向到了一个build.log中,用于追踪构建过程…… 另外,我的blog配置为rsync方式发布,所以,需要确保构建服务器能通过SSH证书认证的方式,免密码的登录blog所在的服务器。

关于端口映射与DDNS

由于这台服务器,是在我家中的一台服务器运行,需要外网能够访问到它,所以,需要在路由器上,把9000端口映射出去。那如果家中的宽带,IP地址不固定怎么办呢?嗯,你还需要一个域名和一个类似于DDNS能实现动态解析的工具,比如:GoDNS。如果你的构建服务器,是公网的一台VPS,有固定的公网IP,可以直接跳过DDNS这部分设置内容……

Git仓库相关设置

好了,省去DDNS设置的过程,现在,在路由器也做好了映射,并且,可以通过我自己的域名:ci.xiaozhou.net来访问到我家中的这台Gen8服务器了,我们可以直接去远程Git仓库设置webhook了。

结合之前我们设置的webhook处理程序,我们暴露在公网可以访问到的webhook处理程序地址为:

http://ci.xiaozhou.net:9000/hooks/blog

我的blog的git仓库是放在bitbucket.org的,因此,可以在项目的设置中,做一些如下设置:

  • 设置blog项目的access key,将构建服务器的SSH public key,添加到项目中,让构建服务器有权限可以访问到blog所属的git仓库:

  • 设置构建服务器所监听的webhook地址,让git仓库的改动,能通过webhook的方式,通知到家中的构建服务器:

自动构建测试

万事俱备,只欠东风,这里的东风,也就是我们对blog的这个git仓库的操作了,比如新建一篇blog,提交,并push过去,后续一系列的自动构建过程就会自动开始执行了,并且,可以在构建服务器上的build.log看到完整的构建过程和日志。

实现这样自动构建的好处在于,将blog构建与发布的过程自动化,我们所需要做的,只是专注于编辑blog和提交给git仓库,后续的过程,让机器来帮助你实现吧。也许,只需要喝几口咖啡的功夫,构建服务器就会为你自动构建blog并发布就行了。

另外,告诉你一个小秘密:此篇blog基于Hexo自动构建与发布的方式生成 :-)

支持原创技术分享,据说打赏我的人,都找到了女朋友!