Moby 项目发布流程深度解析:九周发布周期、代码冻结与 RC 候选版本机制
本文以 project/RELEASE-PROCESS.md 为核心,完整解析 Moby(Docker 引擎的开源项目)的发布流程:九周时间盒式的发布周期、第 6 周开始的代码冻结(freeze)与 Release Candidate(RC)机制、冻结期内 master 与 RC 的并行演进策略,以及补丁发布的分支/回移(backport)配套规则。读完本文后,你将能够判断一个改动"还能不能赶上本次发布",理解 docker-vX.Y.Z 标签、docker-MAJOR.x 发布分支与 releases/versions.yaml 之间的协作关系,并在自己的贡献计划中合理安排合入时机。
一、发布范围:一次"全家桶"式版本发布
根据 RELEASE-PROCESS.md,Docker 项目的发布流程覆盖 Docker Engine、Compose、Kitematic、Machine、Swarm、Distribution、Notary 等项目,以及它们各自的底层依赖(如 libnetwork、libkv 等)。文档中明确了流程的分工:
- RELEASE-PROCESS.md(本文主体):描述整体发布节奏——何时开发、何时冻结、何时发版;
- PATCH-RELEASES.md:描述补丁(bugfix)发布的逐步技术细节,包括是否需要建立 release 分支、补丁的回移规则。
当前仓库是这一流程的直接载体。从 releases/versions.yaml 可以看到项目当前所处的版本状态:
docker:
last: "29.7.2"
next: "29.8.0"
这说明最新已发布版本是 29.7.2,下一个目标版本是 29.8.0。结合 BRANCHES-AND-TAGS.md 的说明,仓库中的各个组件拥有各自独立的版本体系:
| 组件 | 标签格式 | 示例 |
|---|---|---|
| Moby 核心库 | vX.Y.Z |
v2.0.0-beta.5 |
| Docker Engine | docker-vX.Y.Z |
docker-v29.1.2 |
| API(api/ 目录,独立 Go module) | api/vX.Y.Z |
api/v1.52.0 |
| Client(client/ 目录,独立 Go module) | client/vX.Y.Z |
client/v1.52.0 |
标签遵循类语义化版本规范:vX.Y.Z[-suffix[N]],例如 1.8.0 的首个候选版本打 v1.8.0-rc1,第二个 alpha 版本打 v1.0.0-alpha1。
二、发布周期:九周时间盒(Release cycle)
Docker 项目采用基于时间的发布周期(time-based release cycle),每 9 周 发布一次。一个周期的开始日就是上一个周期的结束日——周期首尾相接,滚动前进。
周期被明确划分为两个阶段:
-
前 6 周:开发阶段(Development phase) 提交到任意关联项目的新功能与 bugfix 都有资格(eligible)进入下一个发布版本。但文档特别强调:此期间提交的任何改动都不保证会在本周期内合并。
-
第 7 周起:冻结阶段(Freeze phase),持续 3 周,详见下一节。
原图中的周期示意如下(ASCII 图完整继承自 RELEASE-PROCESS.md):
Codebase Release
Start of is frozen (end of the
the Cycle (7th week) 9th week)
+-----------------------------------+---------------------+
| | |
| Development phase | Freeze phase |
| | |
+---------------------------------------+---------------------+
6 weeks 3 weeks
<---------------------------------------><-------------------->
这个 6+3 的结构是整个发布流程的骨架:所有围绕"何时能提交""冻结期内改什么""补丁从哪切"的规则,都是围绕这两个阶段展开的。
三、冻结期(The freeze period)与 RC 候选版本
在周期开始后的第 6 周,代码库正式冻结(frozen),进入接近最终发布的状态,同时生成一个 Release Candidate(RC)。冻结期的目的非常明确:在正式发布前发现 bug、收集社区对 RC 状态的功能与稳定性反馈。
冻结期内的关键规则(直接来自 RELEASE-PROCESS.md):
master分支照常开发:冻结只针对 RC,master继续正常的开发节奏;- RC 不接受任何新功能:冻结期内新 feature 一律不进 RC;
- 有选择地 cherry-pick:当 bug 在
master上修复后,发布负责人(release owner)会挑选(selectively)其中关键的修复,cherry-pick 到 RC 中; - RC 滚动更新:随着 RC 内容变化,会不断推出新的 RC 供社区测试和评审。
这个"master 不停车、RC 单独冻结"的双轨模型,正是 Moby 能够维持 9 周滚动周期的核心机制:开发不中断,发布质量靠冻结期内的定向修复与社区反馈来保证。
冻结期结束时(周期第 9 周),所有项目一起发布(released together)——呼应第一节提到的全家桶式发布范围。
四、补丁发布:从 master 直切还是走发布分支?
RELEASE-PROCESS.md 将补丁发布的逐步技术细节委托给 PATCH-RELEASES.md,其决策逻辑非常清晰:
- 如果
master上没有不适合补丁发布的内容变更:patch release 可以直接从master分支切出; - 如果
master上已有不适合进补丁发布的变更:需要建立一条 release 分支,后续 bugfix 和补丁必须回移(backport) 到该分支。
补丁(patch)必须同时满足三个条件:
- 不是重大功能/新功能;
- 不破坏现有功能;
- 是 bugfix 或小型改进。
要标记"某个针对 master 的 PR 应进入下一个补丁发布",作者或维护者需要给该 PR 打上与发布分支对应的标签:
process/cherry-pick/<BRANCH_NAME>
例如针对 docker-29.x 分支,就是 process/cherry-pick/docker-29.x。
发布分支的命名与生命周期规则在 BRANCHES-AND-TAGS.md 中定义:
- Docker Engine 的发布分支命名格式为
docker-MAJOR.x(如docker-29.x); - 一条发布分支可以覆盖一整个大版本的发布周期,也可以只服务于某个小版本线(例如历史上的
26.0、26.1分支); - 当前仓库记录的维护状态中,
docker-29.x为 Maintained(维护方为 Moby Project 维护者团队),25.0分支仍处于维护状态直至 2026-12-04;
| 分支 | 贡献状态 | 说明 |
|---|---|---|
docker-29.x |
Maintained | 预期维护至 docker-30.x 之后 |
25.0 |
Maintained | 预期维护至 2026-12-04 |
docker-28.x、27.x、26.1、26.0、24.0、23.0 等 |
Unmaintained | 不再接受贡献,不在安全公告范围内 |
分支的贡献状态定义也值得注意:Maintained 表示接受贡献与回移、在安全公告范围内;Unmaintained 则相反。这决定了补丁回移的目标分支选择。
五、发布分支的落地操作:仓库中的同步脚本
仓库在 releases/scripts/ 下提供了两个直接服务于上述发布流程的 bash 脚本,可作为发布操作的事实佐证。
5.1 sync-branch:将发布标签合入分支
sync-branch 接收一个或多个发布标签作为参数,逐个执行 git merge --no-ff 将其合入当前分支:
- 如果合并失败且存在冲突(
git diff --diff-filter=U非空),脚本会以git checkout "$tag_to_sync" -- '.'以标签侧内容为准解决冲突后继续合并——即发布标签的内容优先于分支侧; - 所有标签合入后,脚本还会用
git merge-base --is-ancestor逐一校验每个标签确实已成为 HEAD 的祖先,防止"合并看似成功但实际未包含某个标签"的情况。
这一"标签内容优先 + 事后祖先校验"的设计,正对应补丁发布流程中"发布分支必须完整包含目标发布内容"的要求。
5.2 unmerged-tags:找出该回移的发布标签
unmerged-tags 的用法是 unmerged-tags <RELEASE_BRANCH> <TAG>,用于计算某个标签之前(含该标签)、已合入 master 但尚未合入指定发布分支的所有 docker-v* 发布标签:
- 先校验标签存在,若标签已在发布分支中则直接退出(幂等);
- 确认标签在
master(优先upstream/master)中; - 通过
git tag --merged "$master" --no-merged "$release_branch" --sort=v:refname 'docker-v*'按版本号排序列出候选标签,并用awk截断到指定标签为止。
它输出的正是需要执行 cherry-pick/backport 操作的标签清单,是第四节"回移"规则的具体执行入口。
5.3 版本号如何进入构建:hack/make.sh
构建侧的入口 hack/make.sh 展示了标签与构建版本的衔接:默认 VERSION=dev,但会优先从 GIT_CEILING 检查出的 git ref 推导——refs/tags/docker-v* 会剥离 docker-v 前缀作为版本,refs/tags/v* 剥离 v 前缀。这与 BRANCHES-AND-TAGS.md 中 docker-vX.Y.Z 的 Engine 标签格式完全对应:发布时打的标签,直接决定了构建产物的版本号。
六、如何在冻结日前最大化合入概率?
RELEASE-PROCESS.md 给出了四条实操建议。首先要接受前提:任何特定改动都没有合入保证,但以下行为能显著提高概率:
- 对齐 Roadmap:团队优先评审与路线图一致的 PR。仓库根目录的 ROADMAP.md 就是该文档的实例——当前路线图的优先级包括运行时改进(向 containerd 收敛)、BuildKit 集成的镜像构建器、Rootless 模式、测试体系(integration-cli 向 integration 迁移)以及内部解耦等;
- 尽早开 PR:PR 开开得越早,维护者可用的评审时间越充裕。文档明确指出:在冻结日前一天才开的 PR,几乎不可能赶上本次发布;
- 与保持者持续沟通:通过邮件列表、IRC、GitHub issue 等渠道,在动手实现前就拿到设计层面的早期反馈,通常能显著缩短改动集的讨论周期;
- 代码质量达标:代码有注释、测试充分、并完整遵循 CONTRIBUTING 指南 的每一条规则——这能直接加快评审速度。
七、例外情况:发布延期(Pushed back release)
RELEASE-PROCESS.md 还规定了唯一的例外机制:
如果在冻结期结束前发现严重问题(critical issue),且解决它需要更多时间,发布将被推迟(pushed back);而一旦某次发布被推迟,下一个发布周期也会随之延迟。
由于周期首尾相接(新周期从旧周期结束日当天开始),一次延期会级联影响后续所有发布的时间表——这也解释了为什么冻结期内的 RC 测试与社区反馈如此重要:它正是发布前最后一道"是否具备发货条件"的检验。
八、小结:发布流程要素速查
| 要素 | 规则 | 依据 |
|---|---|---|
| 发布周期 | 每 9 周一次,周期首尾相接 | RELEASE-PROCESS.md |
| 开发阶段 | 前 6 周,改动"有资格"但不保证合入 | 同上 |
| 冻结阶段 | 第 7 周起 3 周,RC 只接受 cherry-pick 的关键修复 | 同上 |
| 发布动作 | 第 9 周末所有项目一起发布 | 同上 |
| 延期规则 | 严重问题导致延期,后续周期级联推迟 | 同上 |
| 补丁来源 | 可从 master 直切;否则建 docker-MAJOR.x 发布分支并回移 |
PATCH-RELEASES.md、BRANCHES-AND-TAGS.md |
| 补丁标记 | PR 加 process/cherry-pick/<BRANCH_NAME> 标签 |
PATCH-RELEASES.md |
| 标签格式 | Engine 为 docker-vX.Y.Z,如 docker-v29.7.2 |
BRANCHES-AND-TAGS.md、releases/versions.yaml |
| 同步工具 | sync-branch(合入标签)、unmerged-tags(列出待回移标签) |
releases/scripts/sync-branch、releases/scripts/unmerged-tags |
对贡献者而言,最有操作价值的结论只有两点:在冻结日前的早期开 PR 并优先对齐 ROADMAP.md;面向存量版本修 bug 时,确认目标发布分支的维护状态,并按 PATCH-RELEASES.md 要求打上 process/cherry-pick/ 标签,改动才有进入下一次补丁发布的通道。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00