Skip to content

test(cli): opt-in pre-built binary for faster subprocess spawns#28278

Open
kitlangton wants to merge 2 commits into
worktree-cli-tier-afrom
worktree-cli-prewarm
Open

test(cli): opt-in pre-built binary for faster subprocess spawns#28278
kitlangton wants to merge 2 commits into
worktree-cli-tier-afrom
worktree-cli-prewarm

Conversation

@kitlangton
Copy link
Copy Markdown
Contributor

Summary

Adds an opt-in pre-built binary path for subprocess test spawns. `bun run --conditions=browser src/index.ts` pays ~15s of JIT + plugin init + DB migration per spawn in isolation mode. A pre-built binary cuts that to ~5s.

The harness (`test/lib/cli-process.ts`) reads `OPENCODE_TEST_CLI_PATH` and spawns the binary directly when set; falls back to dev mode otherwise. Default behavior, CI, and local iteration are unchanged.

Usage

```
bun script/prebuild-test-cli.ts
export OPENCODE_TEST_CLI_PATH="$PWD/dist/test-cli/bin/opencode"
bun test test/cli/
```

Numbers (local, 331 CLI tests)

Mode Runtime Notes
Dev (default) 29.9s `bun run src/index.ts` per spawn
Binary 22.1s After one-time 2.8s build

Net savings: ~5s on full suite (~26% faster). The win compounds — every new subprocess test that hits DB migration saves ~10s vs dev mode.

Implementation notes

  • `script/prebuild-test-cli.ts` wraps the existing `script/build.ts` with `--single --skip-embed-web-ui --skip-install` and symlinks the platform-specific output to a stable `dist/test-cli/bin/opencode` path.
  • Harness change is 3 LOC: one env var read, one helper function, three call sites switch from a hard-coded argv prefix to `cliArgv()`.
  • Strictly opt-in. No risk to existing tests.

Stacked on #28274

Base: `worktree-cli-tier-a` so the diff stays minimal once the parent merges.

Test plan

  • `bun run typecheck` clean
  • `bun run test test/cli/` — 331/331 pass in dev mode (29.9s)
  • `bun run test test/cli/` — 331/331 pass in binary mode (22.1s after 2.8s build)
  • Same test bodies, same assertions in both modes; behavior identical.

\`bun run --conditions=browser src/index.ts\` pays ~15s of JIT + plugin
init + DB migration per subprocess spawn in isolation mode. A pre-built
binary cuts that to ~5s — most of which is now the SQLite \`:memory:\`
migration that runs regardless of execution mode.

Adds \`script/prebuild-test-cli.ts\` which wraps the existing build.ts
with \`--single --skip-embed-web-ui --skip-install\`, then symlinks the
platform-specific output to \`dist/test-cli/bin/opencode\` so the
harness has a stable path.

The harness (test/lib/cli-process.ts) reads OPENCODE_TEST_CLI_PATH and
spawns the binary directly when set; falls back to dev mode otherwise.
Strictly opt-in — default behavior, CI, and local iteration are
unchanged. Anyone who wants the speedup runs:

  bun script/prebuild-test-cli.ts
  export OPENCODE_TEST_CLI_PATH="\$PWD/dist/test-cli/bin/opencode"
  bun test test/cli/

Measured locally:
  Dev mode (default):  29.9s  (331 tests)
  Binary mode:         22.1s  (-26%, after one-time 2.8s build)

The win compounds as more subprocess tests are added — every new test
that hits DB migration saves ~10s vs dev mode.
Applies findings from the third simplify pass:

1. \`cliArgv\` is a module-level const, not a function — prebuiltCli is
   read once at module init and never mutated, so the per-spawn function
   allocation was pure overhead.

2. Help-snapshot failures surface via \`Effect.fail\` instead of \`throw\`,
   symmetric with the \`Effect.fail\` already inside the partition above.
   Keeps the failure typed in the Effect channel rather than as a defect.

3. \`prebuild-test-cli.ts\` skips the build when the binary is already
   newer than every file in src/ — saves the 2.8s rebuild cost on every
   subsequent invocation. Pass --force to bypass.

4. \`prebuild-test-cli.ts\` verifies the built binary is executable before
   symlinking — catches a silently-failed build leaving stale output
   instead of letting tests fail with confusing exec errors later.

Verified: 331/331 CLI tests pass; typecheck clean; skip-if-fresh + --force
behave as documented.
@kitlangton kitlangton force-pushed the worktree-cli-prewarm branch from c16197a to 44b2840 Compare May 19, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant