Migrate action to run oxlint instead of eslint#1
Conversation
In-place rewrite of the action-eslint composite action to run oxlint through reviewdog instead of eslint. Captures input renames, the new oxlint→rdjsonl converter, file additions/deletions, and testing plan. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Twenty bite-sized tasks covering: TDD of the JSON→rdjsonl converter, action.yml/script.sh rewrite, deletion of the bundled eslint formatter and repo-root eslint detritus, testdata/test-subproject fixture updates, workflow audit (test.yml rewrite, reviewdog.yml rename, npm-publish.yml deletion), and README rewrite with migration callout. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Validated against oxlint 1.61.0: the output is an object wrapping the
diagnostics array (`{"diagnostics": [...], "number_of_files": N, ...}`),
not a bare array as the initial spec assumed. Bare arrays still parse
for forward-compatibility. Cache file reads so multi-diagnostic files
aren't re-read per diagnostic.
Spec updated to reflect the real shape.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ptions Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Smoke-tested against oxlint 1.61.0: empty.js emits no diagnostics; error.js fires no-var + no-unused-vars; test.js fires no-var + no-empty (with a multi-line span). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Needed a subproject-local .oxlintrc.json to shadow the repo-root config's ignorePatterns (which include test-subproject/) — otherwise oxlint considers every subproject file ignored when invoked inside the subproject. Existing sub-testdata/test.js already fires no-var, no-unused-vars, and for-direction under oxlint defaults, so the JS fixture is unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| @@ -1 +1 @@ | |||
| 🐶 // test for unexpected character | |||
| var unusedVar = 1; | |||
There was a problem hiding this comment.
🚫 [oxlint] <no-unused-vars> reported by reviewdog 🐶
Variable 'unusedVar' is declared but never used. Unused variables should start with a '_'.
There was a problem hiding this comment.
The errors here are duplicated because the workflow tests all three styles of Reviewdog comments. I've confirmed it only reports once per issue on repo code.
| @@ -1 +1 @@ | |||
| 🐶 // test for unexpected character | |||
| var unusedVar = 1; | |||
| for (var i = 0; i < 10; i++) { | ||
| } |
| var a;var b;//comment | ||
| console.log(i); | ||
| function sample() { | ||
| for (var i = 0; i < 10; i++) { |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Previously the action always went through `npx --no-install -c 'oxlint --version'` to detect oxlint, then fell back to `npm install` if that check failed. This broke two pnpm/monorepo cases: 1. pnpm's symlink + workspace:* resolution can make the npx check return non-zero even when oxlint is present. 2. Falling back to `npm install` fails with EUNSUPPORTEDPROTOCOL on any `workspace:*` dep. Now the script resolves oxlint by preference: - binary on PATH -> use directly - ./node_modules/.bin/oxlint -> use directly - neither -> `npm install` as before (still fails on pnpm, but the consumer can opt out by installing oxlint themselves beforehand) Invocation goes through the resolved path; `npx` is only used as a last resort after the install step. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| @@ -0,0 +1,147 @@ | |||
| 'use strict'; | |||
There was a problem hiding this comment.
This is a port of the test output formatter that Reviewdog used for ESLint. It's been modified to work for Oxlint's JSON output and tested against real results.
| jobs: | ||
| eslint: | ||
| name: runner / eslint | ||
| oxlint: |
There was a problem hiding this comment.
This action is used for testing, it's not the actual action that gets run in repo use.
| @@ -1,5 +1,5 @@ | |||
| name: 'Run eslint with reviewdog' | |||
| description: '🐶 Run eslint with reviewdog on pull requests to improve code review experience.' | |||
| name: 'Run oxlint with reviewdog' | |||
There was a problem hiding this comment.
This is the actual production action definition.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| # project has no oxlint on PATH and no ./node_modules/.bin/oxlint — this | ||
| # avoids breaking pnpm / yarn / monorepo setups where `npm install` would | ||
| # reject workspace protocols. | ||
| if command -v oxlint >/dev/null 2>&1; then |
There was a problem hiding this comment.
Use the locally-installed oxlint when possible. Removes the need to work with the repo's specific npm/yarn/pnpm setup.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… two examples Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Closing for now, we'll return. |
Summary
Breaking rewrite of this composite action to run oxlint through reviewdog instead of eslint.
eslint-formatter-rdjsonwith a small Node converter (oxlint-to-rdjsonl.js) that turnsoxlint --format=jsoninto rdjsonl lines forreviewdog -f=rdjsonl.eslint_flags→oxlint_flags; dropsnode_options(no-op for a Rust binary);tool_namedefault becomesoxlint.eslint-formatter-rdjson/, the repo-root.eslintrc.js/package.json/package-lock.json, and thenpm-publishworkflow (nothing to publish).testdata/andtest-subproject/updated so oxlint produces deterministic diagnostics.docs/superpowers/.35 converter unit tests pass (
node --test oxlint-to-rdjsonl.test.js). End-to-end smoke-tested against oxlint 1.61.0.Breaking changes for consumers
oxlint, noteslint.eslint_flags→oxlint_flags.node_optionsremoved.A short "Migrating from action-eslint" section was added to the README.
Test Plan
testworkflow runsnode --test oxlint-to-rdjsonl.test.jsand is green.reviewdogworkflow exercises the action across Node 18/20/22 againsttestdata/andtest-subproject/sub-testdata/; annotations appear on this PR.oxlint --format=json testdata/ | node oxlint-to-rdjsonl.jsand confirm rdjsonl output.🤖 Generated with Claude Code