最近想把之前写的博客重新注册一个域名放到网上,地址: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等。

了解到这里,我们就知道如何去自动部署我们的博客网站了,首先将博客源码推到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
| 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

在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
| 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; }
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一下,可以看到我们自动部署服务成功了。最新的文章也出现在了网站上。
