Skip to content

Replace ESLint with oxlint and graphql-inspector - #12359

Merged
nbudin merged 3 commits into
mainfrom
oxlint-migration
Nov 6, 2026
Merged

nbudin merged 3 commits into
mainfrom
oxlint-migration

Conversation

@nbudin

@nbudin nbudin commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Replaces ESLint with oxlint for JS/TS, and with graphql-inspector for .graphql files. This supersedes the failed ESLint 10 Renovate PR (#11492).

  • JS/TS: new .oxlintrc.json, generated by @oxlint/migrate from the old ESLint config and then trimmed. eslint-plugin-i18next runs as an oxlint jsPlugin (801 warnings, vs 797 under ESLint). eslint.config.mjs, eslint, and 20+ ESLint plugins/configs are removed.
  • GraphQL: oxlint can't parse .graphql, so @graphql-eslint is replaced by graphql-inspector validate (yarn lint:graphql: deprecated-field warnings, --maxDepth 10).
  • #import comments removed from 63 .graphql files. Codegen ignores them, but they broke the graphql-tools loader that graphql-inspector uses (and VSCode).
  • CI: the eslint job (Reviewdog) is now a lint job running oxlint --format=github and yarn lint:graphql. lint-staged runs oxlint --fix.
  • Oxlint errors fixed (separate commit): the React Compiler-style rules (refs, set-state-in-effect, immutability, error-boundaries) and no-unsafe-optional-chaining/no-unused-vars. Notably, scrollToItem in the form presenter read a ref during render, so it was a no-op until something re-rendered; it now resolves the ref when called.
  • Tests (separate commit) for the four refactored components (DateTimeInput, MaximumEventSignupsInput, FileInputWithPreview, OpenLayersMap), verified against the pre-refactor code and by mutating the new code.

Things to know

  • The CI check is renamed from eslint to lint. If branch protection requires eslint, it needs updating before merge.
  • Dropped GraphQL checks: strict-id-in-types on schema.graphql and the per-field depth exemptions have no graphql-inspector equivalent. Max depth is now 10 (Inspector counts depth differently; Reports/queries.graphql fails at 8 and 9).
  • Dropped lint rules: no-undef and react/require-render-return are nursery-only in oxlint; the import/resolver settings aren't carried over; eslint-config-prettier is gone with ESLint (oxlint has no formatting rules).
  • TicketPurchaseForm (auto-selecting the only available product) was also refactored but isn't covered by new tests.

Test plan

  • yarn oxlint app/javascript test/javascript: 0 errors (warnings only)
  • yarn lint:graphql: exits 0
  • yarn ts:check
  • yarn vitest run: 1592 passed, 1 skipped (pre-existing)
  • CI lint job passes
  • Manual check: date/time input, signup limit selector, a map page, CMS file upload, ticket purchase form

Closes #11492

🤖 Generated with Claude Code

nbudin and others added 3 commits November 6, 2026 11:46
- Add .oxlintrc.json (migrated from the ESLint config); eslint-plugin-i18next
  runs as an oxlint jsPlugin
- Validate .graphql documents with graphql-inspector (deprecated-field
  warnings, max depth 10) via `yarn lint:graphql`
- Remove ESLint, its plugins/configs, and eslint.config.mjs
- Remove dangling `#import` comments from .graphql files (unused by codegen,
  and they broke the graphql-tools loader and VSCode)
- Update the static analysis workflow and lint-staged accordingly

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Test casts over optional chains now use `| undefined` with `?.`
- Drop unused variables/catch bindings
- Stop reading refs during render (useValidatableForm, FormPresenter,
  MaximumEventSignupsInput); scrollToItem now resolves the ref when called,
  which also fixes it being a no-op on the first render
- Replace set-state-in-effect with derived state or render-time state
  adjustment (DateTimeInput, FileInputWithPreview, TicketPurchaseForm,
  MaximumEventSignupsInput, OpenLayersMap)
- Remove the unused, impure return value from toggleRunDetailsVisibility
- Avoid constructing JSX inside try/catch in FreeTextItemDisplay

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Cover DateTimeInput, MaximumEventSignupsInput, FileInputWithPreview and
OpenLayersMap, including syncing state from props and the stale-preview and
latest-onChange cases. Verified against the pre-refactor components and with
mutations of the new code.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@nbudin nbudin added dependencies patch Bumps the patch version number on release labels Nov 6, 2026
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Report: Only Changed Files listed

Package Base Coverage New Coverage Difference
app/javascript/BuiltInFormControls/DateTimeInput.tsx 🟠 54.05% 🟢 94.87% 🟢 40.82%
app/javascript/CmsAdmin/CmsFilesAdmin/FileInputWithPreview.tsx 🟢 86.36% 🟢 90.91% 🟢 4.55%
app/javascript/EventsApp/ScheduleGrid/ScheduleGridContext.tsx 🟢 97.1% 🟢 96.92% 🔴 -0.18%
app/javascript/FormPresenter/ItemDisplays/FreeTextItemDisplay.tsx 🔴 23.08% 🔴 21.43% 🔴 -1.65%
app/javascript/FormPresenter/Layouts/FormPresenter.tsx 🟢 88.89% 🟢 81.82% 🔴 -7.07%
app/javascript/Maps/OpenLayersMap.tsx 🔴 0% 🟢 100% 🟢 100%
app/javascript/SignupRoundsAdmin/MaximumEventSignupsInput.tsx 🔴 0% 🟢 91.18% 🟢 91.18%
app/javascript/setupI18Next.ts 🟢 89.66% 🟢 82.76% 🔴 -6.9%
Overall Coverage 🟢 67.35% 🟢 67.54% 🟢 0.19%

Minimum allowed coverage is 0%, this run produced 67.54%

@nbudin
nbudin merged commit a9f1b03 into main Nov 6, 2026
41 of 42 checks passed
@nbudin
nbudin deleted the oxlint-migration branch November 6, 2026 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies patch Bumps the patch version number on release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant