feat(heureka): migrate ESLint config to vite-react-ts.mjs - #1883
feat(heureka): migrate ESLint config to vite-react-ts.mjs#1883hodanoori wants to merge 12 commits into
Conversation
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>
🦋 Changeset detectedLatest commit: 5ed0dc1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
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 |
There was a problem hiding this comment.
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.mjsto use@cloudoperators/juno-config/eslint/vite-react-ts.mjsand replace legacy rule workarounds with targeted, justified overrides. - Apply mechanical lint fixes across the app (e.g.,
void navigate(...), remove unnecessaryasync, tighten types / removeany, 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 (any → unknown) 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 (any → unknown[]) 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.
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>
| * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
| /* eslint-disable @typescript-eslint/no-unsafe-assignment */ |
There was a problem hiding this comment.
thats in nowhere i am confused
| setIsExpanded(!isExpanded) | ||
| } | ||
|
|
||
| type QueryFilter = { service?: string[]; image?: string[]; vulnerability?: string[] } |
| ` | ||
| } | ||
|
|
||
| type QueryFilter = { service?: string[]; image?: string[]; vulnerability?: string[] } |
| // staleTime: 0 makes ensureQueryData treat any cached entry as immediately stale, forcing a | ||
| // network request without cancelling in-flight queries (unlike removeQueries). | ||
| return fetchRemediations({ apiClient, queryClient, filter, staleTime: 0 }) | ||
| }, [service, image, vulnerability, apiClient, queryClient, refreshKey]) |
There was a problem hiding this comment.
if the linter is right and the refreshKey is not needed good to clean this up
| `Vulnerability ${cveNumber} has been marked as a false positive and moved to the Remediated list.` | ||
| ) | ||
| }, []) | ||
|
|
There was a problem hiding this comment.
may take a look at these linter warnings
| "jsdom": "30.0.1", | ||
| "postcss": "8.5.10", | ||
| "prettier": "3.8.5", |
| postcss: | ||
| specifier: ^8.5.18 | ||
| version: 8.5.23 |
Summary
Migrates the Heureka application from the legacy
juno-typescript.mjsESLint config to the newvite-react-ts.mjsconfiguration. 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
eslint.config.mjsto importvite-react-ts.mjsand remove all legacy rule workaroundsvoidoperator to all fire-and-forgetnavigate()calls to satisfyno-floating-promisesonClickhandlers withvoidto fixno-misused-promisesasyncfrom test loaders andact()callbacks that had noawait(require-await); restoreawait act(async () => {...})with a scoped disable for two Suspense-dependent tests where theasyncis required for React promise resolutionissuesPromise && (...)withissuesPromise != null && (...)to fixno-misused-promisesin boolean conditionalsqueryClient.setQueriesDatacache callbacks with a local cache shape type instead ofanygetActiveVulnerabilityFilterandsanitizeFilterSettingswith concrete types instead ofanyDateTimeGraphQL scalar fields explicitly to fixno-unsafe-assignmentgetNormalizedErrornetwork error shape with an explicit type instead ofanycaststring | ""union types inComponentInstance(no-redundant-type-constituents)as Xtype assertions in routevalidateSearchfunctions@ts-ignore→ removed entirely incodegen.ts(dotenv has types)/* eslint-disable */header to auto-generatedgraphql.tsanyintypes/index.d.tsplugin options withRecord<string, unknown>anyinutils.tsutility functions (isEmpty,isNil,omit) withunknownErrorBoundaryresetKeysprop type fromanytounknown[]and remove redundant!!castReact.MouseEvent/React.ChangeEvent/Date[]types to event handler callbacks wherejuno-ui-componentsprop types resolve asanyin CI but correctly locallyeslint-disablecomments foruseAuth()fromgreenhouse-auth-providerandencodeV2/decodeV2fromjuno-url-state-provider— these packages export error-typed values in CI due to type resolution differences; each disable has an explanatory commentRemediationModalcomponent introduced by a concurrent main branch refactor (same patterns:useAuth()cast,void handleConfirm(), typed input callbacks)eslint.config.mjs:react-refresh/only-export-components(TanStack Router requires mixed exports in route files) andreact-hooks/set-state-in-effect(intentional derived-state sync pattern)reportUnusedDisableDirectives: "off"to suppress false-positive warnings for CI-only disables that are unused locally (where package types resolve correctly)vite.config.ts,vitest.config.ts,vitest.setup.ts, andtailwind.config.tsfrom ESLint entirely (not included intsconfig.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:
eslint.config.mjs,package.json,vite-react-ts.mjs) — the actual migration; the only part worth careful reviewvoid navigate(...)(~10 files) — fire-and-forgetnavigate()calls markedvoid; no behaviour changeasyncremoval (~8 test files) —loader: async () =>→loader: () =>andact(async→act(where there was noawait; no behaviour change. Two Suspense tests keepawait act(async () => {...})with a scoped lint disable.ImageIssuesList,ImageVersionIssuesList) —{promise && ...}→{promise != null && ...}; no behaviour changeutils.ts×2,ErrorBoundary,getTestRouter,types/index.d.ts, event handler annotations) —anyreplaced with concrete types or explicit casts with commentsIssuesDataRow,RemediatedIssueDataRow,RemediationHistoryPanel,RemediationModal) —queryClient.setQueriesDatacallbacks now use a localRemediationsCachetype instead ofany; verify the shape matches what's actually stored in the cacheRelated Issues
Screenshots (if applicable)
none
Testing Instructions
pnpm ipnpm TASKChecklist
PR Manifesto
Review the PR Manifesto for best practises.