Hexo博客云端写作,一键部署

前面我们已经使用Travis CI实现了自动部署,使我们不必每次在新的电脑上进行写作时,都需要重新搭建Hexo的环境,我们只需要把博客的源代码clone下来,然后把我们的文章加进去,push到远程仓库,Travis CI就能执行构建自动帮我们博客发不出去。可是这样每次都要拉取源代码然后push上去,还是显得有点麻烦。有没有什么办法能让我们把注意力只放在写博客上,其余的工作都交给其他人或者让它们自动化完成了,答案是有的。

一句话就是:

Hexo + Github + 语雀 + yuque-hexo + travis-ci + serverless打造全自动持续集成个人博客,云端写作,一键部署

1. 整体流程

  • 在语雀上在线编辑一篇文档
  • 使用语雀提供的webhook调用配置的serverless函数服务
  • serverless服务发起请求trigger一个build任务
  • travis ci使用yuque-hexo同步语雀文章并构建部署hexo
  • github博客文件展示

如图所示:

2. 具体实现步骤

1. yuque-hexo同步语雀文档

yuque-hexo是一个开源库:https://github.com/x-cold/yuque-hexo
使用方法很简单,我们只需要简单地修改一下配置文件即可。
1)修改package.json文件,增加如下配置

1
2
3
4
5
6
7
8
9
10
11
12
13
"yuqueConfig": {
"baseUrl": "https://www.yuque.com/api/v2",
# login填写的是你的语雀账户个人路径,可在设置-账户管理-个人路径查到,就是u+一串数字
"login": "u164819",
# repo填写的是你的语雀仓库路径,进入仓库,可通过URL看到
"repo": "zq4z0b",
"mdNameFormat": "title",
"postPath": "source/_posts/yuque",
"cachePath": "yuque.json",
"adapter": "hexo",
"concurrency": 5,
"onlyPublished": false
}

2)package.json增加命令:

1
2
3
4
5
6
7
8
9
"scripts": {
"clean": "hexo clean",
"clean:yuque": "yuque-hexo clean",
"deploy": "yuque-hexo sync && hexo deploy",
"publish": "npm run clean && npm run deploy",
"dev": "hexo s",
"sync": "yuque-hexo sync",
"reset": "npm run clean:yuque && npm run sync"
}

可参考我的package.json文件。
3)修改.travis.yml文件,增加如下两条命令

npm i -g yuque-hexo
yuque-hexo sync

可参考我的travis.yml文件。

2. 配置serverless

目前阿里云和腾讯云都有提供serverless服务,而且有一定的免费额度使用,对于我们个人博客的日常使用是完全足够的。下面介绍一下如何配置。
1)创建函数
这里我使用的是腾讯云的无服务器云函数,注册登录腾讯云,进入无服务器云函数的控制台,在概览页,可看到你账户下拥有的函数统计信息,点击函数服务,在这里可以新建函数服务,如图:

函数配置:
image.png
可在线配置函数,函数配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<?php
function main_handler($event, $context) {
// 解析语雀post的数据
$update_title = '';
if($event->body){
$yuque_data= json_decode($event->body);
$update_title .= $yuque_data->data->title;
}
// default params
$repos = 'xxxx'; // 你的仓库id 或 slug
$token = 'xxxxxx'; // 你的登录token
$message = date("Y/m/d").':yuque update:'.$update_title;
$branch = 'master';
// post params
$queryString = $event->queryString;
$q_token = $queryString->token ? $queryString->token : $token;
$q_repos = $queryString->repos ? $queryString->repos : $repos;
$q_message = $queryString->message ? $queryString->message : $message;
$q_branch = $queryString->branch ? $queryString->branch : 'master';
echo($q_token);
echo('===');
echo ($q_repos);
echo ('===');
echo ($q_message);
echo ('===');
echo ($q_branch);
echo ('===');
//request travis ci
$res_info = triggerTravisCI($q_repos, $q_token, $q_message, $q_branch);

$res_code = 0;
$res_message = '未知';
if($res_info['http_code']){
$res_code = $res_info['http_code'];
switch($res_info['http_code']){
case 200:
case 202:
$res_message = 'success';
break;
default:
$res_message = 'faild';
break;
}
}
$res = array(
'status'=>$res_code,
'message'=>$res_message
);
return $res;
}

/*
* @description travis api , trigger a build
* @param $repos string 仓库ID、slug
* @param $token string 登录验证token
* @param $message string 触发信息
* @param $branch string 分支
* @return $info array 回包信息
*/
function triggerTravisCI ($repos, $token, $message='yuque update', $branch='master') {
//初始化
$curl = curl_init();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, 'https://api.travis-ci.org/repo/'.$repos.'/requests');
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//设置post方式提交
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
//设置post数据
$post_data = json_encode(array(
"request"=> array(
"message"=>$message,
"branch"=>$branch
)
));
$header = array(
'Content-Type: application/json',
'Travis-API-Version: 3',
'Authorization:token '.$token,
'Content-Length:' . strlen($post_data)
);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
//执行命令
$data = curl_exec($curl);
$info = curl_getinfo($curl);
//关闭URL请求
curl_close($curl);
return $info;
}
?>

函数中有几个参数需要我们按照自己的填进去:

  1. 仓库id和slug,需要我们调用官方的API接口查询。使用findder或者postman发送GET请求:https://api.travis-ci.org/owner/travis用户名/repos,请求的返回体中可获取到ID和slug。如图


上面图中Authorization的token,可以从你的travis账户中的设置里面取到。同时这个token要填到上面函数中的相应位置。
2)配置触发方式
如图:

得到一条访问路径。

3. 语雀webhook配置

在知识库的设置中的开发者设置中,新建一条webhook,将上面得到的路径填入其中。可以选择所有更新触发或者主动触发,主动触发的意思即发布需要勾选一个选项才会触发webhook。具体可参见语雀文档:https://www.yuque.com/yuque/developer/doc-webhook
可以在上述路径后面填上参数:

token 登录token
repos 仓库id
message 提交信息
branch 分支

也可不加,直接从serverless函数中获取。

4. 开始发布或者更新一篇文章

发布或者更新一篇文章后,我们可以看到serverless函数被调用,如图:

image.png
这里有一点要注意的是函数默认配置的超时时间是3秒,但是实际运行时间可能会超过3秒导致调用失败,所以,我们需要将超时时间适当调大一些,当然内存也可以适当调大一些。
然后,我们可以在travis-ci中看到已经出发了构建请求,如图:

大功告成,我们以后就可以在语雀上写博文,然后同步到自己的博客网站上。
最后,还有一点需要注意的是,语雀编辑器和hexo的文档格式略有不同,yuque-hexo的作者做了兼容处理,我们需要将markdown文档头改为:

date: 2015-04-18 00:00:00
tags: [css]
categories: CSS


注意,最后一行的分割线不能少。

参考文档:

  1. Hexo 博客终极玩法:云端写作,自动部署