Skip to content

fix(oxlint-plugin): Resolve the oxlint bin without assuming a pnpm layout - #5066

Merged
juliusmarminge merged 1 commit into
pingdotgg:mainfrom
mwolson:fix/oxlint-bin-resolution
Jul 31, 2026
Merged

fix(oxlint-plugin): Resolve the oxlint bin without assuming a pnpm layout#5066
juliusmarminge merged 1 commit into
pingdotgg:mainfrom
mwolson:fix/oxlint-bin-resolution

Conversation

@mwolson

@mwolson mwolson commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • The oxlint rule-harness tests hardcoded pnpm's virtual-store hoist path for
    the oxlint binary. Resolve the real package through vite-plus instead and
    run its bin through the current Node binary, so the suite runs under any
    install layout.

Problem and Fix

Problem and Why it Happened Fix
oxlint-plugin-t3code/test/utils.ts spawned node_modules/.pnpm/node_modules/.bin/oxlint, a pnpm-internal hoist path. oxlint is only a transitive dependency (via vite-plus), so no package manager guarantees a stable .bin shim for it: under Bun-style hoisted installs that path does not exist, and the root node_modules/.bin/oxlint is vite-plus's LSP-only wrapper ("This oxlint wrapper is for IDE extension use only"). All 35 rule tests fail with spawn ... ENOENT on such layouts. Resolve oxlint/package.json with createRequire, starting from vite-plus's resolved package directory (the dependency that actually pulls oxlint in), and run the package's own bin/oxlint. Module resolution works identically through pnpm's virtual store and hoisted layouts, so the harness no longer depends on any package manager's .bin placement. Resolution happens once at module scope, so a broken install fails with a single clear resolution error rather than one opaque defect per test.

Defensive Fixes

Problem and Why it Happened Fix
bin/oxlint is an extensionless #!/usr/bin/env node script. Spawning it directly cannot work on Windows (no shebang handling; the old .bin POSIX shim had the same limitation), and on any platform it runs whichever node is first on PATH, which under version managers can differ from the Node running the tests. Spawn process.execPath with the resolved bin script as the first argument, pinning the interpreter to the Node running vitest and removing the dependence on shebang support and the file's exec bit.

Validation

  • vp check: pass (0 errors, 11 pre-existing warnings)
  • vp run typecheck: pass
  • oxlint-plugin-t3code: vp test run passes 35/35 under a non-pnpm hoisted
    install layout; before the change all 35 failed with spawn ENOENT. Under a
    standard pnpm install the resolved path is the same real oxlint package the
    old hardcoded shim pointed at (the pnpm shim ends in
    exec node "$basedir/../oxlint/bin/oxlint"), and CI's Test job passes under
    a real pnpm install.

Note

Low Risk
Test-only harness changes with no production runtime or security impact; behavior under a correct pnpm install stays equivalent to the old shim target.

Overview
The oxlint rule-harness in test/utils.ts no longer spawns a hardcoded pnpm virtual-store path to oxlint. It resolves oxlint/package.json at module load via createRequire, anchored on vite-plus (the package that pulls in oxlint), and builds the path to that package’s bin/oxlint.

Harness runs invoke process.execPath with that script as an argument instead of executing the bin directly, so Windows avoids shebang/extensionless spawn issues and the same Node that runs Vitest interprets the script.

A bad install now fails once at import with a resolution error instead of ENOENT on every rule test.

Reviewed by Cursor Bugbot for commit 3da07e2. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix oxlint binary resolution in oxlint-plugin to work without a pnpm layout

  • Replaces a hardcoded .pnpm-based path with a dynamic resolution using node:module's createRequire, resolving oxlint/package.json relative to vite-plus and deriving the bin path from its directory.
  • Updates process spawning to invoke the oxlint bin script via the current Node executable (process.execPath) rather than directly, which avoids shebang issues on Windows.
  • Behavioral Change: module load now fails immediately with a resolution error if vite-plus or oxlint cannot be resolved.

Macroscope summarized 3da07e2.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 36a51ae4-dc9a-46c3-bcde-68c5ff5286d0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Jul 31, 2026
…yout

The rule-harness tests spawned node_modules/.pnpm/node_modules/.bin/oxlint,
a pnpm virtual-store hoist path. oxlint is only a transitive dependency of
vite-plus, so no package manager guarantees a stable .bin shim for it: under
Bun-style hoisted installs that path does not exist, and the root
node_modules/.bin/oxlint is vite-plus's LSP-only wrapper, so all 35 rule
tests fail with spawn ENOENT. Resolve oxlint/package.json through vite-plus
instead, at module scope so a broken install fails once with a clear
resolution error, and run the package's own bin/oxlint through
process.execPath so the spawn does not depend on shebang support or
whichever node is first on PATH.
@mwolson
mwolson force-pushed the fix/oxlint-bin-resolution branch from ca5f5c6 to 3da07e2 Compare July 31, 2026 03:06
@mwolson
mwolson marked this pull request as ready for review July 31, 2026 03:11
@macroscopeapp

macroscopeapp Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 3da07e2

Test-only infrastructure fix that replaces hardcoded pnpm paths with proper Node module resolution and adds Windows compatibility. No production code is affected.

You can customize Macroscope's approvability policy. Learn more.

@juliusmarminge
juliusmarminge merged commit 894d6d6 into pingdotgg:main Jul 31, 2026
21 checks passed
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Jul 31, 2026
## What's Changed
* fix(ci): repair the mobile showcase screenshots workflow by @juliusmarminge in pingdotgg/t3code#5057
* fix(ci): capture iPad App Store screenshots in landscape by @PixPMusic in pingdotgg/t3code#5065
* fix(oxlint-plugin): Resolve the oxlint bin without assuming a pnpm layout by @mwolson in pingdotgg/t3code#5066


**Full Changelog**: pingdotgg/t3code@v0.0.32-nightly.20260731.963...v0.0.32-nightly.20260731.964

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.32-nightly.20260731.964
@mwolson
mwolson deleted the fix/oxlint-bin-resolution branch July 31, 2026 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants