☰
opentelemetry-go 发布流程完全指南:从 Semantic Convention 升级到多模块 Tag 与签名制品的端到端实践
2026/10/15 20:23:33 网站建设 项目流程
  • 开发工具
  • 云原生
  • 微服务

【免费下载链接】tilt

Define your dev environment as code. For microservice apps on Kubernetes.

项目地址:https://gitcode.com/gh_mirrors/tilt/tilt
点击查看免费下载

本文基于仓库中随附的 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 驱动。其核心步骤为:

  1. 将TAG环境变量设置为要生成的目标 Semantic Conventions tag;
  2. 在本仓库中运行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 两个关键约束

官方文档以加粗形式强调了两条硬性约束:

  1. 必须使用与 Pre-Release 阶段完全相同的 tag。如果在 Pre-Release 与打 Tag 之间修改了versions.yaml,会留下损坏状态;
  2. 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 最佳实践,发布制品需要签名。具体操作是:

  1. 从 tags 页面下载本次发布 tag 对应的.tar.gz与.zip两个源码归档;
  2. 两者均需使用你的 GPG 密钥签名。签名前可先借助第三方校验脚本(attest-sh)核对归档内容;
  3. 查找自己的 GPG 密钥 ID:
gpg --list-secret-keys --keyid-format=long

密钥 ID 是sec rsa4096/(或类似输出)之后的 16 位字符串。

  1. 设置环境变量并分别对两个归档签名:
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
  1. 验证签名:
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 项目的发布纪律:

  1. 单一事实来源:版本号集中在versions.yaml,所有模块版本由multimod工具统一替换,避免手工改版本号导致的不一致;
  2. 可逆操作前置、不可逆操作后置:先验证(gorelease、contrib 兼容性、git diff 审查),再执行不可逆动作(打 tag、创建 Release、上传制品);
  3. 变更可追溯:CHANGELOG 的Released section受脚本保护、milestone 归位、Version Releaseissue 全程跟踪,任何一步都留下审计痕迹;
  4. 下游兼容优先:semconv 属性升级遵循OTEL_SEMCONV_STABILITY_OPT_IN兼容通道,破坏性变更必须在 CHANGELOG 中以醒目方式声明(如 sdk/metric 默认基数上限),给下游(如 tilt)留出升级窗口。

按照本文的步骤执行,即可完整复现 opentelemetry-go 官方仓库的规范化发布流程。

  • 开发工具
  • 云原生
  • 微服务

【免费下载链接】tilt

Define your dev environment as code. For microservice apps on Kubernetes.

项目地址:https://gitcode.com/gh_mirrors/tilt/tilt
点击查看免费下载
上一篇:Summarize 接入 NVIDIA Parakeet/Canary ONNX 本地转写:外部 CLI 集成、自动下载与回退链路全解析
下一篇:micropython-mqtt:打造终极抗干扰MQTT通信!自动恢复WiFi与 broker 断线的完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询