2026.10.07 · 3 分钟阅读
博客发布工作流
目录
发布博客的工作流思路:
编辑 Markdown,提交源码
↓
推送到本地 Gitea
↓
本地 Runner 自动构建 Hugo
↓
Wrangler 上传 public/ 到 Cloudflare Pages
↓
Blog Web
先从日志定位耗时
最初工作流在每次任务中准备 Node.js、下载 Hugo,并通过 npx --yes wrangler@4 上传网站。一次成功部署的步骤耗时如下:
| 步骤 | 耗时 |
|---|---|
| 准备任务容器 | 2 秒 |
| 拉取源码 | 不足 1 秒 |
| 准备 Node.js | 1 秒 |
| 安装 Hugo Extended | 5 秒 |
| Hugo 构建 | 不足 1 秒 |
| 安装 Wrangler 并部署 | 1 分 41 秒 |
展开部署日志后,关键结果是:
Uploaded 11 files (64 already uploaded) (7.33 sec)
这说明本次部署共检查 75 个文件,其中 64 个已经存在,只上传了 11 个文件。Hugo 每次生成完整网站,Cloudflare 上传阶段则复用内容相同的资源。修改一篇文章还可能影响首页、分页、RSS 和站点地图,因此变动文件数量不一定等于修改的文章数量。
真正的文件上传只用了 7.33 秒。部署步骤剩余的时间还包括 Wrangler 下载与启动、接口请求和创建部署。由于当时日志没有逐行时间戳,不能把剩余时间全部归因于 npm 安装。
Hugo 构建已经很快,因此继续保留全量构建,确保文章删除、分页和索引都能同步更新。
第一次优化:固定版本并尝试缓存
先把 Wrangler 固定到已验证的 4.148.0,将安装和发布拆成独立步骤,再使用 Actions 缓存保存 .ci-tools 中的安装结果。预期是首次下载,后续恢复缓存并跳过安装。
实际运行时,缓存恢复和保存都出现了连接超时:
Failed to restore: getCacheEntry failed: Request timeout
Failed to save: reserveCache failed: Request timeout
恢复缓存耗时约 20 秒,任务结束时保存缓存又等待了约 1 分钟。缓存没有带来提速,反而增加了等待时间。
Docker Runner 与它创建的任务容器可能位于不同网络。缓存服务需要被任务容器访问,必须配合检查 cache.host、cache.port 和端口映射。只在工作流里添加缓存步骤,并不能保证缓存可用。
这次配置尚未确定具体网络阻断点,因此先移除了缓存。continue-on-error 可以让失败步骤继续执行,但不能消除连接超时,也不能阻止缓存 Action 在任务结束时尝试保存。
第二次优化:预装构建工具
将重复安装移到镜像构建阶段,制作专用于博客发布的镜像:
| 工具 | 版本 |
|---|---|
| 基础镜像 | node:22-bookworm-slim |
| Hugo Extended | 0.167.0 |
| Wrangler | 4.148.0 |
Dockerfile 同时安装 Git、curl 和证书等工具,下载 Hugo 后校验 SHA-256。镜像不包含博客文章或发布凭据;Cloudflare Token 仍由 Gitea Secrets 在部署步骤注入。
在 Runner 所在的 Debian 虚拟机上准备 Dockerfile,并在其目录中执行:
docker build --pull \
-t meshnook-blog-builder:hugo0.167.0-wrangler4.148.0-node22 .
构建完成后验证工具:
docker run --rm \
meshnook-blog-builder:hugo0.167.0-wrangler4.148.0-node22 \
bash -c 'node --version && hugo version && WRANGLER_SEND_METRICS=false wrangler --version'
Runner 挂载宿主机的 /var/run/docker.sock,所以任务使用的是宿主机 Docker。镜像构建在同一台 Debian 上后,Runner 可以直接使用,无需上传镜像仓库,也无需在 Compose 中增加一个长期运行的构建服务。
在现有 Runner 的 Compose 配置中增加专用标签:
GITEA_RUNNER_LABELS: "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest,meshnook-blog:docker://meshnook-blog-builder:hugo0.167.0-wrangler4.148.0-node22"
重新创建 Runner,让环境变量生效:
docker compose up -d --force-recreate runner
确认 Gitea 页面显示 meshnook-blog 标签后,将工作流设置为:
runs-on: meshnook-blog
本地镜像要求 Runner 的 container.force_pull 为 false。清理 Docker 镜像时也要保留这个镜像,否则任务会尝试从远程拉取一个未发布的镜像。
优化后的发布流程
准备阶段:构建工具镜像 → 配置 Runner 标签
↓
日常发帖:编辑 Markdown → 推送 main
↓
启动预装工具的任务容器
↓
拉取源码 → Hugo 全量构建
↓
Wrangler 检查并上传变动资源
↓
Cloudflare Pages 创建部署
新版工作流保留工具版本检查、Hugo 构建和 Cloudflare 发布,移除了每次任务中的工具安装和不可用的缓存步骤。
预期收益是省去重复下载与安装。镜像第一次构建仍需要网络,日常发布也仍需要访问 Gitea、Action 来源和 Cloudflare。优化后的实际总耗时还需以新的 Actions 日志为准,目前没有记录可对比的最终测量结果。
后续升级工具时,重新构建并使用新的镜像标签,同时更新 Runner 标签。这样工具准备与文章发布分开维护,日常发帖只需要提交并推送内容。