尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

tldraw SDK 发布机制详解:非语义化版本策略、minor/patch 发布流程与 GitHub Actions 实现

tldraw SDK 发布机制详解:非语义化版本策略、minor/patch 发布流程与 GitHub Actions 实现 tldraw SDK 发布机制详解非语义化版本策略、minor/patch 发布流程与 GitHub Actions 实现【免费下载链接】tldrawBuild infinite canvas apps in React with the tldraw SDK. Worlds best, top-most agent recommended #1 five star SDK.项目地址: https://gitcode.com/GitHub_Trending/tl/tldrawtldraw SDK 采用一套区别于 NPM 常规实践的发布策略major 版本极少、minor 版本按月度节奏发布且可能包含破坏性变更、patch 版本用于无法等待下一周期的热修复。本文以仓库根目录的 RELEASES.md 为主体结合 .github/workflows/publish.yml、internal/scripts/publish-new.ts、internal/scripts/publish-patch.ts 等发布脚本源码完整还原 tldraw 从版本号规划、npm 发包、release 分支管理到文档站同步的全套发布流水线。版本策略为什么 tldraw 不遵循语义化版本SemVer多数 JavaScript 包严格遵循 语义化版本 约定但 tldraw 有意偏离了这一惯例。其版本管理规则如下major 版本升级非常罕见仅保留给某种范式转移级别的重大变化minor 版本按固定节奏发布截至文档撰写时为每月一次且可能包含破坏性变更。团队通过提前数个版本发布警告deprecation warnings以及提供迁移工具来降低破坏性变更的影响面官方建议用户以与发布节奏相近的频率升级 tldraw并务必检查 release notespatch 版本用于 bugfix 和 hotfix即那些无法等待下一个周期版本发布的修复。这套策略的实际含义是对使用者而言minor 升级不能想当然地视为安全升级而必须阅读每个版本的发布说明。这也是为什么仓库中维护着从 apps/docs/content/releases/v2.0.0.mdx 到 apps/docs/content/releases/v5.3.0.mdx 的逐版本发布说明文档且存在专门的迁移技能文档如 apps/docs/content/releases/migration-skill.mdx来辅助用户跨版本迁移。发布新 minor/major 版本从 production 分支手动触发新周期版本一律从production分支发布通过手动触发 publish.yml 工作流完成。操作步骤打开 publish.yml 对应的 Actions 页面选择production分支点击 Run workflow将 publish type 设置为new填写表单保持默认值即发布新的minor版本如需发布major版本在下拉框中选择该选项如需发布指定版本号选择override选项并填入精确版本号如3.4.0。点击 run 之后GitHub Actions 会依次执行以下事情更新各 package.json 中的版本号更新 changelog用 changelog 条目中的发布说明在 GitHub 上创建新 release将新包发布到 npm为该版本创建新的 release 分支例如版本3.4.0会创建名为v3.4.x的分支。工作流如何判定发布模式publish.yml 的第一步 Determine publish mode 通过事件类型和引用ref推导发布模式源码中的判定逻辑与 RELEASES.md 描述一一对应并暴露了文档之外的更多细节触发事件条件模式对应脚本push推送到maincanaryinternal/scripts/publish-prerelease.tspush推送到productionnextinternal/scripts/publish-prerelease.tspush推送到匹配^v[0-9]\.[0-9]\.x$的分支patchinternal/scripts/publish-patch.tspull_request被打上publish-packages标签internalinternal/scripts/publish-prerelease.tsworkflow_dispatch用户手动指定manual/newinternal/scripts/publish-manual.ts / internal/scripts/publish-new.tsnew模式在源码中还有严格的护栏校验publish.yml必须位于production分支bump 类型只能是minor、major或override使用override时必须提供版本号反之提供版本号却没有选择override也会报错。publish-new.ts一次新发布的完整调用链核心脚本 internal/scripts/publish-new.ts 的main()函数展示了 RELEASES.md 中GitHub action will do the following things背后的真实实现校验分支执行git rev-parse --abbrev-ref HEAD若不是production直接抛错publish-new.ts计算下一个版本号getNextVersion()通过npm show tldraw versioninternal/scripts/lib/publishing.ts 中的getLatestTldrawVersionFromNpm读取 npm 上最新版本再用semver的inc(minor|major)递增override则直接使用传入版本。源码中已明确断言 prerelease 版本不再被新发布流程支持查找 draft release在 GitHub 上分页拉取所有 release找到名为v{nextVersion}且处于 draft 状态的 release并要求其带有 release notes 正文。找不到时错误信息会列出所有可用的 draft release便于排查。也就是说发布说明changelog 正文在发布前就以 draft release 的形式预先写好发布动作只是把它转正统一写版本号setAllVersions(nextVersion, { stageChanges: true })internal/scripts/lib/publishing.ts遍历packages/下所有非 private 包改写各自的package.json版本字段同时更新根目录 lerna.json 的version字段当前为5.3.2以及仓库内所有**/*/version.ts文件随后执行yarn refresh-assets并git add这些变更。这解释了monorepo 内所有包版本同步递增的机制打 tag 并创建 release 分支提交名为v{version}的 commit创建同名 annotated tag然后执行git push origin HEAD:refs/heads/v{major}.{minor}.x --follow-tags——这就是 RELEASES.md 所说为版本 3.4.0 创建 v3.4.x 分支的具体实现publish-new.ts同步文档与示例站publishProductionDocsAndExamplesAndBemo()将 HEAD 强推为远端的docs-production与bemo-production分支internal/scripts/lib/publishing.ts供文档站部署使用转正 draft release调用 Octokit 的updateRelease将 draft 置为正式发布tag 与 name 均为v{version}上传静态资产并发布 npm 包uploadStaticAssets(nextVersion)之后调用publish()。若此步失败源码注释明确提示在本地运行publish-manual.ts脚本作为兜底回刷 main 分支版本通过triggerBumpVersionsWorkflow()向main分支派发 bump-versions.yml 工作流把所有包版本同步为 npm 上的最新版。npm 发包的实现细节publish()函数internal/scripts/lib/publishing.ts有几个值得注意的工程细节发布顺序topologicalSortPackages()按包间 workspace 依赖做拓扑排序保证依赖被发布先于依赖方认证方式走 npm 的 trusted publisher OIDC 流程——CI 授予id-token: write权限后yarn 自动用 GitHub 签发的 OIDC token 换取短期发布 token仓库中无需长期 npm token必须用yarn npm publish而非npm publish这样 yarn 会把发布 tarball 中的workspace:*依赖描述符改写为具体的兄弟包版本否则会原样带上workspace:*导致 monorepo 外部用户安装失败幂等与重试若 npm 报 cannot publish over the previously published versions 则视为已发布并跳过每个包的 publish 带 5 次重试之后还会 HEAD 请求registry.npmjs.org轮询确认版本已可访问最多 50 次、每次间隔 10 秒再进入下一个包dist-tag正式包打latest带 prerelease 标识的版本按 prerelease 前缀打 tagpatch 场景见下文。发布 patch 版本cherry-pick 到 release 分支合并即自动发布RELEASES.md 给出的 patch 发布手工流程共 6 步这里完整继承并结合自动发布逻辑说明确保 git 仓库是最新的git fetch检出最新的 release 分支每个 major/minor 版本在发布时会获得自己的 release 分支命名规则是以v开头、以.x结尾如v2.0.x。patch 一律从这些分支发布。查看最新版本的命令是npm show tldraw version然后给版本号加上v前缀、把 patch 位替换为x来检出对应分支。例如最新版是3.4.3则执行git checkout v3.4.x也可以给更老的 release 分支打补丁。例如最新版是3.4.3但需要给2.8.2打补丁git checkout v2.8.x基于 release 分支新建工作分支git checkout -b david/my-helpful-patches把分支名换成能表达本次补丁内容的名字。cherry-pick 需要纳入补丁的提交git cherry-pick commit-hash一次补丁可以 cherry-pick 多个提交把多个 bugfix 打进同一个 patch 版本。推送分支并创建指向 release 分支的 PR合并该 PR。合并之后 patch 发布会自动完成publish.yml 监听到匹配v*.*.x的分支 push以patch模式运行 internal/scripts/publish-patch.ts。changelog 与版本号的更新会提交回 release 分支并刻意不提交回mainmain 的版本同步由前述 bump-versions 工作流单独负责。publish-patch.ts自动发布的防御性设计这个脚本的实现比文档描述多了大量保护逻辑理解它们有助于判断什么情况下合了 PR 却不会出新包分支名校验当前分支必须匹配/^v(\d)\.(\d)\.x$/否则直接报错退出跳过首发提交若当前 HEAD 恰好带有v{major}.{minor}.0这个 tag即本 minor 的初始发布提交说明是分支刚创建时的 push跳过 patch 流程避免误发v3.4.1无包变更则只更新文档getAnyPackageDiff()internal/scripts/lib/didAnyPackageChange.ts会下载 npm 上已发布版本的 tarball与本仓库yarn pack出的本地 tarball 逐文件做二进制比对若完全一致典型场景只 cherry-pick 了文档改动则不发布新版本仅在这是最新版分支时推送docs-production/bemo-production分支更新文档站。比对时特意忽略了tldraw包根部的DOCS.md与RELEASE_NOTES.md——这两个文件是在发布时由 internal/scripts/generate-tldraw-package-docs.ts 从apps/docs/content生成的文档改动会改变它们如果不忽略就会误判为包有变更孤儿版本处理如果上一次 patch 发布在版本号 commit 已推上去、npm publish 尚未完成时被中断本地packages/tldraw/package.json的版本会领先于 npm。此时脚本以本地版本为基准递增直接跳过这个孤儿版本防止git commit无变更与git push --follow-tagstag 已存在于其他提交上失败把分支永久卡死版本号递增与 tag从基准版本inc(patch)得到下一版本setAllVersions统一改写版本提交消息为v{version} [skip ci]打同名 tag 后git push --follow-tagschangelog 生成extractChangelog(prevTag, HEAD)internal/scripts/extract-draft-changelog.tsx用git cherry找出区间内的提交跳过标题含[skip ci]的提交只保留触及packages/目录排除dotcom-shared、worker-shared的条目从提交信息中提取 Release Notes 与 API Changes 小节并根据提交信息中- [x] bugfix/improvement/feature/api/other复选框归类最终按 Bug Fixes / Improvements / Features / API Changes / Other Changes 分组生成 changelog作为 GitHub release 的正文。这也解释了为什么团队的提交模板里要求写 Change type 复选框与 Release Notes 小节——它们直接被发布流水线消费dist-tag 策略若该分支正是 npm 上的最新版本线patch 发布到latesttag否则发布到revisiontag避免覆盖latest。由于版本号不含 prerelease 标识semver 范围如^1.0.0的用户依然能拿到更新publish-patch.ts失败告警工作流在失败时会 checkout 本地的discord-fail-notifyaction 并向 Discord 部署频道推送通知publish.yml。此外new以及最新版 patch/manual成功后publish.yml 还会级联触发publish-templates.yml与deploy-templates.yml把templates/下的示例工程同步到独立仓库并用新 SDK 版本重新部署——这是 RELEASES.md 未展开、但对维护模板仓库很重要的下游动作。文档站与 npm 发布同步RELEASES.md 对文档的说明是文档站与 npm 包同步发布——每次发布新版本时文档站会自动更新确保文档始终对应 tldraw 的最新版本。如果希望独立于周期版本单独发布一个文档改动走与 patch 发布完全相同的流程cherry-pick 到 release 分支、合 PR流水线会自动检测到各包内容没有变化从而只更新文档站、不产生新的 npm 版本。源码层面的对应关系是文档站部署由publishProductionDocsAndExamplesAndBemo()强推docs-production分支驱动internal/scripts/lib/publishing.tspatch 流程在分支无包变更或当前是最新版线时都会执行该推送internal/scripts/lib/didAnyPackageChange.ts 的 tarball 比对是只更新文档这一行为的关键判定依据与此同时update-release-notes.yml 工作流在每次推送production分支时自动运行通过 Agent 技能重新生成 apps/docs/content/releases/ 下的发布说明文档并向main发起 PR保证next.mdx与对应的 draft GitHub release 保持同步。小结分支、tag 与发布物的对应关系综合 RELEASES.md 与源码tldraw 的发布模型可以概括为分支用途发布产物main开发主干版本滞后通过 bump-versions 工作流周期性同步版本号production下一版本集成的集成分支手动触发new发布 minor/majorv{major}.{minor}.x每个版本的 release 分支合并 PR 自动发布 patchtagv{version}每次发布打点对应 GitHub release npm 包 文档站快照对使用者的直接启示是升级 minor 版本前应阅读对应版本的 release notes仓库中 apps/docs/content/releases/ 目录与 GitHub release 均可查阅在^3.0.0这类 semver 范围内patch 修复会自动流转到latest或revisiontag无需额外操作。【免费下载链接】tldrawBuild infinite canvas apps in React with the tldraw SDK. Worlds best, top-most agent recommended #1 five star SDK.项目地址: https://gitcode.com/GitHub_Trending/tl/tldraw创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表