Skip to content

feat(heureka): migrate ESLint config to vite-react-ts.mjs - #1883

Open
hodanoori wants to merge 12 commits into
mainfrom
hoda-heureka-update-vite-react-type-script
Open

feat(heureka): migrate ESLint config to vite-react-ts.mjs#1883
hodanoori wants to merge 12 commits into
mainfrom
hoda-heureka-update-vite-react-type-script

Conversation

@hodanoori

@hodanoori hodanoori commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Migrates the Heureka application from the legacy juno-typescript.mjs ESLint config to the new vite-react-ts.mjs configuration. The new config provides pure TypeScript linting rules without JavaScript rule interference, enabling strict type checking across the app. All 18+ legacy workaround rule overrides have been removed and replaced with real fixes. Part of the project-wide ESLint migration epic #1565.

Changes Made

  • Switch eslint.config.mjs to import vite-react-ts.mjs and remove all legacy rule workarounds
  • Add void operator to all fire-and-forget navigate() calls to satisfy no-floating-promises
  • Wrap async onClick handlers with void to fix no-misused-promises
  • Remove async from test loaders and act() callbacks that had no await (require-await); restore await act(async () => {...}) with a scoped disable for two Suspense-dependent tests where the async is required for React promise resolution
  • Replace issuesPromise && (...) with issuesPromise != null && (...) to fix no-misused-promises in boolean conditionals
  • Type queryClient.setQueriesData cache callbacks with a local cache shape type instead of any
  • Type getActiveVulnerabilityFilter and sanitizeFilterSettings with concrete types instead of any
  • Cast DateTime GraphQL scalar fields explicitly to fix no-unsafe-assignment
  • Fix getNormalizedError network error shape with an explicit type instead of any cast
  • Remove redundant string | "" union types in ComponentInstance (no-redundant-type-constituents)
  • Remove unnecessary as X type assertions in route validateSearch functions
  • Fix @ts-ignore → removed entirely in codegen.ts (dotenv has types)
  • Add /* eslint-disable */ header to auto-generated graphql.ts
  • Replace any in types/index.d.ts plugin options with Record<string, unknown>
  • Replace any in utils.ts utility functions (isEmpty, isNil, omit) with unknown
  • Fix ErrorBoundary resetKeys prop type from any to unknown[] and remove redundant !! cast
  • Add explicit React.MouseEvent / React.ChangeEvent / Date[] types to event handler callbacks where juno-ui-components prop types resolve as any in CI but correctly locally
  • Add scoped eslint-disable comments for useAuth() from greenhouse-auth-provider and encodeV2/decodeV2 from juno-url-state-provider — these packages export error-typed values in CI due to type resolution differences; each disable has an explanatory comment
  • Apply lint fixes to the new RemediationModal component introduced by a concurrent main branch refactor (same patterns: useAuth() cast, void handleConfirm(), typed input callbacks)
  • Add 2 justified rule overrides in eslint.config.mjs: react-refresh/only-export-components (TanStack Router requires mixed exports in route files) and react-hooks/set-state-in-effect (intentional derived-state sync pattern)
  • Set reportUnusedDisableDirectives: "off" to suppress false-positive warnings for CI-only disables that are unused locally (where package types resolve correctly)
  • Exclude vite.config.ts, vitest.config.ts, vitest.setup.ts, and tailwind.config.ts from ESLint entirely (not included in tsconfig.json, causing parse errors in type-aware linting)

Review Guide

Changes are mechanical and fall into 6 categories — reviewers can approve categories 2–5 at a glance and focus attention on 1 and 6:

  1. Config & setup (eslint.config.mjs, package.json, vite-react-ts.mjs) — the actual migration; the only part worth careful review
  2. void navigate(...) (~10 files) — fire-and-forget navigate() calls marked void; no behaviour change
  3. async removal (~8 test files) — loader: async () =>loader: () => and act(asyncact( where there was no await; no behaviour change. Two Suspense tests keep await act(async () => {...}) with a scoped lint disable.
  4. Promise boolean guards (ImageIssuesList, ImageVersionIssuesList) — {promise && ...}{promise != null && ...}; no behaviour change
  5. Type tightening (utils.ts ×2, ErrorBoundary, getTestRouter, types/index.d.ts, event handler annotations) — any replaced with concrete types or explicit casts with comments
  6. Typed cache callbacks (IssuesDataRow, RemediatedIssueDataRow, RemediationHistoryPanel, RemediationModal) — queryClient.setQueriesData callbacks now use a local RemediationsCache type instead of any; verify the shape matches what's actually stored in the cache

Related Issues

Screenshots (if applicable)

none

Testing Instructions

  1. pnpm i
  2. pnpm TASK

Checklist

  • I have performed a self-review of my code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have made corresponding changes to the documentation (if applicable).
  • My changes generate no new warnings or errors.
  • I have created a changeset for my changes.

PR Manifesto

Review the PR Manifesto for best practises.

Switches from juno-typescript.mjs to vite-react-ts.mjs, removing
all 18+ legacy rule workarounds and fixing every violation surfaced
by the stricter TypeScript-only config.

Signed-off-by: Hoda Noori <hoda.noori@sap.com>
Signed-off-by: Hoda Noori <hoda.noori@sap.com>
Signed-off-by: Hoda Noori <hoda.noori@sap.com>
Copilot AI lite review requested due to automatic review settings August 11, 2026 13:48
@hodanoori
hodanoori requested a review from a team as a code owner August 11, 2026 13:48
@changeset-bot

changeset-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5ed0dc1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@cloudoperators/juno-app-heureka Patch
@cloudoperators/juno-app-greenhouse Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Migrates the Heureka app to the new shared vite-react-ts.mjs ESLint flat-config and updates the app codebase to satisfy stricter type-aware TypeScript lint rules introduced by the migration.

Changes:

  • Switch apps/heureka/eslint.config.mjs to use @cloudoperators/juno-config/eslint/vite-react-ts.mjs and replace legacy rule workarounds with targeted, justified overrides.
  • Apply mechanical lint fixes across the app (e.g., void navigate(...), remove unnecessary async, tighten types / remove any, adjust promise guards).
  • Update Heureka devDependencies/lockfile and add a changeset documenting the migration.

Reviewed changes

Copilot reviewed 41 out of 44 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pnpm-lock.yaml Locks new ESLint-related dependencies needed for the new config/migration.
packages/config/eslint/vite-react-ts.mjs Introduces/adjusts the shared Vite React TS ESLint flat-config used by apps.
apps/heureka/src/utils.ts Tightens utility typings (anyunknown) to satisfy stricter TS lint rules.
apps/heureka/src/types/index.d.ts Replaces Record<string, any> with Record<string, unknown> for plugin options.
apps/heureka/src/routes/vulnerabilities/index.tsx Removes unnecessary type assertion and async loader where no await is used.
apps/heureka/src/routes/services/index.tsx Removes unnecessary type assertion and marks navigate() as fire-and-forget with void.
apps/heureka/src/mocks/getTestRouter.tsx Adjusts test router helper typing/imports to satisfy linting constraints.
apps/heureka/src/generated/graphql.ts Marks generated file and disables linting for it.
apps/heureka/src/components/Vulnerabilities/VulnerabilitiesList/VulnerabilityDetailsPanel/VulnerabilityServices.tsx Adds void to fire-and-forget navigation.
apps/heureka/src/components/Vulnerabilities/VulnerabilitiesList/VulnerabilityDetailsPanel/index.tsx Adds void to navigations and removes redundant boolean cast in heading.
apps/heureka/src/components/Vulnerabilities/VulnerabilitiesList/VulnerabilitiesDataRows/index.tsx Adds void to fire-and-forget navigation.
apps/heureka/src/components/Vulnerabilities/VulnerabilitiesList/index.test.tsx Removes unnecessary async loader in tests.
apps/heureka/src/components/Vulnerabilities/VulnerabilitiesFilters.tsx Adds void to fire-and-forget navigation.
apps/heureka/src/components/Vulnerabilities/Vulnerabilities.test.tsx Removes unnecessary async loader/act(async ...) usage.
apps/heureka/src/components/Vulnerabilities/utils.ts Replaces any with concrete types; adds explicit DateTime scalar casting and safer cache shape typing.
apps/heureka/src/components/Services/utils.ts Tightens error typing and removes redundant type constituents / any usage.
apps/heureka/src/components/Services/ServicesList/ServicesDataRows/index.tsx Adds void to fire-and-forget navigation.
apps/heureka/src/components/Services/ServicesList/ServicePanel.tsx Adds void to fire-and-forget navigation and removes redundant boolean cast in heading.
apps/heureka/src/components/Services/ServicesList/ServicePanel.test.tsx Removes unnecessary async loader in tests.
apps/heureka/src/components/Services/ServicesList/index.test.tsx Removes unnecessary async loader in tests.
apps/heureka/src/components/Services/ServicesFilters.tsx Adds void to fire-and-forget navigation.
apps/heureka/src/components/Services/Services.test.tsx Removes unnecessary async loader/act(async ...) usage.
apps/heureka/src/components/Service/index.tsx Adds void to fire-and-forget navigation.
apps/heureka/src/components/Service/ImageVersionDetails/ImageVersionIssuesList/index.tsx Fixes promise guard in JSX (promise != null && ...).
apps/heureka/src/components/Service/ImageDetails/RiskAcceptanceModal/RiskAcceptanceModal.test.tsx Tightens mocked component typings and removes unnecessary async test wrapper.
apps/heureka/src/components/Service/ImageDetails/RiskAcceptanceModal/index.tsx Wraps async click handler; adjusts auth typing to satisfy lint rules.
apps/heureka/src/components/Service/ImageDetails/index.tsx Adds void to fire-and-forget navigation.
apps/heureka/src/components/Service/ImageDetails/ImageVersionsList/index.tsx Adds void to fire-and-forget navigation.
apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/RemediationHistoryPanel/RemediationHistoryPanel.test.tsx Replaces any promise typing with explicit result shape.
apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/RemediationHistoryPanel/index.tsx Tightens query key/cache typing and wraps async click handler with void.
apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/RemediatedIssuesDataRows/RemediatedIssuesDataRows.test.tsx Removes unnecessary async act(...) usage.
apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/RemediatedIssuesDataRows/RemediatedIssueDataRow/index.tsx Adds typed cache shapes for setQueriesData and removes any usage.
apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/IssuesDataRows/IssuesDataRows.test.tsx Updates test act(...) usage and related lint-driven changes.
apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/IssuesDataRows/IssuesDataRow/index.tsx Adds typed cache shapes for setQueriesData and removes any usage.
apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/index.tsx Fixes promise guards in JSX and adds void to fire-and-forget navigations.
apps/heureka/src/components/Service/ImageDetails/FalsePositiveModal/index.tsx Wraps async click handler; adjusts auth typing to satisfy lint rules.
apps/heureka/src/components/common/Navigation.tsx Adds void to fire-and-forget navigation.
apps/heureka/src/components/common/ErrorBoundary/index.tsx Tightens resetKeys type (anyunknown[]) and removes redundant boolean cast.
apps/heureka/src/components/common/ErrorBoundary/index.test.tsx Tightens spy typing and adds lint suppression for mockRestore call.
apps/heureka/src/components/common/Breadcrumb.tsx Adds void to fire-and-forget navigation.
apps/heureka/package.json Adds ESLint-related devDependencies required by the new config.
apps/heureka/eslint.config.mjs Switches to shared vite-react-ts.mjs config; replaces legacy overrides with 2 justified ones.
apps/heureka/codegen.ts Removes unnecessary @ts-ignore (dotenv has types).
.changeset/heureka-eslint-vite-react-ts-migration.md Adds changeset entry documenting the ESLint config migration.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Suppressed comments (1)

packages/config/eslint/vite-react-ts.mjs:29

  • This config still extends @eslint/js's recommended rules, which reintroduces JavaScript rule sets into what is described (in the PR/epic) as a “pure TypeScript” ESLint config. If the goal is to avoid JS/TS rule mixing, drop the JS recommended config here and rely on the TypeScript-ESLint presets instead.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/heureka/eslint.config.mjs
Comment thread apps/heureka/src/components/Service/ImageDetails/RiskAcceptanceModal/index.tsx Outdated
Comment thread apps/heureka/src/components/Service/ImageDetails/FalsePositiveModal/index.tsx Outdated
hodanoori and others added 9 commits August 11, 2026 15:59
Signed-off-by: Hoda Noori <hoda.noori@sap.com>
Signed-off-by: Hoda Noori <hoda.noori@sap.com>
- Fix inaccurate comment in eslint.config.mjs: ignores excludes files
  entirely, not just from type-aware linting
- Fix bug: act() with sync callback returns void, not the render result;
  capture unmount from renderWithRouter() directly

Signed-off-by: Hoda Noori <hoda.noori@sap.com>
…nces

- Add explicit React.MouseEvent types to event handlers (stopPropagation,
  preventDefault) where juno-ui-components prop types resolve as any in CI
- Add explicit ChangeEvent/Date[] types to RemediationModal input handlers
- Add explicit string|undefined type to onSearch callbacks
- Add eslint-disable comments for greenhouse-auth-provider and
  juno-url-state-provider types that are error-typed in CI (EmbeddedAuth,
  AuthState, encodeV2, decodeV2)
- Add eslint-disable to vi.mock importActual calls in test files
- Add eslint-disable to getSeverityColor/getSeverityIcon assignments
- Set reportUnusedDisableDirectives: off to suppress unused-directive
  warnings for CI-only disables

Signed-off-by: Hoda Noori <hoda.noori@sap.com>
Signed-off-by: Hoda Noori <hoda.noori@sap.com>
…ons error type in CI

Signed-off-by: Hoda Noori <hoda.noori@sap.com>
…rors

Signed-off-by: Hoda Noori <hoda.noori@sap.com>
Signed-off-by: Hoda Noori <hoda.noori@sap.com>
@hodanoori hodanoori added the greenhouse-pr-build Set this label to create a preview image which will automatically set the `greenhouse-pr-preview` label Aug 12, 2026
@github-actions github-actions Bot added the greenhouse-pr-preview THIS LABEL IS SET AUTOMATICALLY. label Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

greenhouse-pr-build Set this label to create a preview image which will automatically set the `greenhouse-pr-preview` greenhouse-pr-preview THIS LABEL IS SET AUTOMATICALLY.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Task](Heureka): Migrate to new Vite-React-TypeScript ESLint configuration

2 participants