Files
deepseek-harness/.agents/notes/implemented/bug-fix/2026-07-29-pnpm-setup-runner-isolation.zh.md
T

2.5 KiB

Agent Note: 按 GitHub Actions runner 隔离 pnpm 设置

Status: implemented

English | 中文

问题

pnpm/action-setup@v4 的安装目标目录默认为 ~/setup-pnpm,并会在设置期间替换该目录。自托管 CI 故障切换在同一个 VM 用户下运行六个 GitHub Actions runner 服务,因此并发作业会共用同一目标目录。在 run 30375670773 中,三个作业在 73 毫秒内进入 pnpm 设置;其中一个设置过程删除了另一个进程的当前工作目录,导致两个作业在 Node 的 uv_cwd 初始化阶段失败。换到另一台 runner 重试后通过,说明该故障取决于时序,并非仓库测试回归。

决策

主 CI 工作流中的每个 pnpm/action-setup 步骤都设置 dest: ${{ runner.temp }}/setup-pnpm。每个 runner 服务独占自己的临时目录,因此一个设置过程无法替换另一个 runner 的安装目录。持久 store 的复用仍由 PNPM_CONFIG_STORE_DIR 独立处理,遵循 pnpm 提供机制决策

工作流回归测试会找出 ci.yml 中的每个 pnpm/action-setup 步骤,并拒绝缺少 runner 专属目标目录的步骤。这可确保后续新增的作业也处于同一隔离边界内。

曾考虑的替代方案

串行执行故障切换作业。 否决:这会牺牲由六个 runner 组成的池所具备的预期并行能力,并把 action 内部的目录冲突变成原本相互独立作业之间的队列等待。

为每个 runner 服务分配独立的 Unix 用户。 这同样能够隔离 HOME,但会把该不变量转移到外部 VM 配置中,并使刻意共享的持久 pnpm store 的所有权变得复杂。工作流已经获得 runner 专属临时目录。

重试失败的设置步骤。 否决:重试只能降低观测到的冲突发生率;另一个并发设置过程仍可能再次删除同一个共享目录。

后果

pnpm 可执行文件采用临时安装,并按 runner 隔离;包下载仍使用已配置的持久或缓存 store。托管作业使用相同的显式目标目录,不改变缓存政策。工作流中的每个设置步骤因此增加三行配置;只有在 pnpm 提供机制有意迁移到另一种隔离机制时,才需要更新回归测试。