自动更新 hugo 博客

原本我个人博客的更新流程是:

  1. 编写 org 文章,将 org-roam dailies 更 org-roam 的节点结合,同时管理任务和文档
  2. 利用 ox-hugo 将文章导出为 md 文件,导出到 blog/content/ 路径下
  3. blog 推送到 GitHub 上
  4. 腾讯云拉取项目,执行 hugo 命令生成静态资源

这套流程最大的问题是需要远程到云上,然后通过手工拉取代码,再执行编译的命令,才能更新博客的资源,但其它推送、拉取、编译的过程是可以能过自动化的脚本来处理的。

为了简化这个流程,利用 GitHub Webhook 功能来做推送请求的响应,当有新的推送时,就自动执行拉取和编译。

webhook 触发脚本

触发的思路是利用脚本,启动一个 https://xxxxx/webhook 链接,然后通过链接执行对应的命令来更新博客。

JavaScript 的触发脚本

需要在服务器上安装 nodejs、npm 命令,并且安装 github-webhook-handler 模块。

  1. 在模块中指定 Webhook 的密钥(与 GitHub 配置的密钥一致)和响应的地址

  2. 指定触发的模式,我这里是在 push 的时候触发

    var http = require('http')
    var exec = require('child_process').exec
    var createHandler = require('github-webhook-handler')
    var handler = createHandler({ path: '/webhook', secret: 'github_secret' })
    
    http.createServer(function (req, res) {
        handler(req, res, function (err) {
            res.statusCode = 404
            res.end('no such location')
        })
    }).listen(7777)
    
    handler.on('push', function (event) {
        let currentTime = new Date();
        console.log('\n --> ' + currentTime.toLocaleString());
        console.log('Recieved a push event for %s to %s',
                    event.payload.repository.name,
                    event.payload.ref);
        exec('sh ./webhook/git_pull.sh', function (error, stdout, stderr) {
            if(error) {
                console.error ('error:\n' + error);
                return;
            }
            console.log('stdout:\n' + stdout);
            console.log('stderr:\n' + stderr);
        });
    })
    
  3. 拉取和编译脚本

    这个脚本就是触发链接中的 git_pull.sh 脚本,是在有 git push 请求之后,可以自动执行下面的命令来更新项目。

    git pull origin main
    hugo
    exit 0
    
  4. 配置 nginx 的服务

    这里 alias 的路径是指向的脚本所有路径,而 proxy_pass 的链接是指的内部的地址,上面脚本使用的是 7777 端口,这里重新影射成 http://xxx.xx/webhook

    location /webhook {
        alias /root/webhook;
        proxy_pass http://127.0.0.1:7777;
    }
    
  5. webhook 监控

    打开对应项目的设置,找到 webhook 的内容,选择新增,将对应网页地址填写到 payload url 中,填写密钥,选择 Content type 为 json 。

完成配置后就可以在推送交易时自动更新项目了。

主题更新触发更新

我的博客使用的是 hugo-theme-next 的主题,增加了一些内容,所以使用的也是需要重新生成博客的。

这里主要是使用 git module 来管理主题,所以每次主题更新,其实是会更新一下主题的对应的版本号,所以修改上面的 shell 脚本如下:

git pull origin main
git submodule foreach git pull
hugo
exit 0

这样就可以两步更新子项目的内容了,同样的方案,可以处理多个子项目合并的编译情况。