feat(bun,deno): add Bun and Deno runtime support - #988
Conversation
3dbf9d8 to
6e7822e
Compare
|
I had to remove the co-authored-by @bz00qa trailers to get the CLA check to pass (they still have credit in the PR descr) |
|
Thanks for picking up #548 and doing the cleanup — this is a solid PR. RTK has no bun/deno support at all today, so it fills a real gap. It's been open a while and
Once rebased with CI green, this looks ready to merge. Thanks again! |
|
@geofflittle I would love this, I use deno a lot and was looking to do this exact same thing. Let me know if I can help. |
6e7822e to
5001771
Compare
|
@pszymkowiak |
|
@geofflittle — first off, apologies for leaving this hanging. You addressed both points I raised (the The PR is in good shape and I'd like to get it in. Two small things:
Once it's rebased I'll review and get it merged. Thanks for your patience, and sorry again for the silence. |
5001771 to
a121629
Compare
|
@pszymkowiak ready x2! |
|
Tested this extensively with real
Ran Root cause: if is_bun {
let trimmed = line.trim_start();
if line.contains(" pass") || line.contains(" fail") || trimmed.starts_with("Ran ") {
result.push(line.to_string());
}
if line.contains('✗') || line.contains("(fail)") {
failures.push(line.to_string());
}
}
Separately,
Suggested fix: give Everything else I tested (install/add/remove, pm ls with JSON+text fallback, build success/failure, run passthrough, bunx/ |
|
Fixed in 92aa5dd. I used the same methodology as your review (real The Running the same end-to-end approach over the rest of the branch found four more real issues. All fixed before merge:
Everything is backed by committed real-output fixtures and regression tests, and CI is green at 2209a04. Three smaller things I left for a follow-up PR, per your earlier note: bunx/npx tool-dispatch parity (bunx currently routes only tsc/eslint to dedicated filters), compacting deno lint's verbose per-diagnostic frames, and |
pszymkowiak
left a comment
There was a problem hiding this comment.
Thanks, tested this again after your fix — all good. bun test/deno test failures now show the actual error details, no more duplication, exit codes and savings all check out on my end too. LGTM 👍
pszymkowiak
left a comment
There was a problem hiding this comment.
Re-confirming my approval after a full end-to-end verification on the current head (2209a04).
Verified locally:
cargo build✅,cargo test→ 43 tests pass (32 bun + 11 deno), all against real command-output fixtures.- Live e2e on real runtimes (installed bun 1.3.14 and deno 2.9.3, each with a one-pass/one-fail suite):
rtk bun test: surfaced the failing test + assertion detail (Expected: 5 / Received: 4), correct1 pass / 1 failsummary, propagated exit code 1. ~62% token savings.rtk deno test: surfaced the failing test + diff (Actual 4 / Expected 5), correct summary, exit code 1, tee log for full output. ~76% token savings.
Covers both Bun and Deno, real fixtures, exit-code propagation is correct, and it shows assertion detail (nice for agent debugging). LGTM.
@TaKO8Ki could you give this a maintainer pass when you have a moment? It supersedes the narrower Bun-only #1374 and #548. Thanks!
|
Thanks for this — the bun/deno filters look solid and I verified them end-to-end on macOS with real I reproduced the rebase locally to de-risk it — it's small, only 2 things to resolve:
Everything else (README, A |
2209a04 to
05db4d7
Compare
|
Looking forward to this! |
|
This is approved on my end, but |
05db4d7 to
f1e819f
Compare
|
@pszymkowiak ready x3! |
KuSh
left a comment
There was a problem hiding this comment.
Requesting changes. Thanks for the rework — everything from the previous round is addressed (Debug derives, the bun x <tool> space form, argv passthrough so ^/~/npm:/workspace: specs survive, the is_bun_count_line state machine, current-deno FAILURES / FAILED | parsing, the bun pm ls tree parser, deno lint/check routed through never_worse, and pipeline_final_safe via ..RtkRule::DEFAULT).
Is this still needed? Yes. develop has no bun/deno support whatsoever — no bun_cmd.rs/deno_cmd.rs, no bun/bunx/deno tokens in src/main.rs, no discover rules. This supersedes the narrower #548 and #1374, which I'm closing in favour of it.
Two things left before merge:
1. Rebase onto develop — the PR is currently CONFLICTING. It's mechanical: only src/main.rs conflicts, and only inside the mod tests block (develop's new grep-routing tests landed on the same lines as your bun/deno parse tests). Both sides are purely additive — keep both. I reproduced the resolution locally: cargo build clean, cargo test --all → 2918 passed, 0 failed.
2. Eight inline findings below. The first three are the ones that matter — they all hit bun test / deno test failure output, which is the highest-value path in this PR. The rest are small.
Unrelated heads-up so you don't chase it: develop itself doesn't compile right now (the phpt filter from #1503 uses lazy_static! without the crate, and src/discover/rules.rs is missing a pipeline_final_safe). CI will be red on any rebase until that lands separately — it's being fixed.
- core/runner.rs: bun error blocks are kept only with proof bun wrote them - core/runner.rs: emit diagnostics when no failure marker was printed - core/runner.rs: deno section boundaries close an open failure block - tests: real bun 1.3.6 and deno 2.9.6 fixtures for all three cases
- bun_cmd.rs: run_pkg and run_pm_ls use run_filtered, which interleaves the streams and tracks what was actually shown - bun_cmd.rs: pm ls JSON requires a version, so a grouped shape falls through to the tree parser instead of reporting group names as packages - bun_cmd.rs: keep original indentation on kept install lines
- rules.rs: anchor the deno pattern so it cannot match subcommand prefixes - rules.rs: mark deno install and bun pm (non-ls) as passthrough - registry.rs: normalize whitespace in a captured subcommand
- bun_cmd.rs: bun build passes through unless an output flag sends the bundle to disk, and bunx uses the light npm filter instead of errors-only - core/runner.rs: the err and test runners record the tool that actually ran, with a per-tool tee slug - utils.rs, tsc_cmd.rs, main.rs: resolve tools via the project package manager, and keep the tool name when routing eslint - tracking.rs, README.md: categorize bun and deno as js, and describe what the deno check and bun build filters really do
- core/runner.rs: bun and deno share a buffered engine and differ only in an open, prove, close policy table, so a guard cannot land on one runtime alone - core/runner.rs: deno gains the proof rule it never had, so a passing test that logs its own error line no longer reports as a failed suite - core/runner.rs: a block closes when the next one opens, so consecutive stack-free failures stay separate - tests: every scenario is asserted on both runtimes from real fixtures
- utils.rs: tool_exec prefers an explicitly named package runner over lockfile detection, which applies only when nothing was named - tsc_cmd.rs, lint_cmd.rs, main.rs: thread that runner from the invocation - utils.rs: detection can be asked about a directory, so its test needs no chdir - bun_cmd.rs, rules.rs: strip ANSI on the pm ls text fallback, and stop bun build claiming savings it does not deliver
- utils.rs: MissingTool says whether the npm arm may fetch, instead of every newly routed caller inheriting --no-install by accident - tsc_cmd.rs: tsc fetches as it always did, lint and the rest still do not
92563f1 to
d549f9d
Compare
|
Resolving the remaining review threads. Each was verified against the pushed tree and, where the behaviour is observable, against real
Four further rounds of review ran after these threads were opened; those findings are fixed in the same two commits. The ones deliberately left alone, with reasons, are in the PR description and in #2431 ( As noted in the description: I authored the remediation, so this still needs a second maintainer's review. |
Failure detection, so a green run is never reported red: - a failure marker vouches for the block it closes, so a frameless failure such as a timeout keeps the line that says why it failed - bun's marker and run footer are matched with the duration and test count they carry, since a test is free to log a line that starts the same way - deno's FAILURES entries are matched by shape, because a bare " => " also occurs in arrow functions and assertion messages - deno fences output it did not write, and names the fence for when it was printed, so the rule is matched by shape and gates both the failures list and the block engine Diagnostics that were reaching nobody: - deno's type-check errors are kept with the frame under them: they open no block and carry no section, so a type error left the caller with a bare "Type checking failed." - bun's frames are kept, since two failing tests that share a name, and a module error that has no marker at all, cannot otherwise be located Runs whose output rtk must not touch: - watch mode on every filtered entry point goes through unfiltered, since the runners buffer the whole stream until a child that never exits - a deno reporter the user named is left alone, because --reporter=junit and --junit-path write the report to stdout - bun build and deno compile run unfiltered: without an output flag the bundle is stdout, with one the emitted-file summary is the point of the run, and on failure the diagnostics are, none of which an errors-only filter keeps Tool resolution: - a package runner the user named wins over lockfile detection, and over a tool that merely happens to be on PATH - lockfile detection never resolves through bunx, which always fetches a missing tool and cannot be told not to - a tool rtk may fetch resolves through npx, the only runner that can Input and output: - bunx forwards the caller's stdin when it is a pipe, since the filtered path buffers output and an inherited terminal would let a prompt wait invisibly - strip the resolution lines bun actually prints when piped, count the tree levels drawn with a leading pipe, and stop injecting --json into a command the user typed - the lint label records the arguments once, and the shell runners' placeholder tool name stays out of their verbose line Fixtures are real bun 1.2.20 and deno 2.9.6 captures for each case. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A subcommand that runs unfiltered cannot save anything, so classify_command zeroes its estimate rather than letting it inherit the rule's headline. The status and the percentage were separate fields and only the percentage reaches the projection, so marking a subcommand passthrough left the claim standing. The bun and deno percentages are measured against real output rather than against fixtures shaped to the filter: bun install 70, deno lint 40, deno check 50. Each is backed by a captured fixture the module's own test measures. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
d549f9d to
e78427b
Compare
Took over the PR, will require another maintainer review
|
Validated by @pszymkowiak, merging |
Summary
Token-optimized filtering for Bun and Deno CLI commands.
install/add/remove(strip the version header and resolution lines, ~70% measured),test(failures only, ~90%),pm ls(compact dependency list, ~70%),run,buildandpm <non-ls>(passthrough),bunx(routestscandeslintto their filters, everything else through the npm line filter)test(failures only, ~90%),lint(~40%) andcheck(~50%) (strip ANSI, download and blank lines + tee recovery),run/task/install/compile(passthrough)Based on #548 by @bz00qa and carried forward by @geofflittle. Supersedes #548 and #1374.
Why some subcommands are passthrough
bun buildwrites its bundle to stdout when no output flag is given, and its emitted-file summary is the point of the run when one is.deno compileis the same: the artifact path and, on failure, the type-check diagnostics are the payload. An errors-only filter kept neither, so both run unfiltered and are declared 0% in the discover rules rather than claiming savings they cannot deliver.Watch mode (
--watch) is passthrough on every filtered entry point: the filtered runners buffer the whole stream until the child exits, and a watched child never does — so a filtered watch run printed nothing at all and lost the buffer on Ctrl-C. A deno reporter the user named (--reporter=junit,--junit-path) is likewise left alone, since it writes a machine-readable report to stdout.Savings figures
Every percentage above is measured against a captured fixture of real
bun 1.2.20/deno 2.9.6output, and asserted by that module's own test — not against a fixture shaped to the filter.deno lintandcheckkeep every diagnostic; their reduction is ANSI and blank lines, which is why the numbers are lower than a summarizing filter's.Known limitation
bunx <tool>forwards the caller's stdin only when it is a pipe, andrtk npxdoes not forward it at all. That is #2431, which covers every filtered entry point rather than this one; thebunxhalf arrives with this PR and should be fixed there.Test plan
cargo fmt --all --checkcleancargo clippy --all-targets— 0 warningscargo test --all— 3058 tests passbun 1.2.20anddeno 2.9.6: pass/fail/timeout/module-load-error runs, type-check failures, leak failures, watch mode,pm lsnested trees, piped stdin, exit-code propagationMaintainer takeover
@geofflittle has stepped back from this PR. I have taken ownership: rebased onto
developand pushed fixes for five rounds of review findings on top of his work, which is preserved in the history.This needs review by another maintainer — I authored the remediation commits, so I should not be the one approving them.