这两天我把博客的发布链路重新理了一遍,目标其实很朴素:我在 Windows 本地改完代码,只 push 一次,GitHub Pages 能更新,www.june6699.top 也能跟着更新。

之前的问题不复杂,就是链路断过几次。页面看起来像是“没同步”,其实不是代码没发出去,而是两边发布的方式没有统一起来。

先定一条原则

我最后只保留一份源码,一份构建产物。

源码还是老规矩,本地改,push 到 GitHub。真正上线的时候,不再分开维护两套内容,而是让 Hugo 先构建出同一份 public/,然后:

  1. GitHub Pages 用这份 public/
  2. 服务器上的 top 域名也同步这份 public/

这样就不会出现“GitHub 站已经新了,top 还停在旧页面”的情况。

现在这条链路长什么样

我现在的流程是这样的:

Windows 本地改代码
-> push 到 GitHub main
-> GitHub Actions 跑 Hugo 构建
-> 生成同一份 public/
-> 发布到 GitHub Pages
-> 再用 SSH rsync 到 june-server
-> www.june6699.top 读取服务器上的 public/

这里最关键的一点是:top 域名不是单独再做一套部署逻辑,它只是跟着那份 public/ 走。

为什么这样最稳

因为“同步”这件事,最怕的不是慢,是分叉。

如果 GitHub Pages 一套构建,服务器上又手动拷一套文件,时间一长就会开始出现这些毛病:

  • 文章顺序不一致
  • 某篇文章只在一个域名上可见
  • 图片路径偶尔失效
  • 你自己也记不清到底哪边是最新

我不想再给自己留这个坑,所以干脆把部署出口收拢成一份构建结果。

GitHub Actions 里做了什么

仓库里的工作流现在会在 main 分支 push 后自动跑:

  • checkout 代码
  • 安装 Hugo
  • npm run build
  • 把生成的 public/ 上传给 GitHub Pages
  • 再把同一份 public/ 发到服务器

这一步里,GitHub Pages 和服务器同步用的是同一个 artifact。也就是说,只要这次构建成功,两边看到的内容理论上就是同一批。

服务器那边只做一件事

服务器不再自己维护仓库,也不再自己改源码。

它只负责接收同步结果,然后对外提供 www.june6699.top。这样服务器就退回成一个很干净的角色:被同步者,不是编辑者。

这点我挺喜欢,省心。

动态密钥怎么放

站里还有一块动态内容,访问时要走 GitHub 的环境变量去做验证。

我没有把这类密钥写死在仓库里,而是继续放在 GitHub Secrets 里,让构建和运行时按需读取。这样有两个好处:

  1. 密钥不进代码仓库
  2. 本地、GitHub Pages、服务器这三边的发布逻辑不会互相污染

也就是说,内容可以同步,密钥不要同步到明面上。

我现在怎么判断同步没问题

我不再只看首页。

首页有缓存,视觉上很容易骗人。真要确认同步,我会直接看最新文章、列表页和实际发布后的文件内容。只要这几处都一致,基本就说明两边已经在吃同一份结果了。

后来我又把服务器上的 nginx 配了一遍,top 域名能正常访问以后,这条链路才算真正闭上。

这次顺手学到的一点

网站部署最容易出的问题,往往不是“大故障”,而是“某一步看起来没什么,但实际上链路已经分叉了”。

所以这次我最后做的不是更复杂的系统,而是更简单的约束:

  • 源码只维护一份
  • 构建只产出一份
  • 发布只认同一个 public/

这样一来,GitHub Pages 和 www.june6699.top 就能老老实实地一起更新。