mcpField
M
monorepo-setup-worktrees

monorepo-setup-worktrees

github.com/editframe开发1968 次安装2 周前更新
代码仓库

关于 monorepo-setup-worktrees

为 Editframe 单体仓库提供按范围隔离的 Git worktree 管理技能,面向并行开发团队和 Agent。它通过统一命令行管理 worktree、Docker 服务及分支同步,并保护主 worktree 始终位于 main。

主要功能

  1. 01按 elements、web、render 范围创建环境
  2. 02管理 worktree 生命周期与健康检查
  3. 03暂停、恢复及清理 Docker 容器
  4. 04同步 main 并清理已合并分支
  5. 05执行渲染冒烟测试

适用场景

  1. 01为多个功能分支并行配置隔离服务
  2. 02按需升级 worktree 的服务范围
  3. 03合并后将 main 更新同步到活跃分支
  4. 04合并前验证渲染流水线更改

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/editframe/skills --skill monorepo-setup-worktrees

安装后在 Claude Code 中输入/monorepo-setup-worktrees确认已加载。

详细介绍

Monorepo 工作树系统

按范围隔离工作树,支持并行开发流。每个工作树都有隔离的 Docker 服务、数据库和域名。

范围

范围服务容器创建时间
elements仅 Elements runner + dev-projects2~28s
webElements + telecine 核心(web、hasura、valkey、maintenance)8~1:30
renderElements + telecine 核心 + render pipeline(workers、scheduler)~22~2:30

升级路径:elements → web → render。不支持降级。

工作树管理

所有工作树操作都使用统一的 CLI:scripts/worktree <command>。

worktree create <branch> [scope]       # Create new worktree (default: web)
worktree list                          # List all worktrees
worktree status [branch]               # Health check
worktree pause <branch>                # Stop containers
worktree resume <branch>               # Start containers
worktree remove <branch> [--force]     # Full cleanup
worktree upgrade <branch> <scope>      # Escalate scope (elements→web→render)
worktree merge <branch>                # Merge branch into main (feature → main)
worktree pull                          # Fetch upstream, update local main, sync main → all worktrees
worktree prune [--dry-run]             # Remove worktrees whose branches are fully merged into main
worktree smoke <branch>                # One-shot render verification
worktree logs [branch] [options]       # View logs
worktree doctor [branch] [--skills]    # Diagnose issues
worktree editor-deps [branch]          # Install host-side node_modules for editor tooling
worktree deps [--workspace=...]        # Show dependency graph

架构

仓库布局
~/Editframe/
  monorepo -> worktrees/main/monorepo   (symlink for convenience)
  worktrees/
    main/
      .worktree-scope               # scope for main (e.g. "render")
      monorepo/                     # primary monorepo checkout [main]
        telecine -> ../telecine     # symlink
        elements -> ../elements     # symlink
      telecine/                     # primary telecine clone [main]
      elements/                     # primary elements clone [main]
    <branch>/
      .worktree-scope               # scope for this branch
      monorepo/                     # monorepo worktree [branch]
      telecine/                     # telecine git worktree [branch]
      elements/                     # elements git worktree [branch]

主工作树(worktrees/main/)必须始终处于 main 分支。 切勿在主工作树目录中运行 git checkout、git switch 或任何切换分支的命令。所有功能开发都应在通过 worktree create 创建的专用分支工作树中进行。LLM Agent 最容易在以下情况下违反这一规则:直接运行 git checkout <branch>,把主工作树当作普通的单检出仓库,或使用需要预先检出分支的合并方式。

scripts/worktree.ts 通过两项严格保护措施强制执行此规则——请勿移除或放宽:

  1. cmdCreate 会在创建任何新工作树前断言主工作树处于 main 分支,并始终以 main 为基础创建新分支。
  2. cmdMerge 会断言每个仓库都已处于 main 分支,并在不检出的情况下执行合并——绝不会在主工作树中调用 git checkout。

~/Editframe/monorepo 是一个便捷符号链接,也是所有工作树命令的入口。

作为 Agent 在分支工作树中工作

Agent 的工作目录在启动时固定——通常是 worktrees/main/monorepo。cd 不会持久生效。 创建或找到分支工作树后,每次文件编辑、Git 命令和脚本调用都必须使用以分支工作树为根的完整绝对路径,而不是相对于 Agent 当前工作目录的路径。

分支为 my-feature 时,工作树根目录为 ~/Editframe/worktrees/my-feature/monorepo/。具体规则:

  • 读取/编辑文件:使用 ~/Editframe/worktrees/my-feature/monorepo/ 下的绝对路径
  • Git 操作:使用 git -C ~/Editframe/worktrees/my-feature/monorepo <command>,或在工具调用中使用 workdir 参数
  • Elements 脚本:~/Editframe/worktrees/my-feature/elements/scripts/<script>
  • Telecine 脚本:~/Editframe/worktrees/my-feature/telecine/scripts/<script>
  • 切勿在分支工作中使用相对路径或 worktrees/main/ 下的路径

查找现有分支的根目录:git worktree list | grep my-feature

脚本中的 EDITFRAME_DIR 始终为 $(dirname $(dirname $(dirname $(git rev-parse --show-toplevel))))——即从 monorepo 检出路径向上三级。

共享基础设施
  • editframe-postgres — 单个共享 PostgreSQL,每个工作树都有自己的数据库(telecine-<branch>)
  • editframe-traefik — 共享反向代理,根据 Host 标头路由(<branch>.localhost)
  • telecine-runner / elements-runner — 共享 Docker 镜像(不会为每个工作树重新构建)
数据库模板

telecine-template 从 telecine-main 克隆而来(304 个迁移 + 种子数据,克隆约需 0.6s)。在主工作树上运行 telecine/scripts/start 执行迁移时,模板会自动刷新。

端口偏移

工作树服务使用基于 cksum 的端口偏移(200 个槽位,间隔为 100),使 Postico 等主机工具能够连接。主工作树使用标准端口。

配置脚本
  • telecine/scripts/worktree-config — 导出 WORKTREE_ID、WORKTREE_DATABASE、WORKTREE_DOMAIN、WORKTREE_DOCKER_PROJECT_NAME 和端口变量
  • elements/scripts/worktree-config — 使用相同模式配置 elements
  • monorepo 工作树根目录中的 .worktree-scope 文件用于跟踪当前范围
Docker Compose 配置文件
  • 无配置文件 = 核心服务(始终启动):runner、web、valkey、graphql-engine、data-connector-agent、maintenance
  • render 配置文件:所有 worker 服务、scheduler-go、jit-transcoding
  • dev 配置文件:tracing、otel-viewer、mailhog、playwright
  • telecine/scripts/start 会读取 .worktree-scope 来设置 COMPOSE_PROFILES
服务启动顺序

Runner 必须先启动,并且必须先完成 npm install,之后才能启动其他会执行应用代码的服务(web、dev-projects、workers)。创建和升级脚本会处理这一流程:up -d runner → npm install → up -d(其余服务)。

将 main 同步到工作树

PR 合并到 main 后(这种情况经常发生),请在 main 工作树中运行 worktree pull:

worktree pull

此命令会依次执行以下三项操作:

  1. 获取 monorepo、telecine 和 elements 的上游远程仓库
  2. 将 origin/main 合并到 telecine 和 elements 的本地 main(无冲突时执行快进合并)
  3. 将本地 main 合并到每个活动工作树分支

package.json、package-lock.json 和 VERSION.ts 中的冲突会自动通过采用 main 版本来解决。其他冲突会被报告并跳过 — 受影响的工作树不会被修改,需要手动解决冲突。

要清理分支已在所有三个仓库中完全合并到 main 的工作树:

worktree prune           # remove all fully-merged worktrees
worktree prune --dry-run # preview what would be removed

prune 会先检查所有三个仓库,再执行任何移除操作 — 只有当某个工作树的分支同时是 monorepo、telecine 和 elements 中 main 的祖先时,才会将其清理。

工作树生命周期

create (elements, 28s) → upgrade (web, 63s) → upgrade (render)
     ↓                         ↓
  pause/resume             pause/resume
     ↓
   remove

开发服务器 URL

elements 的 dev-projects Vite 服务器使用 root: elements/dev-projects/。文件从根路径提供 — 而非 /dev-projects/ 路径。

  • video.html → http://<branch>.localhost:4321/video.html
  • canvas-demo.html → http://<branch>.localhost:4321/canvas-demo.html

URL 路径中不要包含 dev-projects/。

工作树中的 dev-projects

elements/dev-projects/ 已被 gitignore。工作树中只有已提交的空壳文件,不包含完整的 asset/src 目录树。

worktree create 会在工作树的 elements/.env 中设置 DEV_PROJECTS_HOST,使其指向 main 中的 dev-projects。docker-compose.yaml 中的 dev-projects 服务会将此路径挂载到 /packages/dev-projects,因此工作树的开发服务器始终能使用 main 中的完整文件树。

冒烟测试

worktree smoke <branch> 是一次性渲染验证。它不是持久化配置范围;请将其用作渲染管线变更的合并前检查。

  1. 需要 web 或 render 范围(使用 elements 时会报错)
  2. 如果范围是 web:临时启动 render 配置文件中的服务,并注册清理陷阱,在退出时停止这些服务
  3. 如果范围是 render:使用已运行的服务,不管理其生命周期
  4. 在 runner 容器中运行 telecine/scripts/smoke-test.ts,并设置 EF_HOST=http://web:3000 和工作树的 EF_TOKEN
  5. 输出仪表板 URL(http://<branch>.localhost:3000),以便直观检查渲染输出
  6. 提示按 Enter 键后再停止 render 服务(如果这些服务是由该命令启动的)

渲染开发工作流:保持在 web 范围,直接运行单元测试,并使用 worktree smoke 作为合并检查,而不是让完整的 render 服务栈全天运行。

scheduler-go 是预构建的 Go 镜像,不由 docker-compose 管理。worktree smoke 会在首次运行时自动构建它。scripts/build-runner-images 也会构建它。

编辑器工具

Docker 容器使用命名卷来存放 node_modules,这些目录在主机文件系统中不可见。主机上的编辑器(VS Code、Cursor 等)需要自己的 node_modules,以解析 TypeScript 类型和 JSX 内置元素。

worktree create 会自动通过 npm install --ignore-scripts 安装主机端依赖。对于缺少主机端类型的现有工作树,请运行 worktree editor-deps <branch>。worktree doctor 会检测并报告缺失的主机端类型。

故障排查

  • 端口冲突:两个分支的哈希值映射到了相同偏移量。使用 cksum 和 200 个槽位时,这种情况极不可能发生,但仍有可能。移除一个工作树并重新创建。
  • 孤立容器:worktree doctor 会检测孤立项目(没有匹配 Git 工作树的容器),并打印用于清理它们的确切 docker rm -f 命令。
  • 创建部分失败:如果 worktree create 中途失败,工作树目录会存在,但内容不完整。重试前运行 worktree remove --force <branch>。
  • 模板过时:运行 scripts/update-template-db,根据当前主数据库状态刷新模板。

评论

支持 Markdown