- 后端
- 云原生
【免费下载链接】deis
Deis v1, the CoreOS and Docker PaaS: Your PaaS. Your Rules.
本文以 Deis v1(CoreOS + Docker PaaS)仓库中维护者发布清单 docs/roadmap/releases.rst 为主体,完整拆解 Deis 补丁版本与主次版本的发布流程:如何用 Go 编写的 bumpver 工具批量更新散落在源码、文档与 Dockerfile 中的语义化版本号、如何用 generate-changelog.sh 从提交日志生成 CHANGELOG、如何提交并推送 release tag,以及发布后对 master 分支和外部渠道的收尾动作。读完后你可以独立走完一次 Deis 产品版本的发布操作,并理解每个版本号在仓库中的分布位置与一致性校验方法。
发布清单的定位与适用前提
releases.rst 是一份面向维护者的 Release Checklist,目标只有一个:协助维护者创建一次新的 Deis 产品版本,并明确要求“流程有变时同步更新本文档”。清单要求从上到下顺序执行,跳过不适用的章节。整个流程围绕三类版本动作展开:
- Patch Release(补丁发布):从上一个 release tag 检出,cherry-pick 特定修复提交,打补丁 tag;
- Major or Minor Release(主次版本发布):直接基于 master 分支发布,涉及 milestone 管理、
-dev版本后缀替换等额外动作; - Any Release(任意版本通用的收尾步骤):CI 构建触发、安装脚本更新、文档站点发布、IRC 频道公告等。
当前仓库正处于 v1 维护期(见 docs/roadmap/roadmap.rst 中“Deis v1 Maintenance”一节,v1 已转入维护,主要跟踪上游 CoreOS 版本升级与安全补丁),仓库内各处版本号一致地停留在1.13.4,本文的示例值均以此为准。
bumpver:批量更新版本号的 Go 命令行工具
清单中所有版本号更新都通过./contrib/bumpver/bumpver完成。该工具位于 contrib/bumpver/ 目录,是一个 Go 编写的单文件命令行程序:入口 bumpver.go 仅一行os.Exit(Command(nil)),全部逻辑在 bump.go 中。
命令语义与参数
从 bump.go 中的 docopt usage 字符串可以看到完整命令规格:
Usage: bumpver [-f <current>] <version> <files>... Options: -f --from=<current> An explicit version string to replace. Otherwise, use the first semantic version found in the first file.-f <current>:显式指定要被替换的旧版本字符串。发布流程中几乎总是显式指定,因为旧版本可能形如1.13.3或1.13.3-dev这类与“第一个匹配到的 semver 不同”的字符串;<version>:新版本号,bump.go 用正则(\d{1,3}\.\d{1,3}\.\d{1,3})校验,不是合法的三段式语义版本会直接报错退出;<files>...:一个或多个待更新文件,工具会替换每个文件中的全部出现位置(bytes.Replace(src, from, []byte(version), -1)),每成功处理一个文件打印一行Bumped <file>。
当未提供-f时,工具从第一个文件中查找首个 semver 匹配作为“旧版本”;若某个文件中找不到匹配则打印Skipped <file>并跳过。这种“显式 from + 全量替换”的设计,使得一次调用可以同时覆盖.go、.py、.rst、.md、Dockerfile 和 user-data 等多种文件——bump_test.go 中的TestGo、TestPython、TestReStructuredText、TestUserdata等用例正是按文件类型逐一验证替换结果,还包含TestBadSemver确认非法版本号(如1.5、0.13.0-dev作为目标版本、latest)会被拒绝。构建与测试通过 contrib/bumpver/Makefile 执行make test build。
Patch Release 场景:全量文件清单
发布补丁版本时,清单要求对完整文件清单执行版本更新(A.B.C→A.B.D)。原始命令如下,其中文件列表完整保留自 releases.rst:
$ ./contrib/bumpver/bumpver -f A.B.C A.B.D \ README.md \ builder/rootfs/Dockerfile \ builder/rootfs/usr/local/src/slugbuilder/Dockerfile \ builder/rootfs/usr/local/src/slugrunner/Dockerfile \ client/deis-version \ contrib/utils.sh \ contrib/coreos/user-data.example \ controller/deis/__init__.py \ controller/Dockerfile \ database/Dockerfile \ deisctl/client/client.go \ deisctl/deis-version \ docs/_includes/_get-the-source.rst \ docs/installing_deis/install-deisctl.rst \ docs/installing_deis/install-platform.rst \ docs/managing_deis/upgrading-deis.rst \ docs/reference/api-v1.7.rst \ docs/troubleshooting_deis/index.rst \ logger/image/Dockerfile \ logspout/image/Dockerfile \ publisher/image/Dockerfile \ registry/Dockerfile \ router/Dockerfile \ store/base/Dockerfile \ version/version.go对照当前仓库可以确认这些文件确实承载版本号:
| 文件 | 版本承载方式 |
|---|---|
| version/version.go | const Version = "1.13.4",deisctl 通过--version打印(见 deisctl.go 引用该包) |
| controller/deis/__init__.py | __version__ = '1.13.4' |
| client/deis-version、deisctl/deis-version | 纯版本号文本文件,各一行1.13.4 |
| deisctl/client/client.go | refresh-units命令 usage 中的默认 tag[default: v1.13.4] |
| contrib/utils.sh | export DEIS_RELEASE=1.13.4 |
| contrib/coreos/user-data.example | 安装命令install.sh \| sh -s 1.13.4与DEIS_RELEASE=v1.13.4 |
| 各组件 Dockerfile(如 builder/rootfs/Dockerfile、controller/Dockerfile) | ENV DEIS_RELEASE 1.13.4镜像标签 |
| 文档(docs/installing_deis/install-deisctl.rst、docs/managing_deis/upgrading-deis.rst 等) | 安装/升级示例中的版本号 |
需要说明的是,清单中的builder/rootfs/usr/local/src/slugbuilder/Dockerfile与slugrunner路径在维护期仓库中已不存在(builder 相关构建脚本收敛到了 builder/src/ 下的 Go 源码)。这正是清单开头“流程有变时请更新本文档”的要求所在:发布清单是一份“活的”文档,文件列表需要随代码库演进而修剪。
Patch Release 完整流程
补丁发布的每一步都对应 releases.rst 中 “Patch Release” 一节,按序执行:
检出上一个 release tag:
$ git checkout vA.B.C注意补丁版本不是从 master 发出的,而是从旧 tag 检出后叠加修复,保证补丁基线与上一发布版本完全一致。
cherry-pick 指定的修复提交:
$ git cherry-pick <commit-ish>...执行上文的全量 bumpver 命令,把
A.B.C全部替换为A.B.D。手动更新 CHANGELOG:清单特别指出,generate-changelog.sh 只统计 merge 提交(
git log --merges,见 脚本第 27 行),而 cherry-pick 产生的是普通提交,因此补丁版本必须手工把变更补录进 CHANGELOG.md。全库搜索确认无遗漏:
$ git grep A.B.C如果还能搜出旧版本号字符串,说明有文件漏改。
提交并推送 tag:
$ git commit -a -m 'chore(release): update version to vA.B.D' $ git tag vA.B.D $ git push --tags origin vA.B.D
Major or Minor Release 发布流程
主次版本直接基于 master 发布,比补丁发布多出 milestone 管理、双阶段版本号替换和 Dockerfile 后缀处理:
将未完成的 issue 移到下一个 deis milestone,然后关闭当前 milestone。
检出并更新 master:
$ git checkout master && git pull双阶段版本号替换。master 上的开发版本带
-dev后缀(如1.14.0-dev),而发布文档里引用的是稳定版本号A.B.C,因此要分两次执行 bumpver:# 第一步:带 -dev 后缀的开发版本号文件,直接指向新版本 $ ./contrib/bumpver/bumpver -f A.B.D-dev A.B.D \ client/deis-version \ controller/deis/__init__.py \ deisctl/deis-version \ docs/reference/api-v1.7.rst \ version/version.go # 第二步:稳定版本号引用的文件(文档、脚本、user-data 等) $ ./contrib/bumpver/bumpver -f A.B.C A.B.D \ README.md \ contrib/utils.sh \ contrib/coreos/user-data.example \ docs/_includes/_get-the-source.rst \ docs/installing_deis/install-deisctl.rst \ docs/installing_deis/install-platform.rst \ docs/managing_deis/upgrading-deis.rst \ docs/troubleshooting_deis/index.rst这个两阶段设计与 deisctl/client/client.go 的
RefreshUnits实现直接相关:deisctl refresh-units从 Deis 项目的 GitHub 仓库按 tag/SHA 下载 unit 文件(units 包),其 usage 字符串底部有一个默认 tag。清单要求手动把该默认值从[master]改为[vA.B.D],使deisctl默认拉取本次发布的 unit 文件。当前仓库中该默认值即为 client.go 第 276 行 的[default: v1.13.4]。另需手工处理:在所有项目 Dockerfile中执行 find-and-replace,把
A.B.D-dev镜像标签替换为A.B.D(bumpver 的替换语义无法区分-dev后缀与纯版本号的两种语境,所以这一步留在人工)。用脚本生成 CHANGELOG:
$ ./contrib/util/generate-changelog.sh vA.B.C | cat - CHANGELOG.md > tmp && mv tmp CHANGELOG.md即把新生成段拼接到现有 CHANGELOG 前部,然后把标题里的
HEAD改为新版本vA.B.D,删除空小节并校对。git grep A.B.C检查遗漏,然后提交、推送 master、打 tag 并推送 tag:$ git commit -a -m 'chore(release): update version to vA.B.D' $ git push origin master $ git tag vA.B.D $ git push --tags origin vA.B.D
CHANGELOG 是怎么生成的
generate-changelog.sh 是整个发布流程中唯一自动化的文档环节,理解它的行为才能解释清单中的那些限制。其核心逻辑:
- 输入区间:
main函数接收FROM(上次 release tag)与TO(默认HEAD),输出以### $FROM -> $TO开头的 markdown 段,与 CHANGELOG.md 现有的### v1.13.3 -> v1.13.4标题格式完全对应; - 只统计 merge 提交:
retrieve函数执行git log --oneline --merges --format="%h %H %b" --grep="$1" "$FROM".."$TO",这依赖 Deis 的 PR merge 提交信息规范; - 按提交类型分组:
TYPES变量默认值为feat(;Features fix(;Fixes docs(;Documentation chore(;Maintenance),即按 conventional commit 前缀(feat/fix/docs/chore)把提交归入 Features、Fixes、Documentation、Maintenance 四个####小节; - 输出格式:每条记录形如
- `c63ade6` Godeps,deisctl: serialize a unit test...,其中子系统名从type(subsystem): message中解析(脚本第 18-21 行); - 可定制性:
REPOROOT(提交链接前缀,默认为 Deis 官方仓库地址)与TYPES都可通过环境变量覆盖。
--merges过滤正是补丁版本必须手工补录 CHANGELOG 的原因——cherry-pick 提交没有对应的 merge 记录,脚本“看不见”它们。
Any Release:发布后的通用收尾步骤
无论补丁还是主次版本,tag 推送之后都要执行 releases.rst “Any Release” 一节:
- 新组件发布:如果本次版本引入了新组件,需先配置
test-acceptanceCI 作业将其推送到 Docker Hub。 - 手动触发 CI 构建(在 Deis 的 CI 服务器上,指定新的
vA.B.Dtag),顺序有严格要求:build-deis-cli-installer-darwinbuild-deis-cli-installer-linuxbuild-deisctl-installer-darwinbuild-deisctl-installer-linux- 等上述客户端作业全部完成后,再触发
test-acceptance验收作业。
- 更新 deis.io 仓库中的安装脚本(
deis-cli/install.sh与deisctl/install.sh),使其指向新版本A.B.D——这与仓库内 docs/installing_deis/install-deisctl.rst 中curl -sSL http://deis.io/deisctl/install.sh | sh -s 1.13.4一类安装命令保持联动。 - 更新 ReadTheDocs 上已发布的文档版本:登录管理后台,把当前版本加入已发布版本列表、从列表中移除最旧版本、重新构建所有已发布版本以刷新各版本页面间的“Versions”索引链接。
- 更新 #deis IRC 频道话题,引用新版本号。
发布之后:master 分支的跟进动作
tag 推送完成并不等于发布结束,master 分支还需要一轮收尾,补丁与主次版本的做法不同。
补丁版本发布后
把 master 上的版本号提到刚发布的版本(只针对稳定版本文档引用,不含 Dockerfile 镜像标签):
$ ./contrib/bumpver/bumpver -f A.B.C A.B.D \ README.md \ contrib/utils.sh \ contrib/coreos/user-data.example \ docs/_includes/_get-the-source.rst \ docs/installing_deis/install-deisctl.rst \ docs/installing_deis/install-platform.rst \ docs/managing_deis/upgrading-deis.rst \ docs/reference/api-v1.7.rst \ docs/troubleshooting_deis/index.rst $ git commit -a -m 'chore(release): update version in master to vA.B.D' $ git push origin master随后在 GitHub Releases 页面创建 release notes:正文直接粘贴新加入的 CHANGELOG.md 段落,必要时加一段说明性文字(例如引用安全修复或升级注意事项)。
主次版本发布后
把 deisctl/client/client.go 中
RefreshUnits的默认 tag 从[vA.B.D]改回[master],让 master 分支恢复跟踪主干 unit 文件;把 master 版本号 bump 到下一个计划版本并加
-dev后缀:$ ./contrib/bumpver/bumpver -f A.B.D A.B.E-dev \ client/deis-version \ controller/deis/__init__.py \ deisctl/deis-version \ version/version.go同时在所有项目 Dockerfile 中把
A.B.D替换为A.B.D-dev,提交并推送 master(提交信息形如chore(release): update version in master to vA.B.D-dev);在 deis.io 的博客上按既有格式撰写 release notes 文章;再把博客内容搬到 GitHub release notes,删除 Jekyll 特有的头部和
<!-- more -->标记;更新 Slack 频道话题,引用下一个计划版本。
版本号一致性:如何验证发布没有漏改
整个流程中最关键的防错手段是发布前的git grep A.B.C。用当前仓库的实际分布做参照,一次合格的发布应当让下列位置全部从旧版本切换到新版本(当前值均为1.13.4):
$ git grep -n "1.13.4" -- README.md contrib/utils.sh contrib/coreos/user-data.example \ docs/_includes/_get-the-source.rst docs/troubleshooting_deis/index.rst deisctl/client/client.go README.md:9:[]... contrib/coreos/user-data.example:114:... install.sh | sh -s 1.13.4' contrib/coreos/user-data.example:128: DEIS_RELEASE=v1.13.4 contrib/utils.sh:17:export DEIS_RELEASE=1.13.4 deisctl/client/client.go:276: [default: v1.13.4] docs/_includes/_get-the-source.rst:9: $ git checkout v1.13.4 docs/troubleshooting_deis/index.rst:110:``deisctl refresh-units --tag=v1.13.4``...可以看到同一版本号的引用形式并不统一:README 徽章和 user-data 里带v前缀(v1.13.4),contrib/utils.sh的DEIS_RELEASE与 Dockerfile 的ENV DEIS_RELEASE不带v,client.go默认 tag 带v——这正是必须用-f显式指定旧字符串、并在全量 grep 中留意前缀差异的原因。此外 docs/reference/api-v1.7.rst 中示例响应的DEIS_PLATFORM_VERSION: 1.13.4、各安装文档中的下载链接版本号,也都属于这份清单的覆盖范围。
小结
Deis v1 的发布流程本质上是一套以 tag 为发布单元、以版本号字符串一致性为核心校验目标的手工 checklist:
- 补丁版本 = 旧 tag 检出 + cherry-pick + 全量 bumpver + 手工 CHANGELOG + tag 推送,master 随后同步版本号;
- 主次版本 = master 直发 +
-dev后缀两阶段替换 +RefreshUnits默认 tag 切换 + 脚本生成 CHANGELOG + 博客与 release notes; - 任何版本都要触发四平台客户端安装器的 CI 构建、更新 deis.io 安装脚本与 ReadTheDocs 已发布版本;
- 自动化由 bumpver(批量、可校验的 semver 替换)与 generate-changelog.sh(基于 conventional commit 的 changelog 聚合)承担,两者都有对应的测试与构建入口(contrib/bumpver/Makefile、contrib/bumpver/bump_test.go),其余环节则以“从上到下执行、跳过不适用项、流程变化时回写本文档”的方式由维护者手工完成。
这套流程的适用前提是 Deis v1 仓库自身的组织结构(多组件 Dockerfile、DEIS_RELEASE环境变量约定、deis.io 安装脚本),阅读清单时应以仓库当前实际文件为准——正如清单自己所要求的那样,文件列表会随代码库演进而需要更新。
- 后端
- 云原生
【免费下载链接】deis
Deis v1, the CoreOS and Docker PaaS: Your PaaS. Your Rules.
相关推荐
Dendron 版本发布实操:Changelog 同步与 Git Tag 管理指南
Dendron 版本发布实操:Changelog 同步与 Git Tag 管理指南 本篇指南以 Dendron 仓库维护手册( dev/dev.t.change
知识管理知识库TinyUSB 版本发布全流程指南:从版本号提升、changelog 整理到 tag 落地
TinyUSB 版本发布全流程指南:从版本号提升、changelog 整理到 tag 落地 本篇技术指南围绕 TinyUSB 仓库内置的发布技能( make r
文档教程Wasmer 发布流程全指南:从版本号更新、CHANGELOG 生成到 crates.io 发布
Wasmer 发布流程全指南:从版本号更新、CHANGELOG 生成到 crates.io 发布 导读 本文基于 docs/dev/release.md htt
语言运行时JIT编译
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考