What's new in vNEXT_VERSION
【免费下载链接】follow🧡 Folo is the AI RSS Reader项目地址: https://gitcode.com/GitHub_Trending/fol/follow
Shiny new things
Improvements
No longer broken
Thanks
Special thanks to volunteer contributors @ for their valuable contributions
之所以要求保留占位符,是因为 `apply-changelog.ts` 的替换逻辑基于它运行: ```ts const new_version = process.argv[2] const majorMinorPatch = new_version.split("-")[0] // 剥离预发布后缀,仅取 x.y.z const nextContent = readFileSync(nextFile, "utf-8") writeFileSync(nextFile, nextContent.replaceAll("NEXT_VERSION", majorMinorPatch)) // 把 next.md 改名为 {版本号}.md,归档本次 changelog renameSync(nextFile, join(changelogDir, `${majorMinorPatch}.md`)) // 用模板重建一份全新的 next.md,供下一次发布使用 copyFileSync(join(changelogDir, "next.template.md"), join(changelogDir, "next.md"))也就是说,一次 bump 会让apps/desktop/changelog/目录发生三件事:占位符替换、草稿归档为历史 changelog、模板重建新草稿。仓库中apps/desktop/changelog/下大量以x.y.z.md命名的文件(如1.12.0.md、0.2.0.md)正是该机制逐版本沉淀的产物。
6. 第三步:选择发布模式(核心决策)
这是整个发布流程中唯一需要人为判断的环节,它取代了旧版的mainHash决策机制。
6.1 检查运行时影响面
用以下命令查看自上个桌面标签以来,会影响桌面运行时(而非纯渲染层)的改动范围:
git diff <last-tag>..HEAD --name-only -- \ apps/desktop/layer/main/ \ apps/desktop/layer/preload/ \ apps/desktop/forge.config.cts \ apps/desktop/resources/ \ apps/desktop/scripts/ \ apps/desktop/package.json如果改动命中了上述路径中的任意一个,说明新版本大概率需要一个新的桌面二进制。
6.2 决策表
| 模式 | 何时使用 | 典型触发场景 |
|---|---|---|
build | 发布需要新的二进制 | main 进程改动、preload/IPC 改动、updater 流程改动、Electron / Forge / 打包 / 签名改动、native 资源改动、影响运行时行为的依赖或包改动 |
ota | 渲染层更新与已安装二进制兼容 | 渲染层 UI 改动、Web 行为改动、不需要新桌面二进制的共享前端逻辑改动 |
ota模式还需要额外确认两个字段:
runtimeVersion:此渲染层更新所兼容的最新已安装桌面二进制版本。例如渲染层 UI 基于 1.12.0 二进制开发完成,就填1.12.0。channel:通常为stable(源码层校验允许stable/beta/alpha,见下)。
判断原则:如果不确定改动是否与现有二进制二进制级兼容,倾向选择
build。
决策分析必须呈报给用户并包含:改动的运行时影响文件、改动摘要、推荐模式(build或ota)、推荐的release-plan.json内容、以及明确的确认请求。
6.3 底层校验:release-plan 是硬约束而非建议
apps/desktop/scripts/apply-release-config.impl.ts用一组不可逾越的规则校验 release-plan,任何违背都会让 bump 直接失败:
const validModes = new Set(["build", "ota"]) const validChannels = new Set(["stable", "beta", "alpha"]) function validateReleasePlan(plan: DesktopReleasePlan) { if (!validModes.has(plan.mode)) throw new Error("release-plan.json mode must be build or ota") if (plan.channel !== null && !validChannels.has(plan.channel)) throw new Error("release-plan.json channel must be stable, beta, alpha, or null") if (plan.mode === "build") { // build 模式:runtimeVersion 与 channel 必须保持 null if (plan.runtimeVersion !== null || plan.channel !== null) throw new Error("desktop build mode must not set runtimeVersion or channel") return } if (plan.mode === "ota") { // ota 模式:runtimeVersion 必须为纯 x.y.z 且 channel 必填 if (!plan.runtimeVersion || !semverPattern.test(plan.runtimeVersion)) throw new Error("desktop ota mode requires a plain x.y.z runtimeVersion") if (!plan.channel) throw new Error("desktop ota mode requires a channel") } }由此可以总结出两种模式的合法 release-plan 形态:
// build 模式(也是 apply-release-config 重置后的默认模板) { "mode": "build", "runtimeVersion": null, "channel": null } // ota 模式示例 { "mode": "ota", "runtimeVersion": "1.12.0", "channel": "stable" }技能文档明确强调:当前实现只支持
build和ota两种模式,不要推荐或书写其他模式。
7. 深入原理:runtimeVersion 如何取代 mainHash 成为 OTA 兼容键
理解这一步决策为何关键,需要回到桌面热更新的运行时逻辑apps/desktop/layer/main/src/updater/hot-updater.ts。
旧机制中的mainHash由apps/desktop/plugins/vite/generate-main-hash.ts生成:它对layer/main目录下全部ts/tsx文件与package.json内容做 SHA-256 摘要后写回package.json.mainHash。它只反映main 进程源码的变化,无法表达「渲染层与已安装二进制」之间的兼容关系,因此不再是 OTA 决策点。
新机制中,apps/desktop/package.json的runtimeVersion字段成为桌面 OTA 兼容键。热更新器在判断远端渲染层 manifest 是否可应用时,第一道门槛就是runtimeVersion 必须严格相等:
export const isRendererManifestUsable = ( manifest: null | Partial<Pick<RendererManifest, "runtimeVersion" | "version">>, input: { appVersion: string; runtimeVersion: string }, ) => { // 远端 manifest 的 runtimeVersion 必须等于本机二进制声明的 runtimeVersion if (!manifest?.runtimeVersion || manifest.runtimeVersion !== input.runtimeVersion) { return false } // ... 再通过 semver 比较版本、判断是否为 full app update }而 bump 阶段对runtimeVersion的写入规则在apply-release-config.impl.ts中非常明确:
packageJson.runtimeVersion = plan.mode === "ota" ? plan.runtimeVersion! : input.version- build 模式:新二进制自洽升级,
runtimeVersion直接写成新版本号本身; - ota 模式:二进制不变,
runtimeVersion写入 plan 中指定的、该渲染层所兼容的最新已安装二进制版本。
这一差异解释了 SKILL 中反复强调的决策原则:只有渲染层改动(纯 UI/Web/共享前端逻辑)才可能走ota;任何触碰 main/preload/IPC/updater/打包依赖的改动都必须走build,否则会破坏渲染层与既有二进制的兼容契约。
8. 第四步:更新发布输入并提交
在 bump 前需要落地两个人工输入,并遵守一个重要前提:
- 编辑
apps/desktop/changelog/next.md(第二步已确认的内容)。 - 编辑
apps/desktop/release-plan.json(第三步确认的模式与参数)。 - 不要直接编辑
apps/desktop/release.json——它由 bump 生成,人工修改会被覆盖。 nbump要求干净的 working tree,因此必须先提交这两个发布输入再执行 bump。
提交命令:
git add apps/desktop/changelog/next.md apps/desktop/release-plan.json git commit -m "docs(desktop): prepare release inputs"如果这两个文件相对当前分支没有变更(例如已提交过),则可以跳过继续。
9. 第五步:运行 bump(含用户批准前置条件)
此步骤不得在用户明确批准“可以推送代码”之前执行——因为 bump 会 push 分支并打开 PR。
pnpm --dir apps/desktop bump【免费下载链接】follow🧡 Folo is the AI RSS Reader项目地址: https://gitcode.com/GitHub_Trending/fol/follow
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考