全流程指南:从版本审计到每日自动化)
Turborepo 示例维护Examples Maintenance全流程指南从版本审计到每日自动化【免费下载链接】turboBuild system optimized for JavaScript and TypeScript, written in Rust项目地址: https://gitcode.com/gh_mirrors/tu/turbo在 Turborepo 仓库中examples/目录下的每个示例都是面向用户的模板它们必须始终处于可直接复制、可运行的状态。然而随着 npm 生态每日发布新版本示例中的依赖版本、packageManager锁定、Node 引擎声明、README 命令乃至 Docker 镜像标签都会逐渐过时。本文以仓库中 examples_maintenance.md 这份技能文档为骨架结合apps/factory/下的真实工具实现系统讲解 Turborepo 示例维护的完整工作流版本审计与更新策略、最佳实践迁移、禁止降级策略、release-age 设置约束、锁文件再生、任务验证以及完成契约Completion Contract。读完本文你将掌握一套审计 → 更新 → 迁移 → 验证 → 提 PR的可复用维护流水线。维护工作的范围与边界examples_maintenance.md明确将示例定位为用户面向的模板user-facing templates维护的第一原则是偏好简单、现代、可复制的模式而不是聪明的抽象prefer simple, modern, copyable patterns over clever abstractions。这一原则直接决定了后续所有策略的取舍方向。维护工作有三条关键边界单示例约束自动化调度与操作者运行operator runs只维护由select_daily_example选出的唯一一个示例运行期间不得检查或修改其他示例。从源码看这一约束被写死进工具层select_daily_example.ts 专门选择今天用于自动维护的单个 Turborepo 示例write_examples_file.ts 中若处于自动维护模式任何写入路径若不以examples/${automatedExample}/开头会直接抛出Automated maintenance can only write examples/${automatedExample}/.错误。保留包管理器意图除非用户明确要求不得把 npm、pnpm、Yarn 或 Berry 示例互转。锁文件再生的前提是使用示例声明的包管理器见下文。最小化变更除非最新版本迁移要求更广泛的代码、配置或工具链变更否则保持改动最小。值得强调的是文档要求维护者不得为了逃避迁移而添加兼容性垫片compatibility shims而应通过真正的迁移、包替换或配置变更让最新版本干净地工作。这意味着维护是升级 修复而不是升级 打补丁掩盖。版本更新审计每一个可能过期的版本化值审计清单不局限于依赖版本审计的范围远超dependencies字段。文档给出的完整清单是类别具体取值依赖声明dependencies、devDependencies、peerDependencies、optionalDependencies包管理器packageManager字段如pnpm9.x、yarn1.xNode 引擎engines.node工具链镜像Docker 镜像标签CI 动作GitHub Action 版本文档README 中的命令与版本引用这一清单与 audit_example_versions.ts 的实现完全对应该工具遍历示例下所有package.json对四个依赖字段逐一检查 npmdist-tags.latest检查packageManager锁定值Yarn 1.x 查yarn包、Yarn 2 查yarnpkg/cli、pnpm/npm 直接查对应包名并对照 Node 官方发布元数据给出最新的 active LTS 版本。工具还会跳过workspace:、file:、link:、portal:前缀以及*这类本地/通配版本因为这些不应被改写为注册表版本。解析真实来源并精确锁定npm 包与 JavaScript 包管理器从 npm registry 元数据https://registry.npmjs.org/name的dist-tags.latest解析Node.js从 Node 发布元数据https://nodejs.org/dist/index.json解析最新 active LTS非 JavaScript 工具链从对应 registry 或 release API 解析。两条硬性规则直接依赖、包管理器与版本化工具链值一律更新为 registry/release 元数据中的精确最新稳定版绝不写入字面量latest标签也不引入^或~这类宽松范围。例如示例会把next: 14.2.5更新为next: 15.1.0精确 pin而不是next: ^15.1.0。主要版本升级是预期行为升级到新大版本后修复由此产生的破坏而不是为了验证容易而降级到上一个 major。最佳实践迁移升级是迁移而非机械版本号替换每次 major 升级后维护者应阅读相关发布说明release notes、迁移指南或当前文档把示例更新为生态推荐的新形态。文档点名的惯用当前默认值包括现代 ESLint 的flat configeslint.config.js/mjs替代历史.eslintrc模式当前 TypeScript 模块设置如moduleResolution: bundler当前框架配置文件名称与选项如 Next.js 的next.config.ts当前包管理器锁文件/安装实践现代测试与构建配置惯例。关键要求是迁移后的配置必须被脚本真正使用——配置通过验证但配置是死的dead config不算通过。例如某任务脚本并未调用lint配置则迁移该配置无意义。同时若旧依赖只服务于旧模式应删除或替换为当前推荐包或框架内建能力README 与命令文档也必须与迁移后的行为同步更新而不只是更新安装版本。禁止降级策略No-Downgrade Policy这是维护策略中最强硬的一条永远不因为另一个包暂不兼容就把直接依赖 pin 在 registrylatest之下。文档特别列出 ESLint、TypeScript、React、Angular、Vite、Storybook、Express、Prisma、TypeORM、Nuxt、Vue、Expo、React Native 等禁止以最新兼容版为名义保留旧 major。当最新包因其他包而损坏时解决路径是迁移掉不兼容的包、删除或替换损坏的插件/配置、更新代码到新 API、或重构示例。以 ESLint 为例若eslint-plugin-react或旧式.eslintrc配置阻塞了最新 ESLint应迁移到 flat config并替换不兼容的插件用法、删除非必要的 React lint 规则或采用能与最新 ESLint 协作的框架/原生 lint 覆盖——禁止仅仅因为某个插件在 ESLint 10 上损坏就 pin ESLint 9。文档允许两个例外边界外部包打补丁patching是最后手段当没有可行的迁移或替换、且必须保持最新直接依赖工作时才允许补丁必须保持小而精、记录在包管理器原生补丁元数据中如 pnpm 的pnpm.onlyBuiltDependencies/ patches 机制、并在包管理器支持时以编程方式生成。唯一可接受的阻塞项是未发布的包/版本、不可用的 registry/服务、缺失的凭据。兼容性失败不是阻塞项而是迁移工作。Release-Age 设置精确锁定与发布新鲜度门控minimumReleaseAge是 pnpm、Bun、npm 等包管理器用来门控刚发布版本安装的机制——新发布的包在指定时间窗口内不允许安装。配套的排除清单escape hatch可以让特定包跳过该门控包管理器排除清单配置pnpmminimumReleaseAgeExcludeBunminimumReleaseAgeExcludesnpmminimum-release-age-exclude由于示例维护采用精确锁定最新发布版本策略文档禁止维护者新增或扩展任何排除清单minimumReleaseAgeExclude/minimumReleaseAgeExcludes/minimum-release-age-exclude添加、调高、调低或移除minimumReleaseAge本身——每个示例现有的 release-age 配置保持原样。这些设置只控制发布版本可以有多新鲜不是兼容性、安全或验证工具。仓库源码将这条规则落实为写入时的强制检查release-age.ts 定义了isReleaseAgeConfigFile覆盖.npmrc、.yarnrc.yaml、.yarnrc.yml、bunfig.toml、package.json、pnpm-workspace.yaml、pnpm-workspace.yml与findReleaseAgeExclusion用正则/minimum[-_]?release[-_]?age[-_]?excludes?/i逐行扫描而write_examples_file与create_pull_request在写入/提 PR 前调用assertNoReleaseAgeExclusion一旦发现排除清单即抛错Remove the setting instead of excluding packages from it移除设置而不是把包排除在门控之外。若安装被示例并不拥有的 release-age 门控阻塞例如示例之外的配置正确做法是把失败的安装命令作为阻塞项上报而不是给包加排除。锁文件从不手写总是用声明的包管理器再生规则非常直白绝不手动编写锁文件。更改依赖或packageManager后必须通过update_example_lockfile运行示例声明的包管理器安装命令来更新锁文件。查看 update_example_lockfile.ts 的实现它读取示例package.json的packageManager字段解析出管理器默认回退 pnpm然后在示例目录下执行manager install——例如pnpm install、npm install、yarn install或 Berry 对应的yarn install。若安装失败必须先修复清单或兼容性问题再进入任务验证阶段不得用跳过安装或伪造锁文件的方式绕过去。任务验证持久任务与非持久任务的分野用 audit_example_tasks 区分两类任务验证前的第一步是调用audit_example_tasks识别持久任务与非持久任务。该工具读取示例的turbo.json与根package.json的 scripts其分类逻辑见 example-tasks.ts持久任务turbo.json中persistent: true的任务以及名字命中内置集合{dev, start, serve, preview}的长驻任务。它们不会自行终止不属于通过/失败型验证任务。非持久任务如build、lint、test、check-types及框架特有的编译检查存在时必须通过。cache: false的任务不参与门控从源码注释可见cache: false的任务被判定为非确定性或有副作用——数据库迁移/种子db:migrate:deploy、db:push、db:seed、破坏性任务clean、storybook/preview 服务器preview-storybook、代码修复器//#fix。这些任务在临时沙箱中永远无法成功不能阻塞自动化 PR 的创建。以 examples/basic/turbo.json 为例build、lint、check-types是需验证的非持久任务而dev标记了cache: false, persistent: true属持久任务被排除。单次调用跑完全部任务所有相关的非持久任务必须一次性传入一次run_example_turbo_tasks调用。该工具的实现run_example_turbo_tasks.ts会通过buildTurboRunCommand构造单条命令含--continuealways让每个失败都浮出水面并且会校验传入的任务集合必须与audit_example_tasks给出的recommendedTurboTasksToRun完全一致否则抛错Validate every audited non-persistent Turbo task in one call.。这从机制上杜绝了挑肥拣瘦、只跑容易通过的任务。验证结果会写入验证状态pending/success/failed并附带示例变更指纹exampleChangeFingerprint。验证工具调用失败 示例失败必须修复失败并重跑完整任务集绝不允许把非零退出码的命令上报为验证通过若版本升级破坏了示例必须在同一次处理中修复而不是留下半更新的示例。完整工具流与完成契约推荐的九步工具流文档给出的推荐流程如下自动运行先调select_daily_example仅对返回的示例调用inspect_example交互式运行则用list_examples或inspect_example理解请求目标用audit_example_versions找出过期的package.json、packageManager与 Node 引擎值用find_versioned_references查找清单之外的版本化引用如 Docker 标签、README 命令、CI 版本用audit_example_tasks识别验证脚本与持久任务修改现有文件前先用read_examples_file读取非锁文件变更用write_examples_file依赖或包管理器变更后用update_example_lockfile把recommendedTurboTasksToRun中的每个任务一次性传给run_example_turbo_tasks自动维护且沙箱含变更时用create_pull_request提 PR——它会拒绝选中示例之外的变更并在无变更时不创建 PR 直接返回。完成契约Completion Contract对于更新我们的示例这类宽泛请求完成的定义是所有示例都处理完毕、所有直接版本 pin 都移动到精确的最新稳定值、锁文件已用声明的包管理器重新生成、最佳实践迁移已应用、所有相关非持久验证任务都已尝试。文档对此有明确的行为约束不得以还有剩余示例、稍后继续结束回合必须在同一次运行中继续不得把检查点、进度报告、阻塞分析或计划当作最终答案除非每个剩余项都被真正的外部阻塞卡住真正的外部阻塞仅限于不可用的 registry/服务、缺失凭据、未发布的包/版本。构建、lint、类型、测试、peer-dependency、框架、插件、迁移失败统统不是阻塞项而是需要修复的工作。这条契约与 daily-example-maintenance.ts 中的自动维护提示词一致Fix validation failures rather than stopping at an audit report修复验证失败而不是停在审计报告。报告规范最终报告应总结变更的示例、选定的精确版本、执行的锁文件更新命令、验证结果。若某检查因依赖或外部服务不可用而无法运行需明确说明并附上失败的命令不得把latest-compatible回退上报为完成——完成要么是精确的最新直接 pin要么是真实的外部可用性阻塞。自动运行场景下分支与标题由create_pull_request按示例自动生成PR 正文聚焦变更本身省略 CI 会覆盖的常规验证仅在更新需要超出测试套件的非常规手工测试时才提及验证。自动化落地每日调度的真实形态这套工作流并非纸上谈兵——仓库将其固化为每日定时任务daily_example_maintenance.ts 用 cron 表达式0 14 * * *每天 14:00 UTC触发DAILY_EXAMPLE_MAINTENANCE_PROMPT。该提示词严格对应本文梳理的完整流程先调select_daily_example、只维护返回的单个示例、审计并更新过期依赖/包管理器 pin/Node 引擎/README 指令/版本化引用/turbo.json任务、使用精确最新稳定版本、应用最佳实践迁移、用声明包管理器再生锁文件、把每个相关非持久验证任务传给一次run_example_turbo_tasks调用、修复验证失败而非停留在审计报告、不引入minimumReleaseAgeExclude或其他 release-age 排除清单、有变更时通过create_pull_request向仓库开 draft PR。交互式维护场景则通过factory-create-pr --branch agents/examples-example-fx-sessionId --title chore: Update example example走 Eve 的 GitHub 凭据完成提交、分支与 draft PR且明确禁止维护者手动执行git commit、git push、gh auth setup-git或gh pr create。小结Turborepo 示例维护的本质是一套把示例永远保持最新、可复制、可运行这一目标拆解为可执行规则与工具约束的系统精确版本审计替代机械 bump最佳实践迁移替代补丁堆叠禁止降级策略把兼容性问题转化为迁移工作release-age 排除清单被写入工具层的强制校验任务验证以单次--continuealways调用保证全量失败可见完成契约则确保自动化运行不会以进度报告敷衍收场。无论是手动维护单个示例还是理解每日自动维护流水线这套工作流都提供了清晰的决策边界与可验证的完成标准。【免费下载链接】turboBuild system optimized for JavaScript and TypeScript, written in Rust项目地址: https://gitcode.com/gh_mirrors/tu/turbo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考