Grafana Loki 发布准备(Prepare Release)流程全解析:基于 release-please 的自动化发布 PR 管线
【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki
本篇指南以 Grafana Loki 仓库的 prepare-release.md 文档为主体,结合仓库内.github/release-workflows.jsonnet、.github/workflows/下的真实工作流文件与 Makefile 相关目标,深入讲解 Loki 如何用 release-please 自动维护"长期运行的发布 PR"、按分支自动区分补丁版/次版本/主版本发布,以及如何为罕见的主版本发布手工生成定制工作流。读完本文,你将掌握 Loki 发布准备管线的完整链路、分支命名与版本策略的对应关系,并能在自己的仓库中复刻这套自动化发布体系。
一、发布准备管线是什么
在 Grafana Loki 中,"发布一个版本"本质上就是合并一个长期运行的发布 PR(long-running release PR)。这个 PR 不是人工临时创建的一次性分支,而是由两条 GitHub Actions 工作流持续维护的"活" PR——每当目标分支有新提交,工作流就会自动重新运行,把最新的提交、版本号、变更日志和构建产物刷新进同一个 PR 中。
这两个工作流的触发条件在仓库的.github/release-workflows.jsonnet中定义(.github/release-workflows.jsonnet):
| 工作流 | 生成的文件 | 触发分支模式 | 版本策略 | 适用场景 |
|---|---|---|---|---|
| 补丁版(Patch) | .github/workflows/patch-release-pr.yml | release-[0-9]+.[0-9]+.x | always-bump-patch | 维护分支上的 bug 修复(如release-3.4.x) |
| 次版本(Minor) | .github/workflows/minor-release-pr.yml | k[0-9]+ | always-bump-minor | 每周发布分支(weekly branch,如k299) |
| 正式发布 | .github/workflows/release.yml | release-[0-9]+.[0-9]+.x、k[0-9]+、main | —— | 合并发布 PR 后真正打出 Release |
从源码结构可以推断:release-[0-9]+.[0-9]+.x是补丁维护分支的命名约定,而k[0-9]+是 Loki 按周切出的"周分支"命名约定,两者分别对应 patch 与 minor 两条发布路径。这条管线每一步做的事情,即文档列出的四项核心工作,会在下文逐一展开。
二、管线执行的四个核心步骤
无论补丁版还是次版本,这套 release-please 驱动的管线都会按顺序完成以下四件事:
- 运行测试与静态检查(Run tests and linting):工作流会先调用
check任务,复用grafana/loki-release仓库中按固定 SHA 引用的检查工作流,注入build_image、golang_ci_lint_version等参数,确保待发布的提交质量过关。 - 为拟发布版本构建二进制与镜像(Build binaries and images):对
dist、loki、logcli、loki-canary、fluentd、fluent-bit、logstash、querytee、loki-docker-driver、loki-helm-test等一系列目标执行构建,产出跨平台产物。 - 基于 Conventional Commits 生成发布说明(Generate release notes):release-please 扫描自上次发布以来的提交,依据约定式提交规范自动归类生成 CHANGELOG。
- 创建或更新长期发布的发布 PR(Create or update the long-running release PR):PR 中会明确"如果合并将发布哪个 commit",并附上已构建产物(artifacts)的链接。
第 3 步依赖的"约定式提交"规范在仓库中有配套的强制检查:.github/workflows/conventional-commits.yml 会在每个 PR 上通过action-semantic-pull-request校验标题格式,并要求标题正文以大写字母开头。这意味着 release-please 能够准确从提交历史中提取 feature / fix / chore 等分类,是自动生成高质量发布说明的前提。
三、从 jsonnet 到工作流:配置源头与生成命令
Loki 的发布工作流并非手写 YAML,而是由 Jsonnet 模板声明式生成。所有发布相关工作流的"单一事实来源"是 .github/release-workflows.jsonnet,其中通过lokiRelease.releasePRWorkflow(...)这个从grafana/loki-release库导入的工厂函数生成补丁版、次版本与正式发布三条工作流。关键的公共参数包括:
branches:工作流监听的分支正则;buildImage:构建用的 Go 镜像(如golang:1.26.6);golangCiLintVersion:golangci-lint 版本(当前为v2.10.1);imageBuildTimeoutMin:镜像构建超时(60 分钟);imageJobs:要构建的镜像清单,覆盖 loki、logcli、loki-canary、fluentd、fluent-bit、logstash、querytee、loki-docker-driver、loki-helm-test 等,并分别指定 amd64/arm64/arm 平台矩阵;imagePrefix:镜像推送前缀(us-docker.pkg.dev/grafanalabs-global/dockerhub-loki-prod-mirror);releaseLibRef:grafana/loki-release依赖库的固定 commit SHA,保证管线可复现;versioningStrategy:补丁版为always-bump-patch,次版本为always-bump-minor。
生成与校验命令
修改.github/release-workflows.jsonnet后,需要运行 Makefile 中的目标重新生成 YAML(Makefile):
# 生成全部 release 工作流到 .github/workflows/ make release-workflows # 校验生成结果是否与仓库当前内容一致(CI 中常用) make release-workflows-checkmake release-workflows内部执行两条命令:先用jb update更新 Jsonnet 依赖,再用jsonnet -SJ .github/vendor -m .github/workflows -V GO_VERSION=$(GO_VERSION) .github/release-workflows.jsonnet把 Jsonnet 模板渲染为-m指定的输出目录下的多个 YAML 文件。release-workflows-check则会重新生成并用git diff --exit-code检查差异,若不一致会提示"Please build release workflows by running 'make release-workflows'"。
此外,Makefile 还提供了 update-loki-release-sha 目标,用于自动把grafana/loki-release依赖更新到最新 commit 并重新生成工作流,保证 release 库的修复能够流入发布管线。
四、release-please 的调用细节:PR 如何被创建与更新
以次版本工作流 .github/workflows/minor-release-pr.yml 为例,其create-release-pr任务在dist等构建任务全部成功之后才运行,核心是一条release-please release-pr命令。值得注意的关键参数:
yarn exec -- release-please release-pr \ --changelog-path "CHANGELOG.md" \ --consider-all-branches \ --group-pull-request-title-pattern "chore${scope}: Release${component} ${version}" \ --label "backport main,autorelease: pending,product-approved" \ --manifest-file .release-please-manifest.json \ --pull-request-footer "Merging this PR will release the artifacts of ${SHA}" \ --release-as "$(version)" \ --release-type simple \ --target-branch "$(branch)" \ --token "$(github app token)" \ --dry-run false--consider-all-branches+--target-branch:让 release-please 在所有分支上独立计算版本,并精确操作当前触发分支;--label:给发布 PR 自动打上backport main、autorelease: pending、product-approved标签,其中backport main意味着合入后会自动回移植到 main 分支;--pull-request-footer:把 PR 尾注写成"合并此 PR 将发布某 commit 的 artifacts 链接",正是文档所述"指示将被发布的 commit 并附带构建产物链接"的落地实现;--release-as:由version任务计算出的拟发布版本号直接指定;- 命令使用 GitHub App(
loki-gh-app)签发的 token 而不是普通 GITHUB_TOKEN,以便绕过仓库对机器人提交的 CI 限制。
从工作流依赖图可以看出,create-release-pr依赖dist、fluent-bit、fluentd、logcli、logstash、loki、loki-canary、loki-canary-boringcrypto、loki-docker-driver、loki-helm-test、querytee等全部构建任务——即"先构建产物、再开 PR",确保 PR 中的产物链接始终有效。
五、构建产物如何产生与存储
构建阶段的实际动作在dist任务中完成(.github/workflows/patch-release-pr.yml):
- checkout 待发布仓库与 release 库;
- 在
golang:1.26.6容器内执行make dist packages,产出二进制包; - 另有一个
continue-on-error: true的可选步骤构建dist/loki-linux-riscv64,即 riscv64 这类非主流架构构建失败不会阻塞整个发布; - 使用
gcloud artifacts generic upload把dist/上传到 Google Artifact Registry(GAR)的generic-loki-dev仓库,--package=binaries、--version=${{ github.sha }},即以 commit SHA 作为产物版本标识。
各镜像任务(loki、logcli、loki-canary 等)则用docker/build-push-action按linux/amd64、linux/arm64、linux/arm平台矩阵分别构建并导出为 tar,再以--package=images上传;loki-docker-driver以type=local输出 rootfs 后打包上传到--package=plugins。这样,合并发布 PR 后,正式发布工作流 .github/workflows/release.yml 就可以按 SHA 从 GAR 下载这些产物直接打 Release,而不必在发布时重新构建,保证"PR 中验证过的产物 == 最终发布的产物"。
六、主版本发布:手工创建定制工作流
主版本(Major)发布与 minor / patch 走完全相同的流程,区别仅在于:主版本不常发生,没有必要让工作流长期保持运行,因此需要为要发布的分支手工创建一条定制工作流。完整步骤记录在 major-release.md 中,操作要点如下:
- 编辑
.github/release-workflows.jsonnet(注意文档中的路径写法对应仓库根目录下的 .github/release-workflows.jsonnet); - 添加一条新的主版本发布工作流。以 3.0 发布为例,模板代码如下:
'three-zero-release.yml': std.manifestYamlDoc( lokiRelease.releasePRWorkflow( branches=['release-3.0.0'], buildImage=buildImage, checkTemplate=checkTemplate, golangCiLintVersion=golangCiLintVersion, imageBuildTimeoutMin=imageBuildTimeoutMin, imageJobs=imageJobs, imagePrefix=imagePrefix, releaseLibRef=releaseLibRef, releaseRepo='grafana/loki', skipArm=false, skipValidation=false, useGitHubAppToken=true, releaseAs='3.0.0', ) + { name: 'Prepare Loki 3.0 release', }, false, false ),- 确保
branches字段指向你要发布的分支(上例为release-3.0.0); - 确保
releaseAs字段设置为你想要的版本号(上例为3.0.0,这是与 patch/minor 工作流最大的区别——主版本必须显式指定,而不是依赖递增策略); - 运行
make release-workflows生成新的工作流文件,并将这次改动同时合并到main 分支和 release 分支; - 建议在同一个 PR 中顺带禁用 patch 发布工作流,理由见下一节。
与补丁发布工作流的竞态问题
新创建的主版本工作流会与 patch 工作流产生竞态(race condition):patch 工作流监听release-[0-9]+.[0-9]+.x模式,而主版本分支release-3.0.0也匹配该正则,两条工作流可能同时尝试更新发布 PR,导致版本号计算或 PR 内容相互覆盖。文档给出了两种解法:
- 禁用 patch 发布工作流,直到主版本发布完成后再恢复;
- 人工盯守发布分支上的所有 Actions(例如
release-3.0.x分支的 runs),发现 patch 工作流触发就手动取消。
从工程实践看,方案一更稳妥,也是文档建议"作为该 PR 的一部分"一并完成的操作。
七、合并发布 PR 之后:正式发布工作流
发布 PR 合入后,release.yml工作流(.github/workflows/release.yml)接管后续动作:通过shouldRelease任务判断当前提交是否应该发布,然后按github.sha从 GAR 下载二进制,检查同名 Release 是否已存在(避免重复发布),再创建(或更新)GitHub Release、推送镜像 tag。至此,"准备(prepare)→ 合并(merge)→ 发布(publish)"三段式发布流程闭环完成,其中本文介绍的 prepare 阶段正是整个链条的入口。
八、在自有仓库复刻这套流程的要点
- 分支即版本策略:用稳定的分支命名约定(如
release-x.y.z模式 + 递增策略)驱动版本管理,避免人工维护版本号; - 配置即代码:把工作流定义收敛到 Jsonnet / 模板文件,用
make目标统一生成与校验,杜绝手改 YAML 造成的漂移; - 先产物后 PR:让发布 PR 的创建依赖全部构建任务,PR 内直接附上可验证的产物链接;
- 固定依赖引用:用 commit SHA 锁定 release 库(
RELEASE_LIB_REF)与构建工具版本,保证任何时刻重跑管线结果一致; - 约定式提交是前提:release-please 的发布说明质量取决于提交信息规范度,务必配套 PR 标题校验(参考 .github/workflows/conventional-commits.yml)。
相关文档与源码索引
- 本文主体文档:prepare-release.md
- 主版本发布步骤:major-release.md
- 工作流声明模板:.github/release-workflows.jsonnet
- 生成的工作流:.github/workflows/patch-release-pr.yml、.github/workflows/minor-release-pr.yml、.github/workflows/release.yml
- 生成与校验命令:Makefile
【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考