:用真实前端框架验证 pnpm 与 pacquet 的安装一致性)
pnpm 生态端到端测试ecosystem-e2e用真实前端框架验证 pnpm 与 pacquet 的安装一致性【免费下载链接】pnpmFast, disk space efficient package manager项目地址: https://gitcode.com/gh_mirrors/pn/pnpm导读本文介绍 pnpm 仓库中专门用于验证包管理器安装结果可用性的端到端测试任务ecosystem-e2e源码位于 pnpm/tasks/ecosystem-e2e。它以真实的前端框架项目Next.js、Vite React、Angular、Astro、SvelteKit、Nuxt、React Router为被测对象用 pnpm CLI 与 pacquet 两套并行实现、在两种node_modules布局下分别安装再通过构建与生产服务器启动两个阶段证明产物布局真实可用。读完本文你将掌握该任务的测试网格设计、四个执行阶段、命令行用法、如何扩展新的技术栈以及它在仓库 CI 中的落地方式。任务存在的两个原因按文档 README.md 的说明这个任务的存在源于本仓库两个特有的关注点pacquet 一致性paritypacquet 与 pnpm CLI 是本仓库内并行维护的两套实现需要保持行为一致。一个在 pnpm 下能正常安装并构建、却在 pacquet 下失败的真实框架项目是远比任何单元测试都强的一致性信号——它直接暴露两套实现之间可观测的行为差异。全局虚拟存储global virtual store全局虚拟存储会改变依赖物理存放的位置属于与迫使 Yarn 为 PlugnPlay 构建生态测试同类的结构性变更。只有把真实技术栈跑在这种新布局之下才能发现哪些工具会因新布局而损坏。因此这个任务不是通用冒烟测试而是专门服务于双实现一致性与新布局兼容性两个具体风险点。测试网格三轴笛卡尔积每次运行都是三个维度的笛卡尔积README 用如下网格示意binary: pnpm | pacquet (--binary) layout: isolated | global-virtual-store (--layout) stack: next | vite-react | ... (--stack, defaults to all)binary 轴由 pnpm CLI 还是 pacquet 执行安装layout 轴使用默认的isolated布局还是启用enableGlobalVirtualStore的global-virtual-store布局stack 轴被测真实框架默认为全部。在源码 cli_args.rs 中BinaryChoice与LayoutChoice枚举定义了这三个选择项每个选择项都有一个expand()方法把both展开为两个具体值。网格中的每个单元格由Cell { stack, binary, layout }表示其id()方法生成stack--binary--layout形式的标识见 runner.rs例如next--pnpm--isolated。单元格的四个执行阶段每个单元格依次执行四个阶段在第一个失败处停止runner.rs 中的run_cell按顺序调用各阶段并短路返回失败1. prepare准备用pnpm dlx将技术栈脚手架项目一次性生成不安装依赖然后拷贝到该单元格的工作目录并写入一份pnpm-workspace.yaml。该文件同时钉住独立的 store/cache 目录与布局选项核心内容如下由 runner.rs 的write_workspace_yaml生成enableGlobalVirtualStore: false # 或 true取决于 layout 轴 dangerouslyAllowAllBuilds: true storeDir: cell-dir/store # 每个单元格独立 store保证冷启动 cacheDir: cell-dir/cache从源码注释可以推断其设计意图把 store 与 cache 钉在单元格内部是为了让 pnpm 与 pacquet 永不共享 store、每个单元格都从冷状态开始enableGlobalVirtualStore被显式写出是为了无论两套二进制各自默认值如何layout 轴对两者含义一致dangerouslyAllowAllBuilds: true让 esbuild 等依赖的构建脚本无人值守运行使 build 阶段真正面对一个完整构建出的node_modules——这是生态测试的意义所在而非安全姿态这些只是从钉死版本的生成器脚手架出的临时项目。2. install安装执行binary install即由被测的 pnpm 或 pacquet 完成依赖安装runner.rs。3. build构建运行项目的构建脚本但PATH 前置node_modules/.bin、完全不经过任何包管理器——这样构建无法触发重装从而不会掩盖被测安装的结果。该阶段证明布局在**打包期bundle time**可以正确解析依赖runner.rs。实现上直接读package.json中的scripts.build并用绝对路径的/bin/sh执行因为子进程的 PATH 被前置了node_modules/.bin若用裸sh启动依赖包如果恰好提供了.bin/sh就可能顶替系统 shell。4. serve运行服务启动生产服务器通过 HTTP 轮询直到它响应要求返回非错误状态码2xx/3xx随后杀掉进程runner.rs。该阶段证明布局在**运行时runtime**可用——请求时刻的require、SSR、原生插件等仅靠 build 无法覆盖。实现细节通过绑定127.0.0.1:0动态挑选空闲端口pick_free_port探测时只读取 HTTP 状态行、不读 bodyprobe2xx/3xx 视为成功连接错误与 4xx/5xx 会重试至超时因为很多开发服务器预热期间会短暂拒绝连接探测路径与超时由各 stack 的Serve配置给出对于通过环境变量而非命令行参数取端口的服务器如 nitro、react-router-serve会同时注入PORT/HOST环境变量服务器无论结果如何都保证被 kill。没有服务器的技术栈会跳过该阶段--skip-serve可全局跳过用于快速迭代。运行方式与命令行参数从仓库根目录运行需先构建 pnpmcargo build --release --bin pnpm# 整个网格、全部 stackpnpm 需已构建cargo build --release --bin pnpm cargo run -p pnpm-ecosystem-e2e -- --pacquet ./target/release/pnpm # 只用 pnpm、单个 stack、两种布局 cargo run -p pnpm-ecosystem-e2e -- --binary pnpm --stack vite-react # 迭代模式跳过重复脚手架 cargo run -p pnpm-ecosystem-e2e -- --stack vite-react --keep任一单元格失败则退出码非零。每个单元格的日志写入work-dir/cells/cell-id/cell.log。完整的 CLI 参数定义在 cli_args.rs逐项说明如下参数默认值说明--pnpm pathpnpmpnpm 可执行文件路径。始终必需无论哪个 binary 执行安装所有 stack 都由 pnpm 经pnpm dlx脚手架生成--pacquet pathpacquetpacquet 可执行文件路径仅当--binary包含 pacquet 时必需--binary pnpm\|pacquet\|bothboth由谁执行安装--layout isolated\|global-virtual-store\|bothboth要演练的node_modules布局--stack name全部限定 stack可重复传参名字匹配STACKS中的name--work-dir pathecosystem-e2e-work存放脚手架模板与各单元格工作树的目录每次运行开始会被清空除非传--keep--keep关闭保留上次工作目录复用已脚手架好的模板便于本地迭代--skip-serve关闭在 build 阶段后停止不再启动并探测应用。serve 才是证明运行时可用性的阶段因此仅用于快速迭代主流程main.rs会先校验可执行文件存在文件不存在则查$PATH见ensure_program随后对每个选中的 stack 执行脚手架一次 → 遍历 binary × layout 全部单元格。若脚手架失败该 stack 的所有单元格都会被标记为失败doomed_cells以保证最终报告仍是一张完整的网格最终报告逐行打印单元格 id、PASS/FAIL、耗时以及失败阶段与日志路径。扩展新的技术栈在 stacks.rs 的STACKS常量中追加一个Stack。每个栈需要四个要素name网格 id 中使用的名字scaffold一组ScaffoldCommand每个命令对应一次pnpm dlx spec args...调用不安装依赖生成的文件跨 binary 与 layout 完全一致随后被拷贝进每个单元格build_scriptpackage.json中负责构建的脚本名serve可选的Serve描述如何启动并探测生产服务器——command中的字面量{port}会被替换为运行时挑选的空闲端口另含ready_path轮询的 HTTP 路径与timeout_secs超时秒数。README 特别强调生成器必须钉住大版本——未钉住的latest会把上游框架的一次发版变成红色单元格看起来像 pnpm/pacquet 的回归。钉住的版本升级必须是有意为之。当前内置的 7 个 stack脚手架命令均经pnpm dlx执行、build_script均为buildstack脚手架命令服务端启动命令超时nextcreate-next-app15 app --ts --app --no-eslint --no-tailwind --no-src-dir --no-turbopack --no-import-alias --use-pnpm --skip-installnext start --port {port} --hostname 127.0.0.160svite-reactcreate-vite6 app --template react-tsvite preview --port {port} --strictPort --host 127.0.0.130sangularangular/cli19 new app --defaults --skip-install --skip-git --package-manager pnpmng serve --port {port} --host 127.0.0.1120sastrocreate-astro5 app --template minimal --no-install --no-git --skip-houston --typescript strictastro preview --port {port} --host 127.0.0.130ssveltekitsv0.16 create app --template minimal --types ts --no-add-ons --no-installvite preview --port {port} --strictPort --host 127.0.0.130snuxtnuxi3 init app --template minimal --packageManager pnpm --no-install --no-gitInitnuxi preview端口走环境变量PORT60sreact-routercreate-react-router7 app --no-install --no-git-init --yesreact-router-serve ./build/server/index.js端口走环境变量PORT30s注意所有生成器都写入名为app的项目目录常量PROJECT_DIR见 stacks.rsserve.command中的可执行文件从该项目的node_modules/.bin直接解析。环境隔离的安全设计所有运行第三方代码的子进程脚手架、安装、构建、服务脚本都经由sandboxed_commandrunner.rs启动环境被清空后仅放行白名单变量ENV_PASSTHROUGH含PATH、HOME、TMPDIR、LANG、代理类变量与 CA 证书类变量等目的是防止不可信包的 lifecycle 脚本读取环境中的 CI 密钥如GITHUB_TOKEN、npm 认证 token。构建与 serve 子进程的 PATH 会被前置node_modules/.binbin_path保证 next、vite 等本地安装的二进制优先于任何全局安装。在 CI 中的落地工作流定义在 .github/workflows/ecosystem-e2e.yml触发方式每日定时cron0 6 * * *加手动workflow_dispatch而不是每次 PR 触发。README 明确说明红色单元格是需要调查的信号而非合并阻塞项因此采用 cron 而非 per-PR构建阶段buildjob 一次性编译 pacquet、harness 与 pnpm bundlecargo build --release --bin pnpm --bin ecosystem-e2e并pnpm --filter pnpm run compile产物上传后由各 stack job 共享避免在整张矩阵中重复数分钟的 Rust 与 bundle 构建矩阵编排ecosystem-e2ejob 以matrix.stack展开七个 stack每个 stack 一个 job——慢或易抖动的 stack 不会掩盖其他 stack且每个 stack 都有独立的日志 artifacttimeout-minutes: 60兜底挂死的 build/serve 子进程被测二进制CI 中--pnpm传入一个包裹了仓库自身pnpm11/pnpm/bin/pnpm.cjs的启动脚本--pacquet传入刚构建出的target/release/pnpm从而用本仓库的 pnpm 与 pacquet 做对比注意工作流中chmod x恢复了 artifact 丢失的可执行位日志留存ecosystem-e2e-logs-stack工件收集ecosystem-e2e-work/**/*.log保留 7 天供失败调查。小结ecosystem-e2e用真实框架 × 双实现 × 双布局的网格把安装一致性验证从单元测试层面提升到真实项目可用性层面prepare保证被测对象一致install考验安装器本身build验证打包期依赖解析serve验证运行时行为。它是本仓库中少见的、直接以真实生态项目为试金石的工程质量工具其设计钉版本防误报、阶段短路、日志留存、cron 而非 per-PR对任何需要验证包管理器或构建工具行为一致性的项目都有借鉴价值。【免费下载链接】pnpmFast, disk space efficient package manager项目地址: https://gitcode.com/gh_mirrors/pn/pnpm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考