Skip to content

fix(vtz): vtz ci self-hosts config loading — drop bun/tsx requirement#2742

Merged
viniciusdacal merged 1 commit into
mainfrom
fix/vtz-ci-self-host
Apr 17, 2026
Merged

fix(vtz): vtz ci self-hosts config loading — drop bun/tsx requirement#2742
viniciusdacal merged 1 commit into
mainfrom
fix/vtz-ci-self-host

Conversation

@viniciusdacal
Copy link
Copy Markdown
Contributor

@viniciusdacal viniciusdacal commented Apr 17, 2026

Summary

Resolves #2739. vtz ci's config loader used to spawn an external JS runtime to evaluate ci.config.ts — bun preferred, node --import tsx as fallback. That meant bun (or tsx as a devDep) was a hard requirement for vtz ci despite vtz itself being a TypeScript runtime.

Surfaced during the bun→vtz CI migration attempt (closed PR #2733): without bun on PATH, the node+tsx fallback also failed because @vertz/ci's package.json exports don't satisfy strict-Node ESM resolution, which tsx uses. Piling workarounds would have masked the real architectural problem.

This PR makes vtz self-hosting for this path — with no fallback. If the running vtz binary path can't be determined, vtz ci fails fast with a clear error rather than silently picking up bun or tsx (which would mask real bugs in the vtz install / execution path).

Changes

1. vtz __exec <file> [args...] — new hidden subcommand

Runs a single JS/TS file through the vtz runtime with process.argv populated as [vtz_bin, abs_file, ...extra_args]. Not for end-user use — it exists to support internal tooling like vtz ci.

2. find_runtime() in ci/config.rs

Always uses std::env::current_exe() + the __exec subcommand. No bun, no tsx, no fallbacks. If current_exe() fails (extremely rare — platform-specific sandbox edge cases), vtz ci surfaces the error instead of silently switching interpreters.

3. process.exit(code) is now implemented

Via new op_process_exit op. It previously threw. The existing .pipe/_loader.mjs (unchanged in this PR) calls process.exit(0) at the end of its run, so this is necessary for the loader to terminate cleanly under vtz. Flushes stdout/stderr before exit.

Verified end-to-end locally

$ vtz ci test --scope @vertz/errors --concurrency 1
[pipe] Loading ci.config.ts...           ← loaded via vtz, not bun/tsx
[pipe] Workspace: 47 packages, 3 native crates
[pipe] Running with concurrency=1
...

No bun on PATH, no tsx devDependency — and vtz ci works.

Rust quality gates

  • cargo test -p vtz --lib — 3441 pass, 0 fail
  • cargo clippy -p vtz --all-targets -- -D warnings clean
  • cargo fmt --all -- --check clean

Unblocks

After this lands + 0.2.69 publishes, the bun→vtz CI migration (formerly PR #2733) becomes a trivial workflow-only change.

Related tracking issues

🤖 Generated with Claude Code

vtz ci's config loader used to spawn an external JS runtime to evaluate
ci.config.ts — bun (preferred) or node + tsx (fallback). That made bun
or tsx a hard requirement for `vtz ci` despite vtz itself being a
TypeScript runtime. Surfaced in #2739 while migrating CI from
bun install to vtz install: without bun on PATH, the fallback failed
because @vertz/ci's package.json exports don't satisfy strict-Node ESM.

Three changes make vtz self-hosting for this path:

1. New hidden subcommand `vtz __exec <file> [args...]`:
   runs a single JS/TS file through the vtz runtime with process.argv
   populated as [vtz_bin, abs_file, ...extra_args]. Not intended for
   end-user use.

2. find_runtime() in ci/config.rs now prefers std::env::current_exe()
   with the __exec subcommand. bun and node+tsx remain as fallbacks
   for the rare case current_exe() is unavailable.

3. process.exit(code) is now implemented (new op_process_exit op).
   It previously threw. The existing .pipe/_loader.mjs calls
   process.exit(0) at the end of its run, so this is needed for the
   loader to terminate cleanly under vtz.

Verified end-to-end locally: vtz ci test --scope @vertz/errors loads
ci.config.ts without setup-bun on PATH and without tsx as a devDep.
The loader writes config JSON, receives callback eval requests, and
exits cleanly via process.exit.

Unblocks migrating CI from `bun install` to `vtz install --frozen`
(follow-up PR; tracked separately from #2739).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@viniciusdacal viniciusdacal merged commit 7f7ff47 into main Apr 17, 2026
6 checks passed
This was referenced Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

vtz ci: load ci.config.ts via vtz runtime itself (not bun/tsx)

1 participant