Repository navigation
Commit 004871f
test(cli): spawn the CLI source entry with node, not the tsx binary, in 76 test files (#28637)
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XCHfAmysCiUnEeJgGTefeZA)_
Part of #23181 (slice 34). The card stays open for later slices: this
one takes only the tsx → `process.execPath` lever on the 78
`packages/cli` test files in the order's list.
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么**:`packages/cli` 里 76 个测试文件起 CLI 源码入口 `bin/run-dev.js` 时,不再经
`node_modules/.bin/tsx` 包装层,改为直接用 `process.execPath`(测试自己的 node)起同一个入口,与
migrate 系列(slice 12)、slice 25、slice 28 已有写法一致。其中 23 个文件还改正了因此变假的注释。清单里其余
2 个文件保留 tsx,原因见下。
- **为什么改**:卡 #23181 的测试提速职责。tsx 包装层是多出来的一个 node
进程加一次转译;入口文件、`src/`、`NODE_ENV=development` 两种起法都一样(oclif 在 development
下自己在进程内注册 tsx,把命令树映射到 `src/`,已用 debug 日志实测)。A/B 六个文件,每个快 25%–43%。
- **风险与回滚**:只改测试文件,不发布任何东西(cli 的 `files[]` 只有
dist、README、CHANGELOG);没有删、没有放宽任何断言,用例名和数量不变,层级划分不变;回滚即 revert。
- **先看**:`packages/cli/test/verify-json-stdout.test.ts`(改正了"纯 node 会从
dist
读命令"这句错注释);`packages/cli/test/serve-publishes-bound-port.e2e.test.ts`(进程组清理的注释,不再有
tsx
孙进程);`packages/cli/test/diff-usage-error-stream.e2e.test.ts`(唯一一处断言改动:对照用例检查的启动器从
tsx 换成 `process.execPath`)。
- **两分钟验证**:`pnpm --filter @objectstack/cli exec vitest run --project
integration test/verify-json-stdout.test.ts
test/generate-refuses-retired-generator.test.ts` → 11/11 通过。
- **需要你做的**:无,席位落地。
## What changes
**Sort.** The order's list
(`pm-orders/server/evidence/23181-s34/files.txt`) re-derived on base
`7449e479c4`: `git grep -lw TSX` over `packages/cli` gives 131 paths;
minus `test/helpers/**`, the 53 left over are every file slices 24–33
own plus two non-test sources (`src/utils/authored-source-codemod.ts`,
`vitest-tiers.ts`). So the list is exactly the 78 files, no difference.
One note on the order's wording: 33 of the 78 import `TSX` from
`test/helpers/serve-process.ts`; the other 45 declare their own `const
TSX = resolve(…, 'node_modules/.bin/tsx')`. Both spawn the same way.
| bucket | files | what happens |
|:--|--:|:--|
| (a) spawns `bin/run-dev.js` through the tsx binary, and the test is
not about that launcher | 76 | switched to `process.execPath` |
| (b) already on `process.execPath`, tsx only in prose | 0 | none |
| (c) keeps tsx | 2 | `run-dev-unbuilt-workspace.e2e`: it pins
`bin/run-dev.js`'s own stderr drain and EPIPE survival, and the shim's
header measures that listener shape under tsx (tsx's hooks worker pipes
into `process.stderr`, so Console's keep-alive is never installed); it
also drives the run with a `--import` hook through `NODE_OPTIONS`.
`serve-host-fallback-base.e2e`: its child is not the CLI entry but a
`probe.mjs` that imports `src/commands/serve.ts` directly, which needs
the tsx loader (the slice 25 reading: no gain for a `.ts` helper child)
|
**The switch, bucket (a).** Every spawn site passes `process.execPath`
where it passed `TSX`, with `bin/run-dev.js` still the first argument;
the child env, cwd, argv, stdio and timeouts are unchanged. A local
`TSX` constant is removed; a helper import drops `TSX` (the export
stays). Spawn shapes covered: `spawn`, `spawnSync`, `execFile`,
`execFileSync`, promisified `execFile`, the files' own `run(file, …)`
wrappers, the `script(1)` command line of the two login NDJSON files,
the `os` shell shim in `i18n-extract-check-hint`, and the `{ exec, argv
}` entry of `start-port-banner-agreement`'s auto-shift leg. The three
generate files' `runTsx` helper is now `runCli`.
**Why the child is the same.** `bin/run-dev.js` pins
`NODE_ENV=development`; under it @oclif/core 5.1.2 (`config/ts-path.js`)
registers tsx in-process and maps `dist/commands` to `src/commands`,
with `packages/cli/dist` built or not. Probe on this branch with `dist/`
built: `DEBUG='*ts-path*' node bin/run-dev.js --version` logs
`registering tsx at …/packages/cli`, `Successfully imported tsx` and
`Found source directory for …/dist/commands at …/src/commands`
(`pm-orders/server/evidence/23181-s34/oclif-ts-path-probe.txt`). The
entry's own static `../src/utils/*.ts` imports load through Node 22's
type stripping (`.nvmrc` = 22), as on the slice 12 files.
**Prose that became false**, corrected in 23 files: the eight `verify-*`
files said plain node makes oclif resolve the command from `dist/` (the
probe above says otherwise); `serve-publishes-bound-port`,
`serve-port-drift-notice` and `package-install-local-jobs-shared-name`
described a tsx shim with the CLI in a grandchild; the rest said "spawns
the CLI through `tsx`", "cold `tsx` starts" or "`bin/run-dev.js` + tsx".
Prose that stays true is unchanged ("`src/` through tsx", "oclif + tsx
cold start", quotes of `bin/run-dev.js`'s header). The `// test-budget:`
headers of the six `package-install-local-*` files still say "the tsx
source entry"; this slice does not touch headers.
The one assertion edit: `diff-usage-error-stream`'s control case
`resolves the dev entry it drives` checked `existsSync(TSX)`; it now
checks `existsSync(process.execPath)`, the launcher it drives. Same
meaning.
Not changed: no case name, case count, timeout, tier, project or `//
test-budget:` header; no file under `test/helpers/**`; no source file.
## Tests
- **All 76 switched files pass on `6410254c`** (the fix commits, before
the merge). Queue tier: `vitest run --project integration
--maxWorkers=2` over the 29 non-`.e2e` files: 29/29 files, 213/213
tests. Nightly tier (`OS_TEST_TIERS=nightly`), the 47 `.e2e` files:
47/47 files, 671/671 tests. Lock VERDICT command-exit 0 on both.
- **Tiers unchanged.** `tierSignals` from `packages/cli/vitest-tiers.ts`
on all 78 files before and after: 78 `integration`, identical. The
switched files still import or name `CLI` / `run-dev.js`.
- **A/B**, six files over six commands. Head `6410254c` vs base
`7449e479c4`, one box, one lock hold, N=3, `--maxWorkers=1`. Base bytes
swapped into the same path (blob hash checked) so both legs keep the
same tier and config; each leg its own vitest invocation, order
alternated per round; restored from `HEAD` and `git diff HEAD` empty
after. Reading: the default reporter's per-file line. Every leg exit 0,
same test counts per side.
| file | base (s) | head (s) | change |
|:--|:--|:--|--:|
| `generate-refuses-retired-generator` | 6.52, 6.73, 6.03 | 4.73, 4.80,
4.95 | -24.9% (mean 6.43 → 4.82) |
| `verify-json-stdout` | 22.06, 23.04, 23.01 | 14.86, 14.73, 16.12 |
-32.9% (mean 22.70 → 15.24) |
| `serve-migrate-exit-schema-parity.integration` | 21.30, 21.44, 20.36 |
13.39, 12.90, 13.21 | -37.4% (mean 21.04 → 13.17) |
| `i18n-check-platform-bucket.e2e` | 47.01, 44.79, 45.16 | 26.01, 26.19,
26.61 | -42.5% (mean 45.65 → 26.27) |
| `login-json-ndjson.e2e` | 20.21, 19.73, 20.03 | 12.37, 12.83, 12.84 |
-36.6% (mean 19.99 → 12.68) |
| `requires-retired-capability.e2e` | 18.34, 18.64, 16.96 | 10.60,
10.44, 11.30 | -40.0% (mean 17.98 → 10.78) |
Raw legs and the script:
`pm-orders/server/evidence/23181-s34/ab-summary.txt`, `ab.sh`.
- `pnpm --filter @objectstack/cli typecheck` (tsc and
`check:test-typecheck`, which compiles the test layer under
`tsconfig.test.json`) exit 0 on `6410254c`, with
`NODE_OPTIONS=--max-old-space-size=4096`; the debt ledger is unchanged
(3 files, 28 errors, 6 pinned signatures). `eslint --no-inline-config`
over the 76 files exit 0 (`@objectstack/cli` has no `lint` script).
- No ablation: no tested behaviour changed (test-only).
## Acceptance notes
- **Out of scope, for a later helper slice.** The helper's own `serve`
spawn (`test/helpers/serve-process.ts`, `runServe()`, around line 982)
still goes through `TSX`. 12 test files call `runServe(` in code
position: `artifact-pinned-boot.e2e`, `serve-app-runtime-hooks.e2e`,
`serve-boot-diagnostics-noise-budget.e2e`, `serve-boot-diagnostics.e2e`,
`serve-cluster-driver-diagnosis.e2e`, `serve-no-artifact.e2e`,
`serve-organizations-host-resolution.e2e`,
`serve-organizations-mount-failure.e2e`,
`serve-package-declared-capabilities`,
`serve-package-registry-always-on.e2e`, `serve-port-readback.e2e`,
`uncreatable-directory-doors.integration`. Carrier: #23181.
- **`skip-changeset`.** Test-only. `@objectstack/cli`'s `files[]` is
`dist`, `README.md`, `CHANGELOG.md`; its build emits no `*.test.ts` into
`dist/`. No `files[]` content changes.
## Verification
Head `95b877c4`: the two fix commits `106e7364` (the switch) and
`6410254c` (the prose), plus one merge of `origin/main` after slices 24
(#28610), 26 (#28599) and 28 (#28616) landed, as the order asks. The
merge touches none of the 78 files and nothing under `test/helpers/**`.
- After the merge: `pnpm install --frozen-lockfile && pnpm build`
(117/117 tasks), then the 29 queue-tier switched files again: 29/29
files, 213/213 tests. The 47 nightly files, the A/B and the typecheck
above were taken on `6410254c`.
- Derived gates (`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` on `95b877c4`, the same 48 as before the
merge): 48/48 exit 0, exit codes captured before any pipe. `--ran`
reconcile: 48 accounted, 48 run, 0 NOT-MEASURED, exit 0
(`pm-orders/server/evidence/23181-s34/gates-ran-95b877c4.txt`).
Prerequisites: `check-plugin-teardown-shape --self-test` after fetching
its control commit; `check:dual-build-cjs-loads` after the full build.
- By hand: `check-commit-card-trailers --range origin/main..HEAD` exit
0; `check-nul-bytes` exit 0.
- CI: the PR's check-runs are the seat's reading.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01FEkQ5n9VfyHfEFRqzGZkWN)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 28ef35e commit 004871f
76 files changed
Lines changed: 171 additions & 233 deletions
File tree
- packages/cli/test
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
85 | 85 | | |
86 | 86 | | |
87 | 87 | | |
88 | | - | |
89 | 88 | | |
90 | 89 | | |
91 | 90 | | |
| |||
127 | 126 | | |
128 | 127 | | |
129 | 128 | | |
130 | | - | |
| 129 | + | |
131 | 130 | | |
132 | 131 | | |
133 | 132 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
85 | | - | |
86 | 85 | | |
87 | 86 | | |
88 | 87 | | |
| |||
93 | 92 | | |
94 | 93 | | |
95 | 94 | | |
96 | | - | |
| 95 | + | |
97 | 96 | | |
98 | 97 | | |
99 | 98 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
91 | | - | |
92 | 91 | | |
93 | 92 | | |
94 | 93 | | |
| |||
111 | 110 | | |
112 | 111 | | |
113 | 112 | | |
114 | | - | |
| 113 | + | |
115 | 114 | | |
116 | 115 | | |
117 | 116 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
96 | | - | |
97 | 96 | | |
98 | 97 | | |
99 | 98 | | |
| |||
105 | 104 | | |
106 | 105 | | |
107 | 106 | | |
108 | | - | |
| 107 | + | |
109 | 108 | | |
110 | 109 | | |
111 | 110 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
75 | 75 | | |
76 | 76 | | |
77 | 77 | | |
78 | | - | |
79 | 78 | | |
80 | 79 | | |
81 | 80 | | |
| |||
86 | 85 | | |
87 | 86 | | |
88 | 87 | | |
89 | | - | |
| 88 | + | |
90 | 89 | | |
91 | 90 | | |
92 | 91 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
51 | | - | |
52 | 51 | | |
53 | 52 | | |
54 | 53 | | |
55 | 54 | | |
56 | 55 | | |
57 | 56 | | |
58 | | - | |
| 57 | + | |
59 | 58 | | |
60 | 59 | | |
61 | 60 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
51 | | - | |
52 | 51 | | |
53 | 52 | | |
54 | 53 | | |
55 | 54 | | |
56 | 55 | | |
57 | 56 | | |
58 | | - | |
| 57 | + | |
59 | 58 | | |
60 | 59 | | |
61 | 60 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
85 | | - | |
| 85 | + | |
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
| |||
94 | 94 | | |
95 | 95 | | |
96 | 96 | | |
97 | | - | |
| 97 | + | |
98 | 98 | | |
99 | 99 | | |
100 | 100 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
75 | 75 | | |
76 | 76 | | |
77 | 77 | | |
78 | | - | |
79 | 78 | | |
80 | 79 | | |
81 | 80 | | |
| |||
270 | 269 | | |
271 | 270 | | |
272 | 271 | | |
273 | | - | |
| 272 | + | |
274 | 273 | | |
275 | 274 | | |
276 | 275 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
41 | | - | |
42 | 41 | | |
43 | 42 | | |
44 | 43 | | |
| |||
49 | 48 | | |
50 | 49 | | |
51 | 50 | | |
52 | | - | |
| 51 | + | |
53 | 52 | | |
54 | 53 | | |
55 | 54 | | |
| |||
0 commit comments