- 开发工具
- 云原生
- 微服务
【免费下载链接】tilt
Define your dev environment as code. For microservice apps on Kubernetes.
本文基于仓库中随附的 opentelemetry-go 官方发布文档(RELEASING.md),系统梳理其从创建发布 Issue、升级 OpenTelemetry Semantic Conventions(semconv)、验证破坏性变更,到 Pre-Release、打 Tag、GPG 签名制品、正式 Release 与 Post-Release 收尾的完整发布生命周期。结合仓库内 Makefile、versions.yaml 等源码级证据展开讲解,读者读完后可完整掌握 opentelemetry-go 这类多 Go Module 仓库的规范化发布方法,并将其迁移到自身开源项目的发布管线设计中。
一、发布前的准备工作:创建Version Releaseissue
官方发布流程的第一步是创建一个Version Release(版本发布)issue,用它来跟踪整个发布过程。这个 issue 充当发布工作清单(todo list),贯穿后续所有阶段——从 semconv 升级、Changelog 整理、打 Tag、签名制品,一直到 Post-Release 阶段的 milestone 关闭与 issue 收尾。
在仓库中,每次发布都会把该 issue 的 todo list 逐项打勾,最终在 Close theVersion Releaseissue 一节中关闭。这一做法保证了发布过程可追溯、可审计,也便于多个维护者协作时明确各自责任。
二、Semantic Convention 升级
opentelemetry-go 的semconv子包与上游 OpenTelemetry Semantic Conventions 版本严格对应:每发布一个新版本的语义约定(Semantic Conventions),就需要在仓库中生成对应版本号的semconv/v<版本>子包。当前仓库的 semconv 目录 中已存在v1.37.0、v1.40.0、v1.41.0等多个版本子包,每个子包都包含独立的doc.go、schema.go、attribute_group.go等生成文件,以及用于指导升级的 MIGRATION.md。
2.1 使用semconv-generate生成新版本子包
生成动作由semconv-generatemake target 驱动。其核心步骤为:
- 将
TAG环境变量设置为要生成的目标 Semantic Conventions tag; - 在本仓库中运行
make semconv-generate。
官方示例:
export TAG="v1.30.0" # 改为你要生成的发布版本 make semconv-generate # 使用上面导出的 TAG从 Makefile 的实现可以看到,该 target 的实际行为是:
- 强制校验
TAG是否已设置,未设置直接报错退出([ "$(TAG)" ] || ( echo "TAG unset: missing opentelemetry semantic-conventions tag"; exit 1 )); - 在
semconv/<TAG>目录下创建目标源码目录; - 通过 Docker 运行
weaver镜像,从语义约定仓库的对应 tag 拉取 model 并执行registry generate,结合仓库内的模板目录生成 Go 代码; - 最后调用
semconvkit工具对生成结果做一致性整理。
生成完成后应提交 Pull Request 将该新子包合入仓库,并确认生成结果正确无误。生成的新子包即为go.opentelemetry.io/otel/semconv/<NEW VERSION>。
2.2 同步更新 CHANGELOG
升级 semconv 必须同步在 CHANGELOG.md 中登记新增子包。官方给出了标准条目格式:
- The `go.opentelemetry.io/otel/semconv/<NEW VERSION>` package. The package contains semantic conventions from the `<NEW VERSION>` version of the OpenTelemetry Semantic Conventions. See the [migration documentation](https://link.gitcode.com/i/9e7dc8168b961dd32f41355192aefe71) for information on how to upgrade from `go.opentelemetry.io/otel/semconv/<PREVIOUS VERSION>`. (#PR_NUMBER)提示:条目中的"新版本"与"先前版本"要按实际变化改写。以当前仓库为例,CHANGELOG.md 中记录了 v1.41.0 semconv 包的加入,并指向./semconv/v1.41.0/MIGRATION.md,同时说明了从v1.40.0升级的迁移文档;各版本的 MIGRATION.md 以 "drop-in replacement"(可直接替换)为基调,明确列出被移除的声明(如ErrorMessage、RPCMessageID等 RPC 消息相关属性),方便使用者评估影响面。
2.3 更新全代码库的 semconv 导入
生成新子包后,需要把代码库中所有 semconv 导入路径统一更新为新版本:
// Before(更新前) semconv "go.opentelemetry.io/otel/semconv/v1.37.0" "go.opentelemetry.io/otel/semconv/v1.37.0/otelconv" // After(更新后) semconv "go.opentelemetry.io/otel/semconv/v1.39.0" "go.opentelemetry.io/otel/semconv/v1.39.0/otelconv"更新完成后运行make检查是否存在编译或测试失败。这里需要注意的是,仓库会以 go.work 方式组织大量子模块,make会遍历所有go.mod目录执行构建与测试(参见 Makefile 中build/%与build-tests/%的定义),因此一次make即可覆盖全部子模块的编译验证。
处理属性变更(Handling attribute changes)
某些 semconv 版本会新增属性,或影响当前正在使用的属性。变更可能只是简单的重命名,也可能是更复杂的合并——例如多个属性合并、属性值类型被修改。处理原则是:
- 更新代码,改用新属性以替代受影响的旧属性,从而始终遵循最新语义约定;
- 遗留(legacy)属性仍可根据
OTEL_SEMCONV_STABILITY_OPT_IN环境变量继续输出,以实现平滑迁移。
这类迁移需要仔细跟踪与执行,官方文档建议参考相关 issue(如 opentelemetry-go 的 #7806)了解迁移的跟踪与落地方式。
2.4 Go contrib linter 更新
semconv 版本升级还涉及配套仓库的联动:需要更新 opentelemetry-go-contrib 仓库中的.golangci.yml,强制要求使用新的 semconv 版本。这保证了主仓库与 contrib 仓库在语义约定版本上保持一致,避免 contrib 侧继续引用已过时的属性名。
三、破坏性变更验证:make gorelease
发布前必须确认公共 API 没有发生非预期的破坏性变更。官方做法是运行make gorelease,该 target 会调用gorelease工具(来自golang.org/x/exp/cmd/gorelease)逐模块检查公共 API 的差异。
从 Makefile 可以看到,goreleasetarget 会遍历所有go.mod目录分别执行gorelease检查。该工具会对比当前版本与上一版本之间的导出符号差异,输出新增、变更、删除的 API 清单,从而帮助维护者判断是否引入了非预期的破坏性变更。
使用建议:把make gorelease的输出逐项与本次发布的变更清单比对,凡是出现在输出中但不在计划内的 API 变更,都需要在合入前重新审视;gorelease 工具本身的问题可以在 Go 官方问题跟踪器中报告。
四、验证 contrib 仓库兼容性
如果主仓库的变更会影响 contrib 仓库(opentelemetry-go-contrib),则必须验证这些变更与 contrib 仓库的兼容性。具体做法是参照 contrib 仓库 RELEASING.md 中 "Verify OTel changes"(验证 OTel 变更)一节给出的步骤执行验证。
这通常意味着在 contrib 仓库中升级对主仓库模块的依赖版本,然后运行 contrib 的构建与测试,确保新增/变更的 API 在 contrib 的用法下依然成立。由于 semconv 属性升级、SDK 默认行为调整(例如当前 CHANGELOG.md 中记录的 sdk/metric 默认 2000 基数上限这类破坏性变更)都可能波及下游,这一步在发布流程中必不可少。
五、Pre-Release:版本号修改与分支准备
进入 Pre-Release 阶段前,首先需要决定本次发布哪些模块集合(module set),并在versions.yaml中更新它们的版本号,然后把该修改提交到新分支。
5.1 versions.yaml:多模块集的版本中枢
versions.yaml 是本仓库发布版本的单一事实来源,它按module-sets分组管理版本:
module-sets: stable-v1: version: v1.44.0 modules: - go.opentelemetry.io/otel - go.opentelemetry.io/otel/bridge/opencensus - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc - go.opentelemetry.io/otel/exporters/otlp/otlptrace - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric - go.opentelemetry.io/otel/metric - go.opentelemetry.io/otel/sdk - go.opentelemetry.io/otel/sdk/metric - go.opentelemetry.io/otel/trace experimental-metrics: version: v0.66.0 modules: - go.opentelemetry.io/otel/exporters/prometheus - go.opentelemetry.io/otel/metric/x experimental-logs: version: v0.20.0 modules: - go.opentelemetry.io/otel/log - go.opentelemetry.io/otel/sdk/log - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp experimental-schema: version: v0.0.17 modules: - go.opentelemetry.io/otel/schema可见该仓库采用"稳定版 + 多个实验版"并行发布策略:stable-v1内的模块遵循 v1.x 语义化版本,而experimental-metrics(v0.x)、experimental-logs(v0.x)、experimental-schema(v0.0.x)各自独立演进。文件底部还有excluded-modules(如内部工具模块)与modules(各模块的version-refs指向的版本文件,例如./internal/version.go)两节,前者用于排除不参与发布的内部模块,后者用于登记版本号的物理存放位置。
5.2 更新子模块依赖并执行prerelease
在versions.yaml更新版本后,还需要更新各子模块的 go.mod,使它们依赖即将在下一步发布的新版本。
随后运行prereleasemake target。它会在当前目录创建一个名为prerelease_<module set>_<new tag>的分支,该分支包含全部发布相关修改:
make prerelease MODSET=<module set>其中MODSET即versions.yaml中的 module set 名称(如stable-v1)。从 Makefile 的实现可以看到,prerelease强制要求设置MODSET,否则报错退出,然后调用multimod工具的prerelease子命令完成批量版本替换。
5.3 验证改动并合入预发布分支
git diff ...prerelease_<module set>_<new tag>该 diff 应显示所有模块的版本号都被更新为<new tag>。确认无误后,将其合并进预发布分支:
git merge prerelease_<module set>_<new tag>5.4 更新 CHANGELOG
合并后更新 CHANGELOG.md,要求:
确保本次发布的所有相关变更都已收录,且语言让非贡献者也能理解。可借助提交日志核对遗漏项:
git --no-pager log --pretty=oneline "<last tag>..HEAD"将所有
Unreleased的变更移动到一个新章节,标题遵循[<new tag>] - <date of release>格式;确保新章节位于发布区注释之下(形如
<!-- Released section -->),从而在后续发布时不会被覆盖。仓库还提供了 verify_released_changelog.sh 脚本,它通过 awk 抽取新旧 CHANGELOG 中Released section区间的文本并 diff,任何对已发布章节的改动都会导致校验失败,以此保护历史发布记录不被篡改;更新文档底部的所有相关链接。
最后将改动推送到 upstream 并在 GitHub 上创建 Pull Request,PR 描述中务必附上从 CHANGELOG 整理的变更说明。
六、Tag:为合并提交打版本标签
当包含全部版本变更的 Pull Request 被批准并合并后,就可以为合并提交打 tag 了。
6.1 两个关键约束
官方文档以加粗形式强调了两条硬性约束:
- 必须使用与 Pre-Release 阶段完全相同的 tag。如果在 Pre-Release 与打 Tag 之间修改了
versions.yaml,会留下损坏状态; - Go module 错误打上的 tag 无法删除。因此推送 upstream 的版本必须确认无误,否则会引发难以处理的连锁问题。
6.2 执行add-tags并推送
对每个要发布的 module set,使用主分支上合并 PR 的提交哈希运行add-tags:
make add-tags MODSET=<module set> COMMIT=<commit hash>只有当前工作目录的HEAD不是正确提交时才需要显式提供COMMIT值(该值默认取HEAD,参见 Makefile)。
随后把 tag 推送到 upstream 远端(而不是个人 fork),并且必须推送所有子模块的 tag:
git push upstream <new tag> git push upstream <submodules-path/new tag> ...由于stable-v1等 module set 内包含大量子模块(如exporters/otlp/otlptrace、sdk/metric等),每次发布都会产生一大批形如<submodule-path>/<tag>的 Git tag,逐一推送即可保证下游用户能通过任意子模块路径拉取到正确版本。
七、签名制品:符合 CNCF 最佳实践的 GPG 签名
为符合 CNCF 最佳实践,发布制品需要签名。具体操作是:
- 从 tags 页面下载本次发布 tag 对应的
.tar.gz与.zip两个源码归档; - 两者均需使用你的 GPG 密钥签名。签名前可先借助第三方校验脚本(attest-sh)核对归档内容;
- 查找自己的 GPG 密钥 ID:
gpg --list-secret-keys --keyid-format=long密钥 ID 是sec rsa4096/(或类似输出)之后的 16 位字符串。
- 设置环境变量并分别对两个归档签名:
export VERSION="<version>" # 例如 v1.32.0 export KEY_ID="<your-gpg-key-id>" gpg --local-user $KEY_ID --armor --detach-sign opentelemetry-go-$VERSION.tar.gz gpg --local-user $KEY_ID --armor --detach-sign opentelemetry-go-$VERSION.zip- 验证签名:
gpg --verify opentelemetry-go-$VERSION.tar.gz.asc opentelemetry-go-$VERSION.tar.gz gpg --verify opentelemetry-go-$VERSION.zip.asc opentelemetry-go-$VERSION.zip签名产物为<归档名>.asc(ASCII armored 分离签名文件),它们将作为发布资产随 Release 一起上传。
八、Release:创建不可变的 GitHub Release
最后一步是为新 tag 在 GitHub 上创建 Release,正文需包含本次发布在 CHANGELOG 中的全部 release notes。
重要:GitHub Releases 一旦创建即不可变。必须在创建 Release 时一次性上传已签名的制品(.tar.gz、.tar.gz.asc、.zip、.zip.asc四个文件),因为之后无法再添加或修改。这也是第 7 节要求提前完成签名、第 6 节要求确认 tag 正确的原因——发布链条上每一环的错误都无法在事后补救。
九、Post-Release 收尾工作
正式发布完成后还有四项收尾任务:
9.1 Contrib 仓库发布
确认无误后,需要为使用本次发布的 contrib 仓库(opentelemetry-go-contrib)也安排一次发布,使其指向最新的主仓库版本。
9.2 网站文档更新
更新 OpenTelemetry 官网的 Go instrumentation 文档(content/en/docs/languages/go目录):将文档中引用的包版本提升为刚发布的最新版本,并确保所有代码示例仍然可以编译、内容准确。
9.3 关闭 milestone
发布完成后,把所有本次修复的 issue 与合并的 PR 归入对应 milestone:
- 查找尚未纳入 milestone 的已关闭 issue(可按无 milestone、已关闭、按更新时间排序、已 linked 到 PR 等条件筛选);
- 查找尚未纳入 milestone 的已合并 PR(按无 milestone、已合并筛选)。
全部归入后关闭该 milestone。这保证了每个里程碑都能准确反映其包含的变更集合。
9.4 关闭Version Releaseissue
当Version Releaseissue 中的 todo list 全部完成(包括上述所有步骤与 milestone 归位)后,关闭该 issue,整个发布流程结束。
十、发布流程在真实仓库中的落地:以 tilt 仓库的 OTel 集成为例
上述发布流程并不只是理论文档——本仓库(tilt)本身就是 opentelemetry-go 的真实下游使用者,可以直接观察到依赖方视角的集成方式。
tilt 在根目录 go.mod 中依赖go.opentelemetry.io/otel v1.44.0、go.opentelemetry.io/otel/sdk v1.44.0、go.opentelemetry.io/otel/trace v1.44.0,并通过otlpmetricgrpc、otlptrace等 exporter 模块上报遥测数据,依赖版本与 versions.yaml 中stable-v1的v1.44.0完全对应。
在 internal/tracer/otel.go 中,tilt 使用 otel SDK 的标准用法初始化 TracerProvider:sdktrace.NewTracerProvider配合AlwaysSample()采样器,再注册NewBatchSpanProcessor批量处理器。而在 internal/tracer/span_collector.go 中,tilt 实现了一个自定义的SpanExporter(ExportSpans/Shutdown),通过内存 channel 缓冲 Span 并支持消费端拉取后 JSON 编码输出,其语义与 opentelemetry-go v0.2.0 的 JSON 序列化格式保持兼容(见 internal/tracer/exptel/span.go 的说明)。
由此可见:opentelemetry-go 每次严格按 RELEASING.md 流程发布的稳定版本(含 semconv 升级与 API 兼容性验证),正是像 tilt 这样的大量下游项目可以放心升级依赖的信任基础。对希望参与或复刻这一流程的开发者来说,本仓库中随附的完整 RELEASING.md、versions.yaml 与 Makefile 就是一套可以直接对照学习的多模块发布样板。
结语:多模块发布的关键纪律
纵观整个发布流程,可以提炼出几条适用于任何多 Go Module 项目的发布纪律:
- 单一事实来源:版本号集中在
versions.yaml,所有模块版本由multimod工具统一替换,避免手工改版本号导致的不一致; - 可逆操作前置、不可逆操作后置:先验证(gorelease、contrib 兼容性、git diff 审查),再执行不可逆动作(打 tag、创建 Release、上传制品);
- 变更可追溯:CHANGELOG 的
Released section受脚本保护、milestone 归位、Version Releaseissue 全程跟踪,任何一步都留下审计痕迹; - 下游兼容优先:semconv 属性升级遵循
OTEL_SEMCONV_STABILITY_OPT_IN兼容通道,破坏性变更必须在 CHANGELOG 中以醒目方式声明(如 sdk/metric 默认基数上限),给下游(如 tilt)留出升级窗口。
按照本文的步骤执行,即可完整复现 opentelemetry-go 官方仓库的规范化发布流程。
- 开发工具
- 云原生
- 微服务
【免费下载链接】tilt
Define your dev environment as code. For microservice apps on Kubernetes.
相关推荐
OpenTelemetry Go 多模块发布全流程指南:从 Semantic Convention 升级到 GPG 签名 Release
OpenTelemetry Go 多模块发布全流程指南:从 Semantic Convention 升级到 GPG 签名 Release 导读 OpenTele
后端微服务存储认证鉴权OpenTelemetry Go SDK(opentelemetry-go)完整发布流程实战指南:从 Semantic Convention 升级到 GPG 制品签名
OpenTelemetry Go SDK(opentelemetry go)完整发布流程实战指南:从 Semantic Convention 升级到 GPG 制
容器运行时云原生CLIopentelemetry-go 版本发布全流程实战:Semantic Convention 升级、GPG 签名与多模块 Tag 管理
opentelemetry go 版本发布全流程实战:Semantic Convention 升级、GPG 签名与多模块 Tag 管理 本文基于 sliver
网络安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考