Context
本站用 Hugo 生成器与 PaperMod 主题构建。两者任一未跟踪的升级都可能静默改变输出:主题的模板、生成器的渲染规则,或两者都可能改变两次"相同"重建之间的 HTML 字节。当发布用字节清单证明时,可复现不是可有可无;同一份源码的两次构建必须产生同一棵树。
Decision
把主题纳入仓库,并把确切的生成器版本与主题版本记录在钉住文件 data/upstream-pins.toml。构建流水线读取该文件,若安装的生成器与钉住版本不符则失败。
Hugo 0.165.0
PaperMod v8.0
data/upstream-pins.toml (钉住)
被纳管的主题放在 themes/ 目录下,作为提交的一部分,因此也成为一次发布字节身份的一部分。
后果
- 可复现输出: 相同源码加上钉住的生成器得到相同树,使清单有意义。
- 升级可见: 升主题或生成器是对钉钉文件的显式、可审的改变,而非意外漂移。
- 来源可审计: 任何一次发布的读者都能看到是哪个生成器与主题产生了这些字节。
- 接受的取舍: 仓库带上 vendored 主题与钉住簿记;相比静默的输出漂移,这个代价很小。
为什么它胜出
输入未钉住的构建,今天可能给正确的答案,明天却给出不同的树,而 diff 与清单都无法告诉你为什么。钉住把"构建变了"变成"钉住变了",而这是一个 changelog 真正能回答的问题。
来源
- Hugo 文档:版本,报告并匹配生成器发布版,已核验 2026-08-21。
- 语义化版本规范,为什么版本边界让可复现有意义,已核验 2026-08-21。