Garden Skills CI完整拆解:validate-skills与release-skill双工作流设计指南
【免费下载链接】garden-skillsConardLi's open-source Skills collection, featuring web design, knowledge retrieval, image generation, and more.项目地址: https://gitcode.com/GitHub_Trending/we/garden-skills
Garden Skills是 ConardLi 开源的 AI Agent 技能(Skills)精选合集,内置 Web 设计、知识检索、AI 绘图、视频演示等 5 个可直接安装的技能。它的 CI 体系由 validate-skills.yml 和 release-skill.yml 两条工作流组成,一套负责"把守质量",一套负责"发布交付"。本文将用通俗的方式完整拆解这套 GitHub Actions 双工作流的设计思路,帮助新手理解一个多技能仓库是如何做到"改一处、全库校验、一键发版"的。
项目概览:一个技能,一个独立版本
Garden Skills 的目录结构非常清晰:每个技能都是 skills/ 下的一个独立文件夹,各自带有SKILL.md(技能说明)和manifest.json(名称、版本号、适用 Agent 等元数据)。例如:
- skills/web-design-engineer/ — Web 设计工程师技能
- skills/gpt-image-2/ — AI 绘图提示词技能
- skills/kb-retriever/ — PDF/Excel 知识检索技能
- skills/beautiful-article/ — 精美长文生成技能
- skills/web-video-presentation/ — Web 视频演示技能
关键点在于:版本号不在仓库根部的 package.json 里,而是分散在每个技能的manifest.json中。每个技能独立发版、独立打 tag,互不干扰——这是整套 CI 设计的出发点。
双工作流为什么这样拆?
| 工作流 | 触发时机 | 权限 | 职责 | 副作用 |
|---|---|---|---|---|
| validate-skills | 每个 PR / 推送到 main | contents: read(只读) | 校验 + 冒烟打包 + README 同步检查 | 无,纯检查 |
| release-skill | 推送*-v*格式 tag | contents: write | 打包 zip、生成 Release、回写 README 链接 | 创建 Release、向 main 推送提交 |
拆分成两条工作流的好处一目了然:高频的 PR 校验保持"便宜、快速、无副作用"(源文件注释原话是 "Cheap, fast, no side effects"),而低频的发布流程才拿到写权限,遵循了 CI 安全设计中的最小权限原则。
validate-skills 拆解:PR 阶段的三道关卡
validate-skills.yml 的触发条件限定在路径白名单:只有改动skills/**、scripts/release/**或三个语言的 README 时才会运行,避免无关 PR 浪费 CI 资源。
核心只有一步:npm run validate。查看根 package.json 可以发现它其实是三条检查的串联:
npm run validate # 等价于:npm run list && npm run pack:all && npm run readme:check三道关卡分别是:
清单与结构校验(list-skills.mjs):遍历 skills/ 下所有技能,检查
manifest.json必填字段、名称是否为 kebab-case、版本号是否符合 SemVer、compat里的 Agent 是否在允许列表内,以及SKILL.md等必备文件是否存在。校验逻辑集中在 lib/skills.mjs,零运行时依赖,跑起来飞快。冒烟打包(pack-skill.mjs 的
--all模式):把每个技能真实打包一次成 zip 并计算 SHA-256,确保"能声明、就能打包",把打包失败的问题拦在合并之前。README 同步检查(update-readme.mjs 的
--check模式):README 中每个技能的"下载 v1.x.x .zip"链接是由机器维护的,版本号来源于该技能最新的 git tag,而不是 manifest(因为 manifest 代表"开发中版本",tag 才是"用户真正能下载到的版本")。检查模式只做 diff,不产生任何改动。
一个容易被忽略的细节:checkout 时显式设置了fetch-tags: true。如果忘记拉取 tag,CI 会认为所有技能都"从未发布过",导致 README 检查误报——注释里把这个坑写得明明白白,是新手读 CI 源码时很好的范例。
release-skill 拆解:tag 驱动的自动发版
release-skill.yml 由推送 tag 触发,约定格式为<技能名>-v<语义化版本>,例如:
git tag web-design-engineer-v1.2.0 git push origin web-design-engineer-v1.2.0整个发布流水线共 6 步:
- 解析 tag:用正则严格匹配
<skill>-v<semver>并拆出技能名和版本号,格式不合法直接报错退出。工作流层面先用宽松的*-v*触发,再由这一步做精确校验——这是 tag 过滤不可靠时的稳健做法。 - 确认技能存在:检查
skills/<skill>/目录和manifest.json是否真的存在,防止打错 tag 空转。 - 打包:调用
npm run pack生成dist/release/<skill>-<version>.zip与.sha256。zip 的顶层目录固定为<skill>/,用户解压到.claude/skills/等目录即可直接用。 - 生成 Release Notes:自动寻找该技能的上一个 tag,用
git log生成"自上个版本以来的改动"列表(首次发布则回退到展示全部历史),并附上安装命令和 SHA-256 校验值。 - 创建 Release:用
gh release create把 zip 和校验文件挂到 Release 上,用户获得一个版本被 pin 死、可复现的下载链接。 - 回写 README 并推回 main:先切回默认分支(tag 触发时 HEAD 处于 detached 状态,注释里特别解释了原因),运行
npm run readme:sync刷新三个语言 README 的下载链接,有 diff 才提交推送,保证幂等——连跑两次不会产生多余提交。
维护者视角:一键发版脚本
对贡献者来说,打 tag 这一步也被自动化了。cut-release.mjs 是维护者侧的"一键发版"入口:
npm run release # 交互式选择要发版的技能 npm run release:dry # 只预览计划,不实际执行它先做安全检查(在默认分支、工作区干净、与远端同步),再列出各技能自上次发版以来的提交,让你逐个选择 patch/minor/major 升级,最后把"版本号 bump + README 同步"合并为一个提交,并与所有 tag一次性原子推送,让 CI 看到的始终是自洽的状态。推送完成后打印 Actions 链接,剩下的工作就交给 release-skill 工作流。
这套设计最值得借鉴的 5 个点
- 职责分离 + 最小权限:检查工作流只读,发布工作流可写,权限按风险分级。
- 路径触发:只在相关文件变化时运行,省钱省时。
- tag 即事实来源:README 广告版本以 tag 为准,开发版本与发布版本解耦,杜绝 404 下载链接。
- 幂等脚本:README 同步脚本跑两次不产生 diff,可安全地在 CI 和手工场景复用。
- 零依赖工具链:发布脚本是纯 Node ESM 脚本(scripts/release/),不装任何 npm 包,CI 冷启动极快。
新手快速上手
如果你想本地复现这套校验流程:
- 克隆仓库(如需克隆可使用镜像地址
https://gitcode.com/GitHub_Trending/we/garden-skills); - 安装依赖后运行
npm run validate,体验与 CI 完全相同的三道关卡; - 运行
npm run list查看全库技能的版本与健康状态; - 阅读 CONTRIBUTING.md 了解完整的发版约定。
小结
Garden Skills 用两条轻量工作流就搭出了一条完整的技能发布流水线:validate-skills 在 PR 阶段把关"能不能合",release-skill 在 tag 阶段自动完成"怎么发出去"。对管理多版本、多组件的开源仓库来说,这套"校验与发布分离、tag 驱动、脚本幂等"的模式非常值得直接抄作业。
【免费下载链接】garden-skillsConardLi's open-source Skills collection, featuring web design, knowledge retrieval, image generation, and more.项目地址: https://gitcode.com/GitHub_Trending/we/garden-skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考