LobeHub Minor Release 工作流实战指南:从 canary 分支到 v2.2.0 的自动化发布全流程
本指南以 LobeHub 仓库中的 Minor Release(次版本迭代发布)工作流为核心,完整讲解一条「从 canary 分支拉出 release 分支 → 创建带精确版本号的 PR → CI 依据 PR 标题自动完成版本号提升、打标签、生成 GitHub Release 并回同步代码」的工程化发布流水线。读完你将掌握 Minor Release 的每一步命令行操作、PR 标题的严格格式约束、与 Patch/Weekly/Hotfix 发布的关系,以及它背后的 auto-tag-release.yml 触发原理与 release-notes 写作规范,可直接应用于你所在团队的版本发布实践。
一、Minor Release 在 LobeHub 版本体系中的定位
LobeHub 的主开发分支是 canary,日常开发全部汇聚于此。发布时以 canary 为源拉出发布分支,合并进 main,随后由名为 auto-tag-release 的 CI 工作流自动完成后续全部动作。相关的完整说明沉淀在 版本发布 Skill 入口 及其 references 目录 中。
从 SKILL.md 的概览表可以看到,实际使用中主要只有两种发布类型(major 极少出现,可忽略):
| 类型 | 适用场景 | 频率 | 源分支 | PR 标题格式 | 版本号 |
|---|---|---|---|---|---|
| Minor | 特性迭代发布 | 约每 4 周 | canary | 🚀 release: v{x.y.0} |
人工设定 |
| Patch | 周更 / 热修复 / 模型 / DB 迁移 | 约每周或按需 | canary 或 main | 自定义(如 🚀 release: 20260222) |
自动 patch +1 |
Minor Release 是"特性迭代发布"的载体:当一批新功能在 canary 上积累到可发布的里程碑时(例如 v2.1.x → v2.2.0),便按本流程发布。它的关键特征是版本号由人精确指定——这与 Patch 由 CI 自动 patch +1 的机制形成鲜明对比。
二、发布前的分支预检(所有发布类型的通用前置)
在创建发布分支前,必须核验源分支是否正确,这是 SKILL.md 中规定的强制预检:
- Weekly Release(
release/weekly-*):必须从canary拉分支; - 其他所有 release / hotfix 分支:必须从
main拉分支,并验证祖先关系:
git merge-base --is-ancestor main <branch> && echo OK
若分支基于错误的源,必须从正确基线重建。这一步能避免把尚未评审的代码意外带入发布线。
三、Minor Release 五步操作流程
minor-release.md 给出了完整的执行步骤,下面逐条展开并补充底层细节。
第 1 步:从 canary 拉出 release 分支
git checkout canary
git pull origin canary
git checkout -b release/v{version}
git push -u origin release/v{version}
分支命名规范为 release/v{version},例如 release/v2.2.0。务必先 git pull 同步最新的 canary 状态,保证发布分支包含当前全部待发布特性。
第 2 步:确定版本号
读取 package.json 中的当前版本,计算下一个 minor 版本:例如当前为 2.1.x,则下一次 minor 为 2.2.0(patch 位置归零)。
这一"由人算版本号"的过程在仓库脚本中也有对应的自动化实现:scripts/releaseWorkflow/index.ts 使用 semver.inc(currentVersion, type) 计算新版本,并在交互式确认面板(consola.box)中展示 Current / New / Type / Branch / Target 信息后再执行创建分支与提 PR 的动作。也就是说,仓库里提供了一条便捷的命令行脚本帮你完成"算号 + 拉分支 + 提 PR"的组合操作。
第 3 步:向 main 创建 PR
gh pr create \
--title "🚀 release: v{version}" \
--base main \
--head release/v{version} \
--body-file release_body.md
[!IMPORTANT] PR 标题必须严格匹配
🚀 release: v{x.y.z}格式。CI 通过对标题做正则匹配来确定精确的版本号,任何格式偏差都会"落入 patch 检测"分支,导致发布类型被误判。
第 4 步:撰写 PR 正文(即发布说明)
PR body 需要按照 release-notes-style.md 的规范撰写,因为该 body 在合并后会被 CI 直接用作 GitHub Release 内容。比较基线(compare base)取 main 上最新的 semver tag:
git fetch origin main canary --tags
PREV_TAG=$(git describe --tags --abbrev=0 origin/main --match 'v*.*.*' --exclude '*-canary*' --exclude '*-nightly*')
echo "$PREV_TAG"
并验证该 tag 可从发布分支到达:
git merge-base --is-ancestor "$PREV_TAG" origin/release/weekly-{YYYYMMDD} && echo OK
为什么不能用"上一个 Weekly 的 tag"? 在两次 Weekly 之间,hotfix(如
v2.1.54、v2.1.55)会直接合入 main,再经由sync-main-to-canary回灌到 canary。因此 main 上最新的 semver tag 才是正确的"上一版本",误用上一次 Weekly 的 tag 会造成提交区间漏算、Since v…版本号陈旧。
第 5 步:合并后的自动触发
PR 合并后无需人工干预,auto-tag-release 会自动完成:版本号提升、打 annotated tag、创建 GitHub Release、触发 sync-main-to-canary 回灌分支。这部分机制详见下文第五节。
四、配套脚本:release:branch
除了手写 git/gh 命令,仓库还封装了交互式脚本,入口注册于 package.json:
bun run release:branch # 交互式选择版本类型
bun run release:branch --minor # 直接指定 minor
对应实现位于 scripts/releaseWorkflow/index.ts,脚本的执行链路为:
checkGitRepo()校验当前目录是 Git 仓库;- 拉取并切换到源分支(默认实现对应开发主干);
getVersionTypeFromArgs()解析--patch/--minor/--major参数,无参数时进入selectVersionTypeInteractive()交互选择;- 基于 package.json 当前版本用 semver 计算新版本号,交互面板展示发布信息并二次确认;
createReleaseBranch()创建release/v{version}分支并推送;createPullRequest()调用gh pr create,标题固定为🚀 release: v${version},目标分支--base main,并附带--label "release"。
注意:该脚本内部仍保留早期以 dev 分支为开发主干的命名习惯,而当前 版本发布 Skill 规定的主开发分支是 canary,实际执行发布时应以 Skill 文档的 canary 说明为准。
五、合并后 CI 到底做了什么:auto-tag-release 触发规则
Minor Release 的"版本号取自 PR 标题"这一设计,在 .github/workflows/auto-tag-release.yml 中有精确的代码级证据。该工作流监听对 main 分支的 PR 关闭事件(pull_request_target + closed),且仅在 github.event.pull_request.merged == true 时执行。
检测优先级
CI 依据以下优先级判定是否发布(见 auto-tag-release.yml):
1. Minor Release(标题精确取号)
对 PR 标题执行严格正则匹配:
if [[ "$PR_TITLE" =~ ^🚀[[:space:]]+release:[[:space:]]*v([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?)$ ]]; then
命中 🚀 release: v{x.y.z}(支持 -prerelease 或 +build 后缀的可选扩展),则从标题提取版本号写入 version 输出。这正是 minor-release.md 强调"标题格式严格"的原因——正则一旦失配,should_tag 即为 false。
2. Patch Release(自动 patch +1),按以下优先级:
- 分支名命中:head 分支为
hotfix/*或release/*时直接触发,绕过标题检测; - 标题前缀兜底:标题以
style/feat/fix/refactor/hotfix/build(含对应 gitmoji 表情前缀)开头时触发。
3. 不触发:docs、chore、ci、test 等前缀合入 main 不会触发发布。
Patch 版本的解析方式
Patch 场景下版本号不用写进标题,CI 从 package.json 读取当前版本,先 npx semver -c 收敛到稳定基线(如 2.0.0-beta.1 → 2.0.0),再执行 -i patch 得到下一 patch(→ 2.0.1)。对比可见:Minor 由标题注入版本,Patch 由仓库现状推导版本,两条路径在 Set context 步骤汇聚为统一的 VERSION 与 KIND 环境变量。
发布后的自动动作
当 should_tag=true 且目标 tag 尚不存在时(git rev-parse v$VERSION 探测防重),CI 依次执行(auto-tag-release.yml):
- 提升 package.json 版本:写入新版本并提交
🔖 chore(release): release version v{x.y.z} [skip ci]; - 生成 changelog:调用
bun run workflow:changelog:gen与bun run workflow:changelog(对应 scripts 下的 changelogWorkflow),更新根目录 CHANGELOG.md 与 changelog 目录; - 创建 annotated tag:
git tag -a "v$VERSION",tag 消息中携带发布 PR 号与作者,然后推送到远端——注意 tag 打在版本提升后的提交 SHA上,而非 PR 的 merge commit; - 创建 GitHub Release:通过
softprops/action-gh-release以 PR 描述作为 Release body 发布; - 回灌分支:调用
gh workflow run sync-main-to-canary.yaml,将 main 同步回 canary,保持两个分支的代码一致。
这一连串动作印证了 Minor Release 的硬性规则:不要手工改 package.json、不要手工打 tag——CI 会在合并后全自动完成。
六、Hard Rules:Minor Release 专属的硬性红线
minor-release.md 中列出的 Minor 专属规则必须严格执行:
- PR 标题格式是严格的:
🚀 release: v{x.y.z},任何偏差都会落入 patch 检测路径(详见上文 CI 正则); - 禁止手工修改 package.json 版本号——版本提升由 CI 在合并后统一完成;
- 禁止手工创建 tag——CI 负责打标签与发布;
- Highlights 条目数通常为 8–12 条——遵循 release-notes-style.md 的规模启发式判断。
这些红线共同保证了"PR 标题是唯一的事实来源(single source of truth)",杜绝人工操作与 CI 状态之间的不一致。
七、如何撰写 Minor 的 Release Notes(长格式规范)
Minor / Weekly 均使用 release-notes-style.md 定义的 长格式(Long-Form) 结构。它遵循四条定位原则:数据置顶、先叙事再结构、深度但易扫读、贡献者前置。
7.1 编写前必须采集的输入
- 比较区间
<prev_tag>...<current_tag>; - 发布指标(commits、merged PRs、resolved issues、contributors,可选 files 变更量);
- 按领域归类的高影响变更(core loop、platform/gateway、UX、tooling、security、reliability);
- 贡献者列表(含突出的个人贡献);
- 已知风险 / 迁移 / 发布说明(如有)。
若指标无法可靠计算,宁可省略也不要猜测。
7.2 计算输入的硬性规则:一切来自 git,禁止凭空捏造
该文档把"臆造 PR 号、错选 Since v… 基线"列为该 Skill 的头号失败模式,并给出三条铁律:
① 比较基线 = main 上最新 semver tag(命令见本文第三节第 4 步),不要目测 tag 列表。
② PR 号必须来自 commit subject:
git log "$PREV_TAG..origin/release/weekly-{YYYYMMDD}" \
--pretty=format:'%s' --no-merges \
| grep -oE '\(#[0-9]+\)$' \
| sort -u > /tmp/release_prs.txt
正文中出现的每个 (#XXXX) 都必须存在于该文件中,禁止凭记忆推断 PR 号。
③ 指标来自 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 身份需通过 gh pr view "$PR" --json author --jq '.author.login' 解析,不能直接拿 git %an 当 handle 使用。
④ 发布前强制校验:对正文与真实提交区间做差集比对:
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
# 输出必须为空
comm -23 /tmp/body_prs.txt /tmp/release_prs_clean.txt
只要差集非空,说明正文引用了该区间内未合并的 PR,必须停下修正后才能发布。
7.3 长格式的规范结构
Minor 与 Weekly 必须按下述顺序组织(release-notes-style.md),Hotfix 与 DB Migration 则走短格式变体:
# 🚀 LobeHub Release (<YYYYMMDD>)- 元数据行:
Release Date+Since <Previous Version>指标 - 一句引用形式的发布主旨(1–2 行)
## ✨ Highlights(大型发布 8–12 条;Weekly 3–8 条)- 领域分块(可用
###子节):🏗️ Core Agent & Architecture、📱 Platforms / Integrations、🖥️ CLI & User Experience、🔧 Tooling、🔒 Security & Reliability、📚 Documentation(可选) ## 👥 Contributors**Full Changelog**: <prev>...<current>
长短发布之间用 --- 分隔。模板骨架同样保存在 release-notes-style.md,可直接复制使用。
对应的完整示例可见 weekly-release.md,它演示了元数据行、Highlights、领域分块、贡献者与 Full Changelog 的组合写法。
7.4 贡献者排序与团队名单
贡献者渲染为单一扁平列表(不再拆分社区/团队子节),排序规则为:社区贡献者在前、团队成员在后,组内按 PR 数降序;机器人(@lobehubbot、renovate[bot])单独放一行 maintenance 说明。团队名单以 release-notes-style.md 中的 LobeHub team roster 为准;名单之外出现的贡献者默认按社区贡献者处理,并应询问是否将其加入名单。
7.5 写作红线与风格
- 不虚构指标:所有数字必须可溯源;
- 不使用空泛头条:每条 bullet 必须同时包含能力 + 影响;
- 不从内部视角表述:以用户/运维视角行文;
- 安全相关修复必须显式声明;
- 术语全篇一致,不得在不同章节换名;
- 迁移或破坏性变更不得埋没:提升到独立章节或用 callout 强调;
- 加粗仅用于能力名,不用于整句;
- 标题层级不超过三级。
八、Minor 与其他发布形态的分工与互补
理解 Minor Release,还需了解它和相邻发布形态的关系(详见 patch-release-scenarios.md 与 SKILL.md 的触发规则):
| 形态 | 场景 | 关键动作 |
|---|---|---|
| Weekly(周更) | canary → main,聚合一周变更 | release/weekly-{YYYYMMDD} 分支;标题 🚀 release: {YYYYMMDD},无版本号 |
| Bug Hotfix | 从 main 直接出发的紧急修复 | hotfix/* 分支;gitmoji 标题(如 🐛 fix: …);合并即自动 patch +1 |
| New Model Launch | 新模型/供应商支持 | 普通 feat/style PR,标题前缀命中即自动触发 |
| DB Schema Migration | 需独立发布的库表变更 | release/db-migration-* 分支 + cherry-pick;短格式 changelog,强调迁移影响与回滚 |
| Minor(本文) | 特性迭代里程碑 | release/v{x.y.0} 分支;标题精确携带版本号 |
两条关键边界值得注意:其一,Weekly、Minor 从 canary 出分支,而 Hotfix、DB Migration 从 main 出分支;其二,Hotfix 与 DB Migration 使用的是另一套短格式发布说明结构——无 Highlights、无领域分块、无 Contributors 长名单,而是以 Hotfix Scope / What's Fixed / Upgrade / Owner 为主(模板见 hotfix.md 与 db-migration.md)。判断该用哪种结构,可依据规模启发式:Minor/里程碑走长格式(Highlights 8–12 条),Weekly 走精简长格式(4–8 条),Hotfix 与 DB Migration 走短格式。
九、写在最后:从文档到流水线的全局视角
回到 minor-release.md 开篇的那句话——Minor Release 的目的是发布一个新的次版本(如 v2.2.0),大约每 4 周一次,PR 标题携带精确版本号,由 CI 解析标题驱动后续全部动作。这条工作流之所以能在 LobeHub 稳定运转,依赖四层设计互为咬合:
- 人只决策"何时发、发什么版本",其余交给自动化;
- PR 标题是唯一的机器可读事实源,正则解析保证确定性;
- 版本提升、打 tag、发 Release、回灌分支全部由 auto-tag-release.yml 接管,人工介入点被压缩到最少;
- 发布说明的数据全部强制来自 git(tag、commit、PR 号),配合发布前差集校验,从机制上杜绝了"发布笔记与真实变更不一致"这一最常见的工程事故。
当你所在团队需要把"发布"从手工操作升级为流程化、可审计的流水线时,LobeHub 这套以"标题为准、CI 执行、git 数据为证"的 Minor 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