Hexo博客使用Github_Webhook自动部署到个人服务器

最近想把之前写的博客重新注册一个域名放到网上,地址:https://luoluoqinghuan.cn/
。博客框架使用的是hexo,部署到服务器上也很简单,把hexo生成的网站文件放在服务器上,用koa-static起一个服务就行了。

但这是一种非常麻烦的部署方式,每次更新博客都要登陆服务器手动上传,如果想要自动更新网站就要解决两个问题:

  • 从哪里拿到最新的代码(github)
  • 如何知道代码已经更新(github-webhook)

What Is Webhook

webhook是github提供的一个钩子,这个钩子在触发github一些事件后,会向配置好的地址发一个http请求。在任何一个仓库 -> Setting -> Webhooks 可以进行配置。我们可以在服务器上监听这个请求,就可以知道更新网站的时机了。

github提供的事件非常丰富,有20多种,几乎覆盖了所有git相关的操作,比如打了个tag、新建了branch、有新的commit等。
image.png

了解到这里,我们就知道如何去自动部署我们的博客网站了,首先将博客源码推到github上,并配置webhook,针对push事件进行监听,在个人服务器上另起一个服务,接收webhook的请求,收到请求后拉取最新代码并重新构建,done!

实现-web服务

我们有两个服务,一个是网站服务,一个是webhook监听服务。咱们一个一个来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 网站服务 hexo_server.js
const serve = require('koa-static');
const Koa = require('koa');
const app = new Koa();

const fs = require('fs')
const http = require('http')
const https = require('https')
const enforceHttps = require('koa-sslify').default

app.use(enforceHttps())
app.use(serve('public'));

const options = {
key: fs.readFileSync('./ssl/luoluoqinghuan.cn.key'),
cert: fs.readFileSync('./ssl/luoluoqinghuan.cn.pem')
}

http.createServer(app.callback()).listen(80);
https.createServer(options, app.callback()).listen(443)
console.log('listening on port 80 443');

直接使用koa-static这个中间件,很容易就可以将网站跑起来,我还在腾讯云申请了免费的证书,这样网站就可以支持https了,虽然一个简单的静态网站好像不需要https,但使用https可以帮助博客在搜索引擎中的排名更高一些。

实现-webhook服务

首先要在博客仓库里配置webhook

image.png

在payloadUrl中填入你服务器的地址,webhook的http请求会发向该地址,secret是密码,webhook会在请求头中使用此密码生成哈希值,供我们鉴权使用,events我们选第一个就可以了,我们在本地写完文章,push上去,触发webhook回调,点击add就添加成功了

接下来就可以写一下服务了。

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
// webhook服务 webhook_server.js
const Koa = require('koa');
const app = new Koa();
const child_process = require('child_process')
const crypto = require('crypto')
const bodyParser = require('koa-bodyparser')

const sigHeaderName = 'x-hub-signature-256'
const sigHashAlg = 'sha256'

app.use(bodyParser())

const secret = '123456'

const main = ctx => {
// 鉴权
const sig = Buffer.from(ctx.request.headers[`${sigHeaderName}`] || '', 'utf8')
const hmac = crypto.createHmac(sigHashAlg, secret)
const digest = Buffer.from(sigHashAlg + '=' + hmac.update(ctx.request.rawBody).digest('hex'), 'utf8')
if (sig.length !== digest.length || !crypto.timingSafeEqual(digest, sig)) {
console.log(`Request body digest (${digest}) did not match ${sigHeaderName} (${sig})`)
ctx.status = 403
return
}

console.log('start cmd')
// 拉取最新代码
const cmd = 'git checkout . && git pull'

try{
const log = child_process.spawnSync(cmd, {shell: true})
console.log(log.stdout.toString())
}catch(e){
console.error(e.toString())
const response = {code: 500, message: 'update failed'}
ctx.response.body = response
ctx.status = 500
return;
}

// build网站
const cmd1 = 'hexo clean && hexo generate'
try{
const log1 = child_process.spawnSync(cmd1, {shell: true})
console.log(log1.stdout.toString())
console.log('hexo blog update successed !!!!')
const response = {code: 200, message: 'update successfully'}
ctx.response.body = response
ctx.status = 200
return;
}catch(e){
console.log(e.toString())
console.log('hexo blog update failed !!!!')
const response = {code: 500, message: 'failed'}
ctx.response.body = response
ctx.status = 500
return;
}
}
app.use(main);
app.listen(3000);
console.log('github hook server listen at port 3000')

这样,我们的监听服务就搞定了,跑起来(推荐使用pm2),写一下文章,然后push一下,可以看到我们自动部署服务成功了。最新的文章也出现在了网站上。

image.png


Hexo博客使用Github_Webhook自动部署到个人服务器
https://luoluoqinghuan.cn/2022/02/10/Hexo博客使用Github自动部署到个人服务器/
作者
David Mu
发布于
2022年2月10日
许可协议