Skip to content
This repository was archived by the owner on Sep 11, 2026. It is now read-only.

fix(js/eslint): resolve bunx via resolveCmd instead of bare PATH lookup - #260

Merged
vitaliytv merged 1 commit into
mainfrom
claude/bun-x-yield-async-iterable-f53ee2
Jul 27, 2026
Merged

fix(js/eslint): resolve bunx via resolveCmd instead of bare PATH lookup#260
vitaliytv merged 1 commit into
mainfrom
claude/bun-x-yield-async-iterable-f53ee2

Conversation

@vitaliytv

Copy link
Copy Markdown
Member

Summary

Investigation of #203 found a much more precise repro than originally assumed: the changelog/consistency: yield* … is not async iterable crash correlates with whether the external n-rules script is invoked via bun x <pkg> or directly (bun bin/n-rules.js), not with OS/architecture as the original hypothesis in #203 claimed. 16/16 direct diagnostic calls on the same self-hosted Linux CI agent (Bun.version/revision unchanged) returned a clean async-iterable from Bun.Glob#scan() — never a Promise — while the same command run through bun x reproduced the crash 100% of the time. The root cause of why bun x affects how a nested Bun.Glob#scan() resolves is still unknown/upstream, so glob-compat.mjs keeps its defensive Promise-unwrapping, with comments updated to reflect the corrected hypothesis.

The one concretely fixable half of the report is a related-but-distinct bug this session addresses: js/eslint's runOxlintJson (main.mjs) and runLinterFix (fix-eslint.mjs) spawned bunx by literal name, relying on the inherited $PATH. On the same self-hosted CI, when n-rules is invoked directly (bypassing bun x), the nested spawn('bunx', …) fails with ENOENT despite $HOME/.bun/bin being on $PATH at the CI-step level — the same class of "behavior depends on how the outer process was invoked" issue.

Changes

  • plugins/lang-js/rules/js/eslint/main.mjs: runOxlintJson now resolves bunx via resolveCmd (absolute path) instead of the bare string, matching the pattern already used throughout this codebase for cargo/uv/shellcheck/etc. Throws a clear error if bunx can't be resolved, instead of a raw ENOENT.
  • plugins/lang-js/rules/js/eslint/fix-eslint.mjs: same fix in runLinterFix; missing bunx degrades gracefully (skips oxlint --fix, eslint --fix still runs).
  • npm/scripts/utils/glob-compat.mjs: updated comments — the "self-hosted Linux Bun 1.3.14" hypothesis is corrected to the bun x vs direct-invocation correlation; documents that bun x <local-devDependency> does not apply patchedDependencies, discovered while diagnosing this (a temporary bun patch applied through bun x n-rules produced zero diagnostic output despite being verified to apply correctly to node_modules locally).
  • Tests added for both the resolved-path and not-found branches in main.test.mjs / fix-eslint.test.mjs (also fixes a pre-existing coverage gap: fix-eslint.mjs line coverage was 72.7%, now 98.18%).
  • File docs regenerated for the three touched source files (CRC-driven, per repo convention).
  • Two .changes/ entries (npm, plugins/lang-js, patch/Fixed).

Test plan

  • bun run --bun vitest run plugins/lang-js/rules/js/eslint npm/scripts/utils/tests/glob-compat.test.mjs — 35/35 passed
  • npx @7n/rules lint (delta) — exit 0 (remaining npm-module/* findings in output are pre-existing repo debt unrelated to this diff)
  • npx @7n/rules lint doc-files/check scoped to touched dirs — clean

🤖 Generated with Claude Code

Investigation of #203 showed the changelog/consistency crash
("yield* … is not async iterable") correlates with whether the external
n-rules script is invoked via `bun x` vs directly, not with OS/Bun version
as originally assumed — the Bun.Glob#scan() Promise hypothesis is disproven
by 16/16 clean direct calls on the same self-hosted Linux agent.

The one concretely fixable half of that report: js/eslint spawned `bunx` by
literal name, relying on inherited $PATH — this ENOENTs on self-hosted CI
when n-rules is invoked directly (bypassing bun x). Both call sites now
resolve bunx via resolveCmd (absolute path), matching the pattern already
used everywhere else in this codebase for cargo/uv/shellcheck/etc.

Also documents the bun x + patchedDependencies interaction observed during
this investigation (bun x does not apply patchedDependencies for local
devDependencies) so it doesn't trip up future diagnostics.
@vitaliytv
vitaliytv merged commit e86381a into main Jul 27, 2026
1 of 4 checks passed
@vitaliytv
vitaliytv deleted the claude/bun-x-yield-async-iterable-f53ee2 branch August 15, 2026 04:34
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant