Cypress Monorepo 工程手册:AGENTS.md 中的工作区划分、命令矩阵、代码规范与 CI/CD 门禁全解
本文以 Cypress 仓库根目录的 AGENTS.md 为骨架,完整拆解这座 monorepo 的工作区结构、开发命令体系、架构分层与代码规范,并逐条对照根目录 package.json、共享 ESLint 配置 packages/eslint-config/src/baseConfig.ts、postinstall 脚本 scripts/run-postInstall.js 等真实源码,说明文档中每条约定背后的实现依据。读完本文,你可以独立配置出与贡献者完全一致的开发环境、按仓库规范运行测试与构建,并理解每条 lint 规则、运行时 API 下限和 CI 门禁的具体含义。
一、AGENTS.md 在仓库中的定位
AGENTS.md 是 Cypress monorepo 的“协作总纲”。Cypress 是面向现代 Web 的开源端到端与组件测试框架,这座 monorepo 同时承载:桌面版与 CLI 主包(cypress)、在浏览器内执行测试的 JavaScript driver、基于 Electron 的测试运行器、一批对外发布的 npm 包(组件测试适配器、webpack/Vite 集成、插件),以及用于构建和发布全部产物的内部工具链。
AGENTS.md 的价值在于:它把“如何装环境、如何跑测试、各包是什么、代码风格怎么约束、PR 和 CI 有什么门禁”压缩到单文件,并且每一条都能在仓库中找到可验证的出处。下文按文档原始脉络逐节展开,并补充源码级证据。
二、工作区划分:六大目录与 workspace 配置
文档将仓库划分为六个工作区。这一划分与根 package.json 中 workspaces.packages 的声明完全一致(cli、packages/*、npm/*、tooling/*、system-tests、scripts),因此所有目录都共享同一棵 node_modules 依赖树:
cli/— 用户实际安装的cypressnpm 主包(CLI 入口),并共置组件测试框架适配器(@cypress/react、@cypress/vue、@cypress/angular、@cypress/svelte、@cypress/mount-utils)。packages/— 32 个核心内部包:测试 driver、Electron 应用、HTTP server、proxy、launcher、Vue 前端应用、launchpad、reporter、config、data-context、telemetry、types、errors 等。npm/— 15 个对外发布的 npm 包:bundler 集成、组件测试适配器、插件与开发工具。tooling/— 3 个内部构建工具:V8 snapshot 创建、packherd依赖打包器、electron-mksnapshot。system-tests/— 针对已构建好的 Cypress 二进制运行的完整端到端系统测试套件。scripts/— 内部构建、发布与 CI 自动化脚本。
三、环境准备:Node、Yarn 与 postinstall 链条
前置条件
文档明确要求:
- Node:使用 .node-version 指定的版本——当前该文件内容为
24.15.0。可用node -v核对,用nvm use切换。 - 包管理器:Yarn 1(
yarn@1.22.22),不要使用 npm 或 pnpm。根 package.json 中packageManager字段锁定了yarn@1.22.22+sha512...,且engines要求node >=24.15.0、yarn >=1.22.22,与.node-version互相印证。 - Lerna:作为 devDependency 安装(当前锁定为
lerna 8.1.9),由根package.json脚本统一编排。 - Electron:构建二进制时由
@packages/electron自动处理;根 package.json 中 devDependencies 将electron固定为41.7.0——这也是文档“运行时目标”一节中“捆绑应用所用 Node/V8 下限”的出处。
yarn 安装时到底发生了什么
本地执行 yarn 会自动触发 postinstall。scripts/run-postInstall.js 按 process.env.CI 区分两条执行链:
- 本地(local):
patch-package && yarn workspace @packages/server sync-cloud-validations && yarn-deduplicate --strategy=highest && lerna run rebuild-better-sqlite3 --scope @packages/server && yarn build && yarn build-v8-snapshot-dev - CI:相同的前四步但不执行
yarn build与 V8 snapshot 构建。
这解释了文档中的两条关键提醒:postinstall 全程约需 4–5 分钟(含构建与 V8 snapshot 生成),若 yarn 被中断必须重跑;以及优先使用 yarn --frozen-lockfile(lockfile 未变化时跳过部分流程,失败才回退到完整 yarn)。另外,仓库通过 patches/ 目录与 patch-package 维护十余个第三方依赖补丁(如 node-fetch+2.7.0.patch、bytenode+1.3.7.dev.patch),这是 patch-package 步骤不可省略的原因。
四、常用命令全览(附脚本实现对照)
以下命令均出自 AGENTS.md,每条都在根 package.json 的 scripts 中找到对应实现。
安装与开发启动
# 安装全部依赖(自动执行 post-install 钩子)
yarn
# 以开发模式启动 Cypress(watch,改动即重建)
yarn dev # 实现为 gulp dev
# 打开开发 + global 模式的 Cypress GUI
yarn start # 实现为 cypress open --dev --global
测试
# 按包 scope 运行测试(优先于裸 yarn test)
yarn test --scope @packages/server
# 指定单个 vitest 规格文件(使用 vitest 的包)
yarn workspace @packages/config test -- <path-to-spec>
# 用 glob 模式指定 vitest 规格
yarn workspace @packages/net-stubbing test -- "<glob-pattern>"
# 指定单个 mocha 规格文件(使用 mocha 的包)
yarn workspace @packages/server test-unit -- <path-to-spec>
# 按名称模式过滤 mocha 测试
yarn workspace @packages/server test-unit -- --grep "<pattern>"
# 运行系统测试(完整二进制级 E2E)
yarn test-system # 实现为 yarn workspace @tooling/system-tests test
# 开发模式下对指定规格 headless 运行 Cypress
yarn cypress:run -- --spec "path/to/spec.cy.ts" # 实现为 cypress run --dev
# 开发模式下对指定规格运行组件测试
yarn cypress:run:ct -- --spec "path/to/spec.cy.ts" # 实现为 cypress run --component --dev
值得注意的实现细节:根 scripts 中 test 的实现是 yarn lerna exec yarn test --scope=cypress --scope=@packages/{...},其中显式排除了 driver 等包(test-unit 则 ignore 了 {driver,root,static,web-config,net-stubbing,network-interception} 等)——不同包使用不同的测试框架与执行方式,这也是文档建议“优先按 scope 运行”的原因。cli/package.json 中 "test-unit": "vitest run" 则印证了 vitest 是 CLI 侧的测试框架。
类型检查
# 全 monorepo TypeScript 类型检查
yarn type-check # 实现为 yarn lerna exec yarn type-check --scope=@tooling/system-tests && node scripts/type_check
# 仅 Lerna 路径的类型检查
yarn check-ts # 实现为 yarn lerna run check-ts
Lint 与格式化
# Lint 所有包(no bail,并发度 2)
yarn lint # 实现为 lerna run lint --no-bail --concurrency 2
# Lint 并自动修复指定 scope
yarn lint:fix # 实现为 lerna run lint ... --scope=@cypress/{grep,mount-utils,schematic,puppeteer,react,vue,svelte} -- --fix
注意:本项目不使用 Prettier,全部格式化由 ESLint 强制。.prettierignore 内容为
**/*,即排除所有文件,与文档声明一致。
构建
# 完整 monorepo 构建
yarn build # lerna-build.js + @packages/electron build-binary + lerna run build-cli
# 构建 V8 snapshot(开发)
yarn build-v8-snapshot-dev
# 构建 V8 snapshot(生产)
yarn build-v8-snapshot-prod
# 清理全部构建产物
yarn clean # lerna run clean --no-bail
# 彻底清理并重装
yarn clean-deps && yarn # clean-deps 会递归删除所有 node_modules
其中 V8 snapshot 脚本的实现是 node --max-old-space-size=8192 tooling/v8-snapshot/scripts/setup-v8-snapshot-in-cypress.js(dev 版本追加 --env=dev),对应 tooling/v8-snapshot/ 目录,服务于 Electron 启动性能优化。
五、架构:子系统与包的职责映射
AGENTS.md 的 Architecture 一节按子系统把 50 余个包归类。结合目录结构逐组说明:
CLI 与分发
cypress(cli/):用户安装的 npm 包,cypress open、cypress run、cypress install等命令的入口,当前 15.x 版本线。其入口逻辑位于 cli/lib/cli.ts 与 cli/lib/cypress.ts,类型声明在 cli/types/。
测试运行器与 Driver
@packages/driver(packages/driver/):在浏览器内执行用户测试代码的 JS driver,实现所有cy.*命令、断言与重试机制。@packages/runner(packages/runner/):webpack 打包的 runner UI,托管被测应用(AUT)iframe 与 driver 通信层。@packages/app(packages/app/):Cypress GUI / Launchpad 的 Vue 3 前端,桌面应用主界面。@packages/launchpad(packages/launchpad/):项目创建、上手引导与测试文件脚手架 UI。@packages/frontend-shared(packages/frontend-shared/):app与launchpad共享的 Vue 组件与设计系统 token。@packages/reporter(packages/reporter/):测试结果报告器 UI(pass/fail 树、日志面板)。
服务器与网络
@packages/server(packages/server/):HTTP server,负责测试文件分发、浏览器启动、socket 通信与测试运行编排,约 248 个源文件是其中体量最大的包。@packages/proxy(packages/proxy/):拦截测试运行期间所有浏览器流量的 HTTP/S 代理。@packages/net-stubbing(packages/net-stubbing/):cy.intercept网络打桩实现——请求匹配与响应篡改。@packages/network/@packages/network-tools/@packages/https-proxy:低层网络协议工具、跨包复用的高层网络辅助、用于 TLS 拦截的 HTTPS 代理实现。
配置与数据
@packages/config(packages/config/):配置类型、默认值、校验与公开的defineConfigAPI。@packages/data-context(packages/data-context/):Cypress 应用集中式 GraphQL 数据访问层(项目、specs、runs、设置),含 packages/data-context/graphql/ 与 packages/data-context/schemas/。@packages/scaffold-config:Launchpad 中框架检测与配置文件生成的脚手架逻辑。
桌面与 Electron
@packages/electron:Electron 运行时封装、二进制构建工具与自动更新集成。@packages/launcher(packages/launcher/):Chrome、Firefox、Edge、WebKit、Electron 的浏览器检测与启动逻辑。@packages/extension:注入浏览器以启用跨域能力与自动化钩子的 WebExtension。
类型、错误与工具
@packages/types:全 monorepo 共享的 TypeScript 类型定义;@packages/errors(packages/errors/):错误定义、错误模板与工具(test 目录含 170 个.ansi快照用于校验错误文案);@packages/socket:driver 与服务端通信的 WebSocket 库(浏览器与 Node 两侧);@packages/telemetry:OpenTelemetry 插桩封装;@packages/icons:图标注册表与 SVG 资产;@packages/stderr-filtering:stderr 输出过滤。
构建与 Snapshot 基础设施
@packages/v8-snapshot-require/@packages/packherd-require:Electron 中 V8 snapshot 的模块加载、以及@tooling/packherd所打包依赖的模块加载器。@packages/web-config/@packages/ts/@packages/eslint-config/@packages/resolve-dist:前端 webpack/PostCSS 配置、共享 tsconfig 与ts-node注册器、共享 ESLint 预设、编译产物路径解析。@tooling/v8-snapshot/@tooling/packherd/@tooling/electron-mksnapshot:V8 snapshot 创建工具、把入口可达的全部依赖打包成单一产物的 bundler、面向目标 Electron 版本的mksnapshot二进制封装。
对外发布的 npm 包(npm/ 目录)
- 组件测试适配器:
@cypress/react、@cypress/vue、@cypress/angular、@cypress/svelte、共享工具@cypress/mount-utils。 - Bundler 集成:
@cypress/webpack-dev-server、@cypress/vite-dev-server、@cypress/webpack-preprocessor、@cypress/webpack-batteries-included-preprocessor、@cypress/vite-plugin-cypress-esm(浏览器测试中可变 ESM 模块的 Vite 插件)。 - 插件与开发工具:
@cypress/grep(按子串/tag 过滤测试运行)、@cypress/puppeteer(用 Puppeteer 增强 Cypress 测试)、@cypress/schematic(Angular CLI 官方 schematic)、@cypress/eslint-plugin-dev(Cypress 开发包共享的 ESLint 规则)。
六、代码规范:每条约定都能在 ESLint 配置中找到出处
文档的 Code Conventions 一节全部由 packages/eslint-config/src/baseConfig.ts 中的规则实现,逐条对照:
| 约定 | ESLint 出处 |
|---|---|
| 不用 Prettier,格式化全由 ESLint 承担 | .prettierignore 排除全部文件;stylistic 插件接管格式 |
| 多行尾逗号 | @stylistic/comma-dangle: ['error', 'always-multiline'](baseConfig.ts#L64) |
禁 console |
no-console: 'error'(baseConfig.ts#L94) |
同步 FS 调用告警(existsSync 除外) |
no-restricted-syntax 用 esquery 选择器匹配 fs.*Sync(baseConfig.ts#L108-L117) |
return 前必须空行 |
padding-line-between-statements(baseConfig.ts#L118-L158) |
测试中禁 .only |
mocha/no-exclusive-tests: 'error'(baseConfig.ts#L189) |
类型导入必须 import type |
@typescript-eslint/consistent-type-imports(baseConfig.ts#L294-L305) |
其余约定:单引号、无分号(semi: 'never')、2 空格缩进、禁 var、模板字符串优先(prefer-template)、对象简写(object-shorthand)、未用变量以 _ 前缀豁免(argsIgnorePattern: '^_')、TypeScript 基础 strict: true 但 noImplicitAny: false。
提交时的第二道防线:根 package.json 的 lint-staged 配置(package.json#L254-L266)对 cli/、packages/、npm/ 等各目录的 JS/TS/Vue 文件自动执行 eslint --fix,配合 husky(prepare: husky install)形成 pre-commit 检查——这正是文档所说“.only 会被 yarn lint 与 pre-commit ESLint 双重捕获”的机制。对于 fixture 或类型样例中确实需要的 .only,用 eslint-disable-next-line mocha/no-exclusive-tests 并附简短注释。.skip 则必须带 NOTE: / TODO: / FIXME: 注释说明原因。
注释风格:解释 why,只描述现状
文档给出的注释准则:代码自解释时优先不写注释;必须写时解释 why 以及代码本身没有直接表达的信息;不在一个文件里重复同一条注释;只描述当前状态,不描述“以前怎样、改了什么”。
反例(文档原文):
// never wipe the entire jar - the old hack called clearCookies() with no filter
// we no longer need to clear the state here, CDP added automatically clearing
// Firefox previously relied on os-level focus, now we use WebDrive BiDi to focus
正例(文档原文):
// Close any extra pages so they don't leak into other tests
// Firefox doesn't support this in native BiDi, so we pull remote.location from current frame
// `cookie`'s serializer rejects an IPv6 literal Domain (e.g. `[::1]`), crashing
// the proxy. Browsers scope cookies for IP hosts to that host anyway, so omit
// Domain and let the cookie default to host-only.
七、运行时目标:不要假设你正在使用的 Node 版本
这是 AGENTS.md 中最容易被忽视、也最影响“能不能用某 API”的一节。monorepo 中的代码运行在多种运行时里,各有各的 JS / 运行时 API 下限,使用现代 Node/DOM API 前必须先确认目标运行时是否支持:
- 开发工具、gulp、构建/开发脚本 — 下限为 .node-version 中的版本(当前
24.15.0)。 - 捆绑应用(main / Electron 进程) — 下限为根 package.json 中固定 Electron 版本(当前
electron 41.7.0)内嵌的 Node/V8,需查该 Electron 发行版对应的 Node 版本。 - config/plugins 子进程与
cypressCLI — 运行在用户的 Node 上,支持范围由 cli/package.json 的engines.node定义(当前为^22.0.0 || ^24.0.0 || >=26.0.0)。文档特别指出这条下限低于开发/捆绑版 Node,因此是这类代码的真正约束。源码印证:该子进程即 packages/server/lib/plugins/child/require_async_child.ts,由 packages/data-context/src/data/ProjectConfigIpc.ts fork。 - 随浏览器分发的 bundle(
@packages/app、@packages/frontend-shared、@packages/driver)— 下限为受支持浏览器的最近 3 个大版本。由于 Safari 大约每年才发一个大版本,这条下限回溯的年份最长,是四者中最保守的;@packages/driver运行在用户 AUT 所在浏览器中。对 WebKit,Cypress 运行的是随playwright-webkit依赖打包的 WebKit(当前根 package.json 中固定为1.61.0),而非用户系统 Safari,因此 WebKit 下限跟随该依赖版本。
文档的结论:在依赖某个 API 之前,先对照相应下限核实(Node 查 node.green,浏览器查 caniuse/MDN)。
八、Pull Request、Changelog 与 CI/CD 门禁
PR 规范
CONTRIBUTING.md 是 PR 约定(含决定下一版本号的 semantic-release 标题前缀)的唯一事实来源。此外两条硬性要求:
- 面向用户、随下个版本发布的变化,须在 cli/CHANGELOG.md 增加 changelog 条目,写法遵循 guides/writing-the-cypress-changelog.md(手写精修而非自动生成,条目分 breaking/dependency/deprecation/feat/fix/misc/perf 等区块)。
- 必须完整填写 Pull Request 模板;不适用的小节写
N/A而不是删除——模板不完整的 PR 不会被 review。
CI/CD 流水线
- 主 CI:CircleCI。配置模块化存放在 .circleci/src/(含 pipeline 源文件),编译产物为
.circleci/packed/pipeline.yml;何时需要把分支加入 full-CI 白名单(binary 测试、Windows 任务、V8 snapshot 校验)见 .circleci/AGENTS.md。 - 补充 CI:GitHub Actions 承担安全扫描(Snyk)、SBOM 生成、浏览器版本自动更新与 PR 校验(.github/workflows/)。
- 基线分支:
develop——所有 PR 指向develop,发布分支命名为release/X.Y.Z。 - 多平台矩阵:Linux x64、Linux ARM64、macOS x64、macOS ARM64、Windows 全部并行。
- 发布门禁:所有测试必须通过
ready-to-release聚合 job,之后才会执行npm-release。 - 外部 PR:需先经过
approve-contributor-pr人工审批门禁,CI 才会运行。 - 二进制构建:npm 发布之后单独触发,跨平台二进制组装后经由 CDN 分发。
九、云端开发环境的已知坑
文档最后一段面向 Cursor Cloud 环境给出实操经验,对本地容器化开发同样适用:
- Node.js >= 22.19.0 与 Yarn 1.22.22 预装;
yarn会触发完整 postinstall(patch-package、yarn-deduplicate、rebuild better-sqlite3、lerna build、V8 snapshot)。 - Xvfb 已运行于
DISPLAY=:1,Chrome 位于/usr/bin/google-chrome-stable。 yarn dev启动 Electron GUI(global/dev 模式的 Launchpad):先构建@packages/app与@packages/launchpad的 Vite bundle 再拉起 Electron,GraphQL server 位于http://localhost:4444/__launchpad/graphql。- 开发模式 headless 运行:
yarn cypress:run -- --project <path> --browser chrome --headless。注意:目标项目的 config 文件不能require('cypress'),因为它会从项目根目录解析而非仓库内。 - 测试优先按 scope 运行;
@packages/network等套件需要特权端口(443),在无特权容器中报 EACCES 属预期;@packages/config有两个断言cypressBinaryRoot包含'cypress'的用例,在目录名不同的工作区(如/workspace)会失败——这是已知的路径依赖问题而非代码 bug。 - 聚焦 lint:
yarn lint --scope @packages/<name>。 - 务必从仓库根目录运行
yarn,不要进入子包内执行。
十、小结
AGENTS.md 把 Cypress monorepo 的工程体系收敛为五类信息:六大工作区的职责边界(与根 package.json 的 workspaces 声明一致)、以 Lerna 编排的命令矩阵(每条命令均可在根 scripts 中溯源)、按子系统归类的 50 余个包的架构地图、可由 packages/eslint-config/src/baseConfig.ts 逐条验证的代码与注释规范,以及以 develop 为基线、ready-to-release 聚合 job 为发布门禁的 CI/CD 流程。对需要理解、检索或二次开发这座仓库的工程师与 AI Agent 而言,它是第一份应当通读的地图;本文补充的源码证据(postinstall 链条、ESLint 规则行号、运行时下限出处)则让其中每一条约定都可以被独立验证。
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 StartedRust0623
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