OpenTelemetry Go SDK 版本发布全流程:以 Moby 仓库中 vendored 的 otel 模块为例
导读
本文以当前仓库中 vendored 的 vendor/go.opentelemetry.io/otel/RELEASING.md 为核心骨架,系统讲解 opentelemetry-go(go.opentelemetry.io/otel)从创建 Version Release 跟踪 issue、升级 Semantic Conventions、校验 breaking changes,到 pre-release、打 tag、GPG 签名制品、发布 GitHub Release 以及 post-release 收尾的完整操作链路。读者阅读后可掌握该 Go 观测性 SDK 的模块化版本发布规范,并能在 vendor/go.opentelemetry.io/otel 目录内对照 Makefile、versions.yaml、CHANGELOG 与 semconv 子包核实每一步的底层实现与预期产物。
一、前置认知:这份文档在仓库中的位置与角色
该文件位于 Moby 仓库的第三方依赖目录下:
- 主文档:vendor/go.opentelemetry.io/otel/RELEASING.md(Release Process 全流程说明)
- 配套材料:同一 vendored 目录下还完整保存了 vendor/go.opentelemetry.io/otel/Makefile(semconv-generate、gorelease、prerelease、add-tags 等 target 的实现)、vendor/go.opentelemetry.io/otel/versions.yaml(module-set 与版本定义)、vendor/go.opentelemetry.io/otel/CHANGELOG.md(Keep a Changelog 风格变更记录)以及 vendor/go.opentelemetry.io/otel/semconv 下按版本号排列的多个子包(v1.17.0、v1.37.0、v1.43.0)。
理解这份文档前需要知道两个关键背景:
- 本文档描述的是上游 opentelemetry-go 仓库的发布流程。文中的发布操作(推分支、打 tag、签名制品、发 Release)发生在 opentelemetry-go 自身仓库内;而 Moby 仓库将其以 vendor 快照方式引入,因此读者可以从本仓库的 vendored 副本核对其中的 Makefile 目标、module 集合与 semconv 布局,实际执行发布仍属于上游仓库维护者的职责范围。
- 发布以“module set”为单位而非单一 module。otel-go 采用多 Go module 布局,
versions.yaml将众多 module 组织为多个 module set(详见下文),因此每次发布需要批量、一致地推进一批 module 的版本。
二、创建 Version Release 跟踪 issue
发布的第一步是在仓库中创建一个 Version Release issue,用于跟踪整个发布流程。该 issue 承担两重职责:
- 将发布流程拆分为可勾选的 todo 清单(semconv 升级、pre-release、tag、签名、Release、里程碑收尾等);
- 在流程结束时(Post-Release 阶段)勾选并关闭该 issue,作为一次发布闭环的存档。
从文档结构看,issue 与 milestone、CHANGELOG 一起构成“可追溯”的发布证据链:每个 PR、每个 issue 都能对应到它被合入/修复的具体版本。
三、Semantic Convention 升级(前置步骤)
注:原文定义的外部链接(OpenTelemetry Semantic Conventions 规范仓库等)请读者按需在上游查询;下面内容聚焦于本仓库可核对的流程与命令本身。
每次上游 [OpenTelemetry Semantic Conventions] 发布新版本,都意味着 go.opentelemetry.io/otel/semconv 包需要重新生成,以携带新版本的语义约定。
3.1 生成新 semconv 子包
生成操作由 semconv-generate 这个 make target 完成。发布者需要:
- 将
TAG环境变量设置为要生成的 semantic conventions 版本标签; - 在本仓库(otel-go 根目录)执行
make semconv-generate。
文档给出的标准示例:
export TAG="v1.30.0" # Change to the release version you are generating.
make semconv-generate # Uses the exported TAG.
在本仓库 vendored 副本中可以找到该 target 的真实实现:vendor/go.opentelemetry.io/otel/Makefile#L289-L313。实现要点包括:
TAG未设置时直接报错退出(TAG unset: missing opentelemetry semantic-conventions tag),强制发布者显式声明版本;- 通过
semconvkit工具与 weaver 镜像从指定 tag 拉取语义约定 registry 源码并渲染 Go 代码到semconv/<TAG>/目录; - 生成完毕后调用
$(SEMCONVKIT)对产物做后处理。
执行完成后,仓库会新增一个 semconv/<NEW VERSION> 子包。发布者应先确认生成内容正确,再提交 PR 合入。
本仓库 vendored 副本中已存在多个历史版本子包,可作为“生成后应长什么样”的参照物:如 vendor/go.opentelemetry.io/otel/semconv/v1.37.0(含 schema.go、exception.go、attribute_group.go 等)与 vendor/go.opentelemetry.io/otel/semconv/v1.43.0(额外包含 httpconv、otelconv、rpcconv 等转换辅助子包)。
3.2 更新 CHANGELOG
新 semconv 子包加入后,需要同步在 vendor/go.opentelemetry.io/otel/CHANGELOG.md 中登记变更,文档给出的 changelog 条目模板如下:
- 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://gitcode.com/GitHub_Trending/mo/moby/blob/252bd664babaa81e2c579352e78a09bab0160f4f/vendor/go.opentelemetry.io/otel/semconv/v1.37.0/MIGRATION.md?utm_source=gitcode_repo_files) for information on how to upgrade from `go.opentelemetry.io/otel/semconv/<PREVIOUS VERSION>`. (#PR_NUMBER)
Tip: 将 release 与 prior version 替换为实际的版本号。
仓库中的 CHANGELOG 恰好提供了这种条目的实例,例如 v1.45.0/0.67.0/0.21.0/0.0.18 一节中“Add the go.opentelemetry.io/otel/semconv/v1.42.0 package.”的记录;配套的迁移文档也能在本仓库直接看到,例如 vendor/go.opentelemetry.io/otel/semconv/v1.43.0/MIGRATION.md(说明 v1.43.0 可作 v1.42.0 的 drop-in 替代)。
3.3 更新全代码库的 semconv 导入路径
新 semconv module 生成后,需要把整个代码库中所有 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 检查是否存在编译失败或测试失败。
3.4 处理 attribute 变更
某些 semconv 版本可能新增 attribute,或影响当前正在使用的 attribute——变更可能从简单重命名,到更复杂的“合并 attribute / 属性值语义改变”。发布者应将代码迁移到取代旧 attribute 的新 attribute,以贴合语义约定;但考虑到兼容性,旧 attribute 仍可能在 OTEL_SEMCONV_STABILITY_OPT_IN 环境变量的控制下继续被输出。
对于这种迁移应该如何跟踪与执行,文档给出了上游 issue(#7806)作为参考案例,可结合该 issue 了解实践中属性迁移的完整过程。
3.5 Go contrib linter 更新
semconv 版本升级通常还牵动 opentelemetry-go-contrib 仓库:需要在其 .golangci.yml 中强制使用新 semconv 版本,确保 contrib 仓库的静态检查与实际依赖保持一致。
四、Breaking Changes 校验
对外发布公共 API 之前,必须确保没有引入“意外”的破坏性变更。执行:
make gorelease
该 target 调用 gorelease 工具(golang.org/x/exp/cmd/gorelease)比对公共 API 变化。本仓库的 Makefile 中其实现位于 vendor/go.opentelemetry.io/otel/Makefile#L315-L322,它针对所有 Go module 逐一运行 gorelease 输出差异报告。若发现问题,可在上游 golang 的 issue(#26420)处上报或排查。
五、验证对 contrib 仓库的兼容性
若主仓库的改动会影响 contrib 仓库(opentelemetry-go-contrib),发布前需要按 contrib 仓库 RELEASING.md 中 “Verify OTel changes” 一节描述的步骤,验证主仓库改动与 contrib 仓库的兼容性。该步骤的核心价值在于:otel-go 是生态底座,主仓库 API 或 semconv 层面的改动会级联影响上层 instrumentation 库,提前在 contrib 层面跑通编译与测试能显著降低正式发布后的回归风险。
六、Pre-Release(发布前准备)
6.1 决定 module set 并更新 versions.yaml
首先决定本次将发布哪些 module set,并在 versions.yaml 中更新它们的版本号,随后在新分支上提交该变更。
module set 是什么?本仓库 vendored 的 vendor/go.opentelemetry.io/otel/versions.yaml 提供了直观样例:例如 stable-v1 集合当前版本 v1.46.0,成员包含 go.opentelemetry.io/otel 主 module、metric、trace、sdk、sdk/metric、各 OTLP/stdout/zipkin exporter 等;另有 experimental-metrics(v0.68.0)、experimental-logs(v0.22.0)、experimental-schema(v0.0.19)等集合,分别服务于不同稳定性阶段的 API(v1.x 稳定 / v0.x 实验)。这正是“一次发布推进一组 module 到同一版本”的机制来源,也是 CHANGELOG 标题写作 [1.46.0/0.68.0/0.22.0/0.0.19] - <date> 的原因。
6.2 运行 prerelease target
更新子模块的 go.mod,使其依赖下一步即将发生的新版本发布。然后:
-
执行
make prerelease,并指定要发布的 module set。它会创建分支prerelease_<module set>_<new tag>,承载所有发布相关改动:make prerelease MODSET=<module set> -
核对改动,确认所有 module 的版本都被改写为新 tag:
git diff ...prerelease_<module set>_<new tag>确认无误后,将改动合入发布前分支:
git merge prerelease_<module set>_<new tag>
在本仓库 Makefile 中可以查看该 target 的真实执行逻辑:vendor/go.opentelemetry.io/otel/Makefile#L328-L331——它依赖 multimod 工具,先执行 verify-mods,再调用 $(MULTIMOD) prerelease -m ${MODSET};MODSET 未设置会直接报错。multimod 正是依据 versions.yaml 中 module-set 定义完成批量版本改写的核心工具。
6.3 更新 Changelog
- 确保本次发布所有相关变更均已收录,且行文能让非贡献者也读懂。可用如下命令直接审查自上个 tag 以来的提交:
git --no-pager log --pretty=oneline "<last tag>..HEAD" - 将
Unreleased下的所有变更迁移到新的版本小节,标题格式为[<new tag>] - <date of release>。 - 确保新小节位于“released section”注释(如
<!-- Released section -->)之下,以在未来的发布中被自动保护、不被覆盖。 - 更新文末所有相关链接。
本仓库的 vendor/go.opentelemetry.io/otel/CHANGELOG.md 恰好展示了这套机制的最终形态:## [Unreleased] 之下紧跟 <!-- Released section --> 注释与 <!-- Don't change this section unless doing release --> 保护性注释,随后是按时间倒序排列的历史版本小节。
6.4 提交 PR
将改动推送至 upstream 并在 GitHub 创建 Pull Request,PR 描述中必须包含上述整理好的 Changelog 变更内容。
七、Tag:为合并后的 commit 打标签
所有版本变更的 PR 被批准并合并后,即可为合并 commit 打 tag。
IMPORTANT:打 tag 必须与 Pre-Release 步骤使用完全相同的 tag!否则会留下 broken state。只要 pre-release 之后不再改动
versions.yaml,通常不会出错。
IMPORTANT:Go module 目前无法删除被错误标记的版本(上游 golang issue #34189),因此必须确保推送到上游的版本号正确无误,否则将引发难以规避的连带问题。
操作步骤:
-
对每个要发布的 module set,用主分支上合并 PR 的
<commit-hash>执行make add-tags:make add-tags MODSET=<module set> COMMIT=<commit hash>只有当工作目录当前
HEAD不是目标 commit 时才需要显式传COMMIT。 -
将 tag 推送到 upstream remote(注意是上游仓库而非 fork),并确保所有子模块的 tag 一并推送:
git push upstream <new tag> git push upstream <submodules-path/new tag> ...
其底层实现同样位于 vendor/go.opentelemetry.io/otel/Makefile#L333-L337:add-tags 依赖 verify-mods 并调用 $(MULTIMOD) tag -m ${MODSET} -c ${COMMIT},由 multimod 依据 module-set 定义与指定 commit 批量生成各 module 的版本 tag。由于 vendored 副本中 go.mod 的 module 与子目录层级(如 semconv/v1.37.0、semconv/v1.43.0 等独立子 module)清晰可查,可以直观对应“为何需要逐个子 module 分别推送 tag”。
八、签名制品(Sign artifacts)
为遵循 CNCF 最佳实践,需要对发布制品做签名:
- 从 releases tags 页面下载新 release tag 对应的
.tar.gz与.zip归档,两者均需使用发布者的 GPG 密钥签名。签名前可用上游提供的脚本核验归档内容。 - 查看 GPG 密钥 ID:
密钥 ID 即gpg --list-secret-keys --keyid-format=longsec rsa4096/(或类似字段)之后的 16 位字符串。 - 设置环境变量并对两个制品签名:
export VERSION="<version>" # e.g., 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
九、Release:创建 GitHub Release
在 GitHub 上为新 tag 创建 Release,正文应包含本次发布在 Changelog 中的全部 release notes。
IMPORTANT:GitHub Releases 一经创建即不可变(immutable)。签名制品(
.tar.gz、.tar.gz.asc、.zip、.zip.asc)必须在创建 Release 时一并上传,之后无法补充或修改。
十、Post-Release 收尾
10.1 Contrib 仓库发布
验证通过后,需同步为使用本次版本的 contrib 仓库(opentelemetry-go-contrib)制作对应的 release,确保生态版本配套推进。
10.2 官网文档更新
更新 OpenTelemetry 官网中 Go instrumentation 文档页(content/en/docs/languages/go)。重点是:
- 将文中引用的各包版本号提升为本次发布的最新版本;
- 重新验证所有代码示例仍可编译且准确无误。
10.3 收尾 milestone
每次 release 完成后,确保本次发布修复的 issue 与合入的 PR 都被归入对应 milestone,以便追踪每个版本包含了哪些变更:
- 用 GitHub 搜索找出尚未归入 milestone 的已关闭 issue(可加
no:milestone is:closed等过滤条件,并排除Stale标签、只保留linked:pr的问题); - 找出尚未归入 milestone 的已合并 PR(条件类似:
no:milestone is:merged)。
全部关联 issue/PR 归入 milestone 后,关闭该 milestone。
10.4 关闭 Version Release issue
当 Version Release issue 的 todo 清单全部完成后,关闭该 issue,一次完整的发布流程就此闭环。
总结
整个发布流程可以凝练为一条清晰的责任链:
- 跟踪:创建
Version Releaseissue,锁定本次发布范围; - 内容准备:升级 semconv(
TAG+make semconv-generate)→ 迁移导入 → 更新 CHANGELOG,再用make gorelease校验无意外破坏性变更; - 版本改写:更新
versions.yaml→make prerelease MODSET=...批量推进 module 版本 → 合并 PR; - 固化:
make add-tags MODSET=... COMMIT=...打 tag 并推送所有子模块 tag; - 可信分发:GPG 签名
.tar.gz/.zip制品 → 创建不可变的 GitHub Release 并上传签名产物; - 生态收尾:发布 contrib 版本、更新官网文档、归拢并关闭 milestone 与跟踪 issue。
这套流程中反复出现的 versions.yaml、Makefile target(semconv-generate / prerelease / add-tags / gorelease)与 CHANGELOG 约定,都可以在当前仓库 vendor/go.opentelemetry.io/otel 目录下找到真实实现与历史样例,值得结合阅读,从而更准确地把控多 Go module 项目规模化发布时的版本一致性与制品可验证性。
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 StartedRust0629
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