chart-releaser-action 底层探秘:chart-releaser CLI 的 package、upload 与 index 三剑客
chart-releaser-action 是一个能把 GitHub 项目一键变成自托管 Helm Chart 仓库的 GitHub Action。许多团队在 workflow 里用它自动发布 Helm Chart,却很少深究它的内部机制。其实,chart-releaser-action 只是一个"编排壳",真正干活的,是它底层调用的 chart-releaser CLI 工具。今天我们就来探秘它的源码,看看 cr package、cr upload、cr index 这三个命令组成的"三剑客",如何把一份 Helm Chart 从本地目录一路送上 GitHub Release 与 GitHub Pages。
一句话概括:chart-releaser-action 用三把剑搞定发布——打包(package)、上传(upload)、建索引(index)。
一、先认识"壳"与引擎:action.yml 和 cr.sh 的分工
在拆解三剑客之前,我们先看清 chart-releaser-action 的整体结构。仓库里有两个关键文件:
- action.yml:GitHub Action 的"说明书",声明了所有输入参数(如
charts_dir、skip_packaging、pages_branch)和输出变量(changed_charts、chart_version)。 - cr.sh:真正的执行脚本,约 360 行 Bash,负责整个发布流程的编排。
cr.sh 的第一步是安装 chart-releaser CLI(默认版本 v1.7.0)。安装函数 install_chart_releaser() 位于 cr.sh:它先检查工具缓存目录,如果没有安装过,就下载 release 压缩包并解压到缓存,再把对应目录加入 PATH。
安装完成后,主流程正式开始,整个发布管线可以浓缩成下面这张表:
| 阶段 | 调用的命令 | 对应函数 | 产出物 |
|---|---|---|---|
| 打包 | cr package | package_chart | .tgz 安装包 |
| 发布 | cr upload | release_charts | GitHub Release |
| 建索引 | cr index | update_index | index.yaml |
这三个命令,就是我们要探秘的"三剑客",下面逐一拆解。
二、第一剑:cr package 命令如何打包 Helm Chart 📦
三剑客的第一剑是 cr package,负责把 charts/ 目录下的 Helm Chart 打包成标准的 .tgz 压缩包。
在 cr.sh 中,package_chart() 函数的实现非常精简:
package_chart() {
local chart="$1"
local args=("$chart" --package-path .cr-release-packages)
cr package "${args[@]}"
}
这里有两个细节值得注意:
--package-path .cr-release-packages:指定打包产物的输出目录。cr.sh 在流程开始前会先清空并重建.cr-release-packages目录(见 cr.sh),保证每次打包都是干净的。- 参数组装:如果配置了
--config(自定义配置文件),也会一并拼进参数里。
对新手来说,可以把这一步理解为"把源码变成安装包"——就像 Java 项目打成 jar、npm 项目打成 tgz 一样,Helm Chart 打成的 .tgz 就是后面所有流程的"弹药"。
三、第二剑:cr upload 命令如何发布 GitHub Release 🚀
有了 .tgz 安装包,第二剑 cr upload 负责把它们发布成 GitHub Release,并作为 Release 的资产(Assets)挂载上去。
release_charts() 函数位于 cr.sh,核心调用长这样:
cr upload -o "$owner" -r "$repo" -c "$(git rev-parse HEAD)"
几个关键参数的含义:
-o owner/-r repo:指定目标仓库。在 action 中,这两个值直接由GITHUB_REPOSITORY环境变量解析而来(见 action.yml)。-c commit:告诉 chart-releaser 当前发布对应的 commit,方便版本追溯。--skip-existing:如果同名版本的 Release 已存在,就跳过上传,避免重复发布报错。--make-release-latest=false:配合mark_as_latest输入,可控制本次 Release 是否标记为 "latest"。
这一步是整个流程中唯一需要写权限的环节,所以 workflow 里记得给 job 加上 contents: write 权限,并提供 CR_TOKEN 环境变量。
四、第三剑:cr index 命令如何生成 index.yaml 索引 🗂️
前两剑解决了"包从哪来、包放哪去"的问题,但 Helm 客户端(helm repo add / helm install)靠什么发现这些包呢?答案是 index.yaml——这正是第三剑 cr index 的职责。
update_index() 函数位于 cr.sh:
cr index -o "$owner" -r "$repo" --push
它的工作分三步:
- 读取 GitHub Releases 上的所有 chart 资产,生成或合并
index.yaml索引文件; - 用
--push参数把索引推送到gh-pages分支; - 之后该分支通过 GitHub Pages 对外提供 HTTP 访问。
这就是为什么 README.md 里强调:你完全不需要在 main 分支维护 index.yaml,它由三剑客自动管理在 gh-pages 分支上。用户只需要一行命令就能安装你的 chart:
helm repo add my-repo https://你的用户名.github.io/你的仓库
helm install my-chart my-repo/my-chart
五、三剑客如何串联?一次 push 引发的发布流水线 🔄
拆完三把剑,我们再看看它们是如何在 main() 函数里被串联起来的。主流程位于 cr.sh,可以概括为 5 个步骤:
- 找基线:
lookup_latest_tag()(cr.sh)获取最近一次发布的 tag; - 找变更:
lookup_changed_charts()(cr.sh)对比当前代码与基线 tag,找出charts/目录下真正发生变化的 chart; - 打包:对每个变更的 chart 调用
package_chart()(第一剑); - 发布:调用
release_charts()(第二剑); - 建索引:调用
update_index()(第三剑)。
整个流程只在"有 chart 变更"时才会执行;如果没有变更,脚本会礼貌地输出 "Nothing to do. No chart changes detected.",不浪费任何构建时间。
另外,cr.sh 还会把本次发布结果写入 changed_charts.txt 和 chart_version.txt,最终由 action.yml 读取并输出为 action 的 changed_charts、chart_version 两个输出变量,方便后续步骤联动(比如发通知、更新下游依赖)。
六、实战技巧:用这些参数灵活控制 chart-releaser CLI ⚙️
理解了底层逻辑,你就能灵活驾驭各种高级场景。下面几个参数值得收藏:
| 参数 | 作用 | 适用场景 |
|---|---|---|
skip_packaging | 跳过打包,只用后两剑 | 想用 helm package 做自定义签名/加密打包 |
skip_existing | 版本已存在则跳过上传 | 多分支、多触发源场景防重复发布 |
skip_upload | 跳过上传与建索引 | 使用 OCI 仓库等不需要 index.yaml 的方案 |
packages_with_index | 把包直接提交进发布分支 | 不想用 GitHub Release,只用 GitHub Pages |
pages_branch | 指定索引推送的目标分支 | 默认 gh-pages,可改成其他分支 |
比如,如果你的团队要求对 chart 包做签名,就可以在 workflow 里设置 skip_packaging: true,先用 helm package --sign 完成自定义打包,再让 chart-releaser-action 只负责 upload 和 index 两个环节——三剑客瞬间变成"双剑合璧",各司其职。
七、结语
通过这次源码探秘,我们可以看到 chart-releaser-action 的设计非常优雅:它把"打包、上传、建索引"三件大事拆成职责单一的三个 CLI 命令,自己只负责编排和参数传递。理解了 cr package、cr upload、cr index 这三剑客,你不仅能用好这个 Action,还能在需要时自定义发布流程,把 Helm Chart 发布彻底玩明白。
想深入了解实现细节?打开仓库里的 cr.sh 从头读一遍,这份不到 400 行的脚本就是最好的教材。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



