LobeHub 版本发布工作流:Minor/Patch 双轨自动化与 GitHub Release 编写规范
本文以 LobeHub 仓库内的
version-release技能(.agents/skills/version-release/SKILL.md)为骨架,完整讲解该仓库"双分支 + CI 自动打标"的版本发布体系:如何发起 Minor(特性)发布、Patch(周更/Hotfix/模型上线/数据库迁移)发布,auto-tag-release.yml的触发判定优先级,以及面向 GitHub Release 的长/短两种 changelog 编写规范。读完你将能够在 LobeHub 的 canary/main 分支模型下,独立走完一次"开分支 → 写发布说明 → 合并触发自动发版"的完整流程,并且让 AI Agent 也能按同样的规则参与发布。
一、发布技能是什么:一个"路由 + 引用"式 Agent Skill
在 LobeHub 仓库的 .agents/skills/ 目录中沉淀了大量给 AI Agent(以及人类开发者)使用的可执行规范。version-release 是其中之一,它的定位在 SKILL.md 的 frontmatter 中写得很清楚:
- name:
version-release - description:版本发布工作流——包括发布流程与 GitHub Release 编写(注意:不是
docs/changelog/*.mdx站点变更日志) - argument-hint:
[minor|patch] [version?],即调用形态为/version-release minor v2.2.0之类 - disable-model-invocation: true:该技能不允许模型主动唤起,必须由用户显式请求
SKILL.md 自身只是一个"路由器"(router),真正的操作细节全部下沉在 references/ 中,避免单个文件臃肿且便于复用:
| 引用文件 | 职责 |
|---|---|
| references/minor-release.md | Minor(v{x.y.0})发布的完整步骤与硬规则 |
| references/patch-release-scenarios.md | 四种 Patch 场景:周更、Bug Hotfix、新模型上线、DB Schema 迁移 |
| references/release-notes-style.md | GitHub Release 说明的编写标准(长文版 + 短变体 + 模板) |
| references/changelog-example/ | 三个实例:周更、hotfix、db-migration 各一 |
此外 SKILL.md 还强调了两个边界:
- 范围边界:本技能只负责①发布分支 / PR 流程、②CI 触发约束(
auto-tag-release.yml)、③GitHub Release 编写。若要写网站上的docs/changelog/*.mdx页面,应改而加载同级的docs-changelog技能(.agents/skills/docs-changelog/SKILL.md)——两条内容管线互不混淆。 - 强制伴随文件:每次执行
/version-release都必须先加载并应用仓库根目录的 DESIGN.md,以保证发布文案的 Voice & Content(语气与内容)与项目整体一致。
从源码结构看,仓库在 package.json 中提供了对应的辅助脚本,是这套手动流程的脚本化封装:
"hotfix:branch": "tsx ./scripts/hotfixWorkflow/index.ts",
"release:branch": "tsx ./scripts/releaseWorkflow/index.ts"
其中 bun run release:branch 为交互式、bun run release:branch --minor 可直接指定 minor(见 minor-release.md),bun run hotfix:branch 对应 hotfix 场景(见 patch-release-scenarios.md)。
二、发布模型总览:canary 开发、main 发布、CI 自动打标
技能文档明确给出 LobeHub 的发布主模型,这也是理解整篇工作的前提:
- 主开发分支是 canary,日常所有开发都合入 canary;
- 发布时把 canary 合入 main;
- 合并后,
.github/workflows/auto-tag-release.yml自动完成:打标签 → 升版本号 → 创建 GitHub Release → 回同步到 canary。
实践中只用两种发布类型(major 极少出现,文档明确可以忽略):
| 类型 | 用途 | 频率 | 源分支 | PR 标题格式 | 版本号 | 参考文档 |
|---|---|---|---|---|---|---|
| Minor | 特性迭代发布 | 约每 4 周 | canary | 🚀 release: v{x.y.0}(严格) |
手动指定 | references/minor-release.md |
| Patch | 周更 / hotfix / 模型 / DB 迁移 | 约每周或按需 | canary 或 main | 自定义(如 🚀 release: 20260222) |
自动 patch +1 | references/patch-release-scenarios.md |
以仓库当前状态为例,package.json 中 version 为 2.2.14——也就是说当下一次 Minor 发布时,期望推进到 2.3.0;而任意一次 Patch 发布则会把 2.2.14 自动推进到 2.2.15。
Minor 与 Patch 的本质差异在于版本号由谁决定:Minor 的精确版本号写在 PR 标题里由 CI 解析;Patch 则完全不需要在标题里带版本号,由 CI 依据 main 上现有版本自动 patch +1。
三、CI 自动发版触发规则:读懂 auto-tag-release.yml 的判定优先级
整条自动化链路的入口是 .github/workflows/auto-tag-release.yml。先看它的骨架配置:
- 触发事件为
pull_request_target,types: [closed],仅监听目标分支 main; - Job 内第一行硬门禁:
if: github.event.pull_request.merged == true,即只有被合并的 PR 才可能触发发版,被关闭/驳回的 PR 不触发; permissions.contents: write+ 使用secrets.GH_TOKEN,且actions/checkout@v6使用fetch-depth: 0拉取完整历史,保证打标与比较范围的准确性。
合并后,CI 按以下优先级判定是否发版(对应 SKILL.md 与 workflow 中的三段检测逻辑):
1. Minor 发布(标题精确版本号,最高优先级)
检测 PR 标题是否匹配严格正则:
^🚀[[:space:]]+release:[[:space:]]*v([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?)$
命中即 should_tag=true、KIND=release,版本号取自标题捕获组。注意这里正则允许 -prerelease / +build 后缀,但文档约定日常 Minor 一律使用干净的 v{x.y.z} 格式。
2. Patch 发布(自动 patch +1,次级优先级)
只有在上一步未命中的情况下才进入此判定,且内部仍分两级:
-
分支名优先:head 分支为
hotfix/*或release/*→ 直接触发,跳过标题检测(title gate bypassed); -
标题前缀兜底(legacy 行为):PR 标题以以下任一 gitmoji/前缀开头即触发——
style/💄 stylefeat/✨ featfix/🐛 fixrefactor/♻️ refactorhotfix/🐛 hotfix/🩹 hotfixbuild/👷 build
(workflow 中的实际正则还允许
(scope)形式如feat(agent): …,并忽略大小写。)
3. 不触发
其余前缀(如 docs、chore、ci、test)的 PR 合入 main 后不会触发发版。
Patch 版本号如何"自动 +1"
看 workflow 的 Resolve patch version 步骤:CI 读取当前 package.json 版本,先用 npx semver@7 "${CURRENT_VERSION}" -c 将预发布版本归一到稳定基线(文档注释举例:2.0.0-beta.1 → 2.0.0),再执行 -i patch 步进补丁号(→ 2.0.1)。这也解释了为何 main 上可能存在带 -canary* / -nightly* 后缀的 tag,而发布版本计算要特意与它们区隔。
合并后的自动化动作序列
should_tag=true 且目标 tag 尚不存在(workflow 中先做 git rev-parse v$VERSION 幂等检查)时,依次执行:
- Bump
package.json,提交信息固定为🔖 chore(release): release version v{x.y.z} [skip ci]([skip ci]用于避免再次触发 CI 环); - 生成并更新静态 changelog:
bun run workflow:changelog:gen与bun run workflow:changelog(对应 package.json 中的changelogWorkflow脚本,产物含CHANGELOG.md与changelog/); - 创建 annotated tag
v{x.y.z},锚点是版本号 bump 提交的 SHA(而非 PR 的 merge commit),tag 信息同时记录 PR 号与作者; - 创建 GitHub Release(
softprops/action-gh-release),引用 PR 描述作为发布正文; - Dispatch
sync-main-to-canary(workflow 文件sync-main-to-canary.yaml),把 main 的新 tag 与版本变更回同步到 canary,保证两条分支版本一致。
四、Minor 发布:从 canary 开分支,标题承载精确版本
Minor 发布面向约四周一次的特性里程碑。完整步骤记录在 references/minor-release.md,全程要点如下。
Step 1:从 canary 创建发布分支
git checkout canary
git pull origin canary
git checkout -b release/v{version}
git push -u origin release/v{version}
Step 2:确定版本号 —— 读取 package.json 当前版本并计算下一个 minor(文档示例:2.1.x → 2.2.0)。
Step 3:向 main 发起 PR,标题必须携带精确版本号
gh pr create \
--title "🚀 release: v{version}" \
--base main \
--head release/v{version} \
--body-file release_body.md
⚠️ 硬性要求:PR 标题必须严格匹配
🚀 release: v{x.y.z}格式,因为 CI 就是靠对这个标题跑正则来确定精确版本号。任何偏离都会"跌落"到 patch 检测逻辑,导致发布类型与版本号错误。
Step 4:PR 正文即发布说明 —— 按下一节的 release-notes-style.md 编写,比较基线取 main 上最新的 semver tag(git describe --tags --abbrev=0 origin/main)。
Step 5:合并后全自动 —— auto-tag-release 识别标题 → bump package.json → 打 v{x.y.z} tag → 建 GitHub Release → dispatch sync-main-to-canary。
Minor 专属硬规则:标题格式严格;禁止手动改 package.json 版本(CI 会 bump);禁止手动建 tag(CI 会打);Highlights 条目数通常为 8–12 条。
五、Patch 发布的四种场景
Patch 场景统一自动 bump patch 版本(如 2.1.31 → 2.1.32),PR 标题无需携带版本号。详细步骤在 references/patch-release-scenarios.md,文档按场景拆成四种。
1. 周更(canary → main),最常用
汇总 canary 一周变更并发布到 main。
git checkout canary
git pull origin canary
git checkout -b release/weekly-{YYYYMMDD}
git push -u origin release/weekly-{YYYYMMDD}
扫描变更并撰写 changelog 时有个关键坑:比较基线必须现算,绝不能沿用上一次周更的 tag。因为周更之间 main 上可能直接合入了 hotfix(如 v2.1.54、v2.1.55…),它们又经 sync-main-to-canary 回灌到 canary,所以 main 上最新的 semver tag 才是正确的 prev tag——沿用旧周更 tag 会静默漏计提交,并把过期版本写进 "Since v…"。
git fetch origin main canary --tags
PREV_TAG=$(git describe --tags --abbrev=0 origin/main --match 'v*.*.*' --exclude '*-canary*' --exclude '*-nightly*')
git log "$PREV_TAG..origin/release/weekly-{YYYYMMDD}" --oneline --no-merges
git diff "$PREV_TAG...origin/release/weekly-{YYYYMMDD}" --stat
随后 PR 标题用 🚀 release: {YYYYMMDD} 格式,body 携带 changelog;合并后 CI 识别 release/* 分支 → 自动 patch +1。
2. Bug Hotfix:从 main 直发
紧急缺陷修复,直接在 main 上发版:
git checkout main
git pull --rebase origin main
git checkout -b hotfix/v{version}-{short-hash}
git push -u origin hotfix/v{version}-{short-hash}
PR 标题要求带 gitmoji 前缀(如 🐛 fix: description);正文按 references/changelog-example/hotfix.md 写精简 hotfix changelog:scope 一行 + 1–3 条修复 bullet(症状与修复各一句)+ 升级说明 + owner,不做长篇根因分析(根因留在 commit message 中)。Owner 必须是真实 PR 作者,通过 gh pr view <number> --json author --jq '.author.login' 取,禁止硬编码用户名。合并后 CI 识别 hotfix/* 分支 → 自动 patch +1。
3. 新模型上线:无需特设流程
社区贡献者以 ✨ feat: add xxx model、💄 style: support xxx models 这类标题提交普通 feature PR 即可——因为这些前缀(feat / style)都在自动触发清单里,合并即自动 patch +1,不需要特殊分支命名或人工发布步骤。对 Agent 而言,被要求添加模型支持时也只管创建一个普通 feature PR。
4. DB Schema 迁移:独立发版并给自托管用户单独说明
需要独立发布的数据库结构变更:
git checkout main
git pull --rebase origin main
git checkout -b release/db-migration-{name}
git cherry-pick <migration-commit-hash>
git push -u origin release/db-migration-{name}
PR 标题用 👷 build: {migration description};changelog 必须解释:新增/修改/删除的表与列、迁移是否向后兼容、自托管用户需要执行的动作;Owner 同样取自真实作者。合并后 CI 识别 release/* → 自动 patch +1。
所有发布类型的统一 Precheck
技能文档规定,创建发布分支前必须先验证源分支正确:
- 周更分支(
release/weekly-*)必须从 canary 切出; - 其余 release/hotfix 分支必须从 main 切出,并用
git merge-base --is-ancestor main <branch> && echo OK验证; - 若基线分支错误,须从正确的基重建,而不是继续沿用。
所有发布类型的统一硬规则
- 禁止手动改
package.json版本——CI 负责; - 禁止手动创建 tag——CI 负责;
- Minor PR 标题格式严格(
🚀 release: v{x.y.z}); - Patch PR 无需显式版本号;
- 发布信息必须事实准确,禁止虚构指标与可用性声明(详见下一节的数据溯源硬规则)。
六、GitHub Release 编写标准:数据可溯源 + 长/短两种体例
发布说明的统一规范集中在 references/release-notes-style.md。它的风格定位是:顶部数据驱动(日期、范围、关键指标)→ 叙事优先、结构化细节随后 → 深但可扫读 → 贡献者前置。
写作前必取的五类输入
- 比较范围(
<prev_tag>...<current_tag>) - 发布指标(提交数、合并 PR 数、解决问题数、贡献者数,可选增删行数)
- 各领域高影响变更(核心循环、平台/网关、UX、工具链、安全、可靠性)
- 贡献者名单
- 已知风险 / 迁移 / 发布说明(如有)
若指标无法可靠计算,宁缺毋滥,省略而不是猜。
计算输入的硬规则:一律来自 git,禁止脑补
文档直言:"编造的 PR 号和错误的 'Since v…' 基线是本技能的第一大失败模式"。因此:
① 比较基线 = main 上最新的 semver tag(前文已述的 PREV_TAG 公式),并须执行可达性校验:
git merge-base --is-ancestor "$PREV_TAG" origin/release/weekly-{YYYYMMDD} && echo OK
校验失败即停止并询问用户——说明发布分支基线错了。
② 正文里每个 (#XXXX) 必须来自提交主题,绝不从描述推断:
git log "$PREV_TAG..origin/release/weekly-{YYYYMMDD}" \
--pretty=format:'%s' --no-merges \
| grep -oE '\(#[0-9]+\)$' \
| sort -u > /tmp/release_prs.txt
凡是写进 body 的 (#XXXX) 都必须出现在该文件中,无例外。文档甚至警告"记忆中的 PR 号约一半是错的",必须按 feature 关键词反查 commit hash、读真实 subject。
③ 指标一律用 git 计数:
PR_COUNT=$(wc -l < /tmp/release_prs.txt | tr -d ' ')
COMMIT_COUNT=$(git log "$PREV_TAG..origin/release/weekly-{YYYYMMDD}" --no-merges --pretty=format:'%h' | wc -l | tr -d ' ')
CONTRIBUTOR_COUNT=$(git log "$PREV_TAG..origin/release/weekly-{YYYYMMDD}" --no-merges --pretty=format:'%an' \
| sort -u \
| grep -viE '^(lobehubbot|LobeHub Bot|renovate\[bot\])$' \
| wc -l | tr -d ' ')
④ 作者名 → GitHub 账号映射:git %an 是提交者显示名而非 GitHub 账号(如 YuTengjing 实为 @tjx666),必须用 gh pr view "$PR_NUMBER" --json author --jq '.author.login' 逐一确认。
⑤ 发布前强制校验:把 body 中所有 PR 引用与实际范围内集合做 diff,凡"正文有但范围没有"的输出必须为空:
grep -oE '#[0-9]+' release_body.md | sort -u > /tmp/body_prs.txt
sed 's/[()]//g' /tmp/release_prs.txt > /tmp/release_prs_clean.txt
echo "=== In body but NOT in actual range (must be EMPTY) ==="
comm -23 /tmp/body_prs.txt /tmp/release_prs_clean.txt
非空 = 正文引用了未在本范围内合并的 PR,必须停下修正后再发布。
长文版体例(Minor / Weekly 通用)
标准段落顺序为:
# 🚀 LobeHub Release (<YYYYMMDD>)- 元信息行:
Release Date、Since <Previous Version>指标 - 一段引用的发布主旨(1–2 行)
## ✨ Highlights(大版本 6–12 条,周更 3–8 条)- 按领域分块,可用
###子节:## 🏗️ Core Agent & Architecture## 📱 Platforms / Integrations## 🖥️ CLI & User Experience## 🔧 Tooling## 🔒 Security & Reliability## 📚 Documentation(有意义时才加)
## 👥 Contributors**Full Changelog**: <prev>...<current>
长文建议在主要板块间使用 --- 分隔。完整可复制的骨架模板见该文档的 ## Template 一节,写作与样式规则也值得直接引用:不得有无法溯源的指标、每条高亮都必须"能力 + 影响"、从用户/操作者视角而非内部视角行文、安全问题必须显式标注、术语全局一致、迁移/破坏性变更不许埋没。
周更的参考实例在 references/changelog-example/weekly-release.md,可见"96 commits · 58 merged PRs · 31 resolved issues · 17 contributors"这类指标行的真实呈现方式,以及按核心架构 / 网关集成 / CLI 体验 / 工具链 / 安全可靠性划分的领域块写法。
短体例变体:Hotfix 与 DB Migration
长文体例不适用于短发布,两种短变体直接覆盖它:
Hotfix 变体——正文短、面向运维、无 Highlights/领域块/贡献者列表。必需段落顺序:
# 🚀 LobeHub Release (<YYYYMMDD>)**Hotfix Scope:**(一行概括回归范围,取代长文的Release Date/指标行)- 一段引用的主旨(描述"已恢复什么")
## 🐛 What's Fixed:1–3 条,格式**<symptom>** — <fix>. (#PR)## ⚙️ Upgrade:自托管与云端的升级动作## 👥 Owner:单个@handle(真实 PR 作者)
实例见 references/changelog-example/hotfix.md:它展示了"Agent 切换时残留 topic 状态"这类回归的 scope 行、修复 bullet 与升级说明的标准写法,以及 {pr-author} 占位符的使用方式(务必替换为 gh pr view 查到的真实作者)。
DB Migration 变体——以操作者影响为头条:
- 标题 + scope 行
Migration overview:新增/修改/删除的表与列Operator impact:是否向后兼容、自托管必须的动作Rollback / backup note:如何回滚## 👥 Owner:单个 PR 作者
实例见 references/changelog-example/db-migration.md:它演示了"新增 5 张 agent eval 表 + 2 个索引"这类迁移的声明方式,并明确"迁移在应用启动时自动执行、标准部署无需手写 SQL、低峰窗口发布并先做快照、失败勿反复重试而是查日志与锁状态"。
贡献者排序规则
呈现为单一扁平列表(不再分 Community / Core Team 小节),排序为:社区贡献者在前、团队成员在后,组内按 PR 数降序;@lobehubbot、renovate[bot] 等机器人单独放 "maintenance" 一行。文档内置了一份 LobeHub 团队名册(如 @arvinxx、@Innei、@tjx666、@LiJian 等约 11 人),用于自动判定贡献者归属;名单之外的新贡献者默认按社区成员处理,并应询问用户是否将其加入名册。注意名册还标注了若干"提交作者名 ≠ GitHub 账号"的特例,再次强调必须用 gh pr view 解析账号。
体量启发式
- Minor / 重大里程碑:长文 + 多领域块,Highlights 8–12 条;
- 周更:长文骨架但减少子节,Highlights 4–8 条;
- Hotfix:短体例,1–3 条修复 bullet,正文一屏内;
- DB 迁移:短体例,必须有 Migration overview、操作者影响与回滚/备份说明。
各体例末尾还附有 Quick Checklist(长文与 hotfix 各一份),例如"PREV_TAG 必须是 git describe 结果而非上周更 tag""正文 (#XXXX) 全部经 comm -23 验证""账号经 gh pr view --json author 解析"等,可当作发布前的自检清单直接复用。
七、Agent 行动指南:把整套流程固化为可执行步骤
综合 SKILL.md 的 Agent Action Guide,当用户提出发布请求时,标准动作序列是:
- Precheck:按发布类型校验源分支(周更从 canary、其余从 main),错误则重建;
- Routing:按类型选择并端到端遵循对应引用文档——
- Minor → references/minor-release.md
- Patch(周更 / hotfix / 模型上线 / DB 迁移)→ references/patch-release-scenarios.md
- 撰写 PR 正文 / Release 说明(任意类型)→ references/release-notes-style.md
- 遵守全局硬规则:不动
package.json、不手动打 tag、Minor 标题严格、Patch 不带版本号、发布数据一律以git为源。
这套设计对开发者的意义在于:把"人脑中的发布经验"沉淀成仓库内可审计、可被 Agent 复用的文档化流程,再配合 auto-tag-release.yml 把最易出错的"版本计算 + 打标 + 发布 + 分支回同步"环节交给 CI 幂等完成,人(或 Agent)只需要保证"分支正确、标题合规、正文数据可溯源"三件事。
关联阅读:发布完成后如需在官网书写面向用户的变更日志页面,请遵循 .agents/skills/docs-changelog/SKILL.md(其产物对应 docs/changelog 目录下的
.mdx文件),与本文所述的 GitHub Release 说明是两条相互独立的内容管线。
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 StartedRust0624
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