-
Notifications
You must be signed in to change notification settings - Fork 1
feat(heureka): adds false positive actions and image version details page #1421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
12bfc52
5d21f3d
864acdb
35ab5a0
4bc758b
d48b237
5768fc1
0242166
43b8fb6
17260fd
6325218
8e69870
eeddd1f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@cloudoperators/juno-app-heureka": major | ||
| --- | ||
|
|
||
| Adds false positive remediation action to image details page with create and delete functionality. Introduces image version details page to display deployment locations for each image version. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,3 +34,6 @@ npm-debug.log* | |
| .env.development.local | ||
| .env.test.local | ||
| .env.production.local | ||
|
|
||
| # TanStack Router cache directory | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. How is this directory being created? |
||
| .tanstack/ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,6 +28,7 @@ | |
| "clean:cache": "rm -rf .turbo" | ||
| }, | ||
| "dependencies": { | ||
| "@cloudoperators/juno-messages-provider": "workspace:*", | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you want really to introduce the messages provider dependency? We can talk about this.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not? it's because of msgs for remediation actions |
||
| "@cloudoperators/juno-ui-components": "workspace:*", | ||
| "@cloudoperators/juno-url-state-provider": "workspace:*", | ||
| "@tanstack/react-query": "5.90.16", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Juno contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| import { ApolloClient } from "@apollo/client" | ||
| import { | ||
| CreateRemediationDocument, | ||
| CreateRemediationMutation, | ||
| CreateRemediationMutationVariables, | ||
| RemediationInput, | ||
| } from "../generated/graphql" | ||
|
|
||
| type CreateRemediationParams = { | ||
| apiClient: ApolloClient | ||
| input: RemediationInput | ||
| } | ||
|
|
||
| export const createRemediation = async ({ | ||
| apiClient, | ||
| input, | ||
| }: CreateRemediationParams): Promise<CreateRemediationMutation["createRemediation"]> => { | ||
| const result = await apiClient.mutate<CreateRemediationMutation, CreateRemediationMutationVariables>({ | ||
| mutation: CreateRemediationDocument, | ||
| variables: { input }, | ||
| }) | ||
|
|
||
| if (!result.data?.createRemediation) { | ||
| throw new Error("Failed to create remediation") | ||
| } | ||
|
|
||
| return result.data.createRemediation | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Juno contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| import { ApolloClient } from "@apollo/client" | ||
| import { | ||
| DeleteRemediationDocument, | ||
| DeleteRemediationMutation, | ||
| DeleteRemediationMutationVariables, | ||
| } from "../generated/graphql" | ||
|
|
||
| type DeleteRemediationParams = { | ||
| apiClient: ApolloClient | ||
| remediationId: string | ||
| } | ||
|
|
||
| export const deleteRemediation = async ({ apiClient, remediationId }: DeleteRemediationParams): Promise<string> => { | ||
| const result = await apiClient.mutate<DeleteRemediationMutation, DeleteRemediationMutationVariables>({ | ||
| mutation: DeleteRemediationDocument, | ||
| variables: { id: remediationId }, | ||
| }) | ||
|
|
||
| if (!result.data?.deleteRemediation) { | ||
| throw new Error("Failed to delete remediation") | ||
| } | ||
|
|
||
| return result.data.deleteRemediation | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Juno contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| import { ObservableQuery } from "@apollo/client" | ||
| import { GetImageVersionsDocument, GetImageVersionsQuery, ImageVersionFilter } from "../generated/graphql" | ||
| import { RouteContext } from "../routes/-types" | ||
|
|
||
| type FetchImageVersionsParams = Pick<RouteContext, "queryClient" | "apiClient"> & { | ||
| filter: ImageVersionFilter | ||
| after?: string | null | ||
| first?: number | ||
| firstVulnerabilities?: number | ||
| afterVulnerabilities?: string | null | ||
| firstOccurences?: number | ||
| afterOccurences?: string | null | ||
| } | ||
|
|
||
| export const fetchImageVersions = ({ | ||
| queryClient, | ||
| apiClient, | ||
| filter, | ||
| after, | ||
| first, | ||
| firstVulnerabilities, | ||
| afterVulnerabilities, | ||
| firstOccurences, | ||
| afterOccurences, | ||
| }: FetchImageVersionsParams): Promise<ObservableQuery.Result<GetImageVersionsQuery>> => { | ||
| const queryKey = [ | ||
| "imageVersions", | ||
| filter, | ||
| after, | ||
| first, | ||
| firstVulnerabilities, | ||
| afterVulnerabilities, | ||
| firstOccurences, | ||
| afterOccurences, | ||
| ] | ||
|
|
||
| // Invalidate cache first to ensure queryFn is always called (forces network request) | ||
| // Then use ensureQueryData to maintain promise stability (like other fetch functions) | ||
| queryClient.invalidateQueries({ queryKey }) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are you always fetching from network? Which benefit gives you then using react-query instead of just fetch? |
||
|
|
||
| return queryClient.ensureQueryData({ | ||
| queryKey, | ||
| queryFn: () => | ||
| apiClient.query<GetImageVersionsQuery>({ | ||
| query: GetImageVersionsDocument, | ||
| variables: { | ||
| filter, | ||
| first, | ||
| after, | ||
| firstVulnerabilities, | ||
| afterVulnerabilities, | ||
| firstOccurences, | ||
| afterOccurences, | ||
| }, | ||
| fetchPolicy: "network-only", // Force network request to always fetch fresh data | ||
| }), | ||
| }) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Juno contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| import { ObservableQuery } from "@apollo/client" | ||
| import { GetRemediationsDocument, GetRemediationsQuery, RemediationFilter } from "../generated/graphql" | ||
| import { RouteContext } from "../routes/-types" | ||
|
|
||
| type FetchRemediationsParams = Pick<RouteContext, "queryClient" | "apiClient"> & { | ||
| filter?: RemediationFilter | ||
| } | ||
|
|
||
| export const fetchRemediations = ({ | ||
| queryClient, | ||
| apiClient, | ||
| filter, | ||
| }: FetchRemediationsParams): Promise<ObservableQuery.Result<GetRemediationsQuery>> => { | ||
| const queryKey = ["remediations", filter] | ||
|
|
||
| return queryClient.ensureQueryData({ | ||
| queryKey, | ||
| queryFn: () => | ||
| apiClient.query<GetRemediationsQuery>({ | ||
| query: GetRemediationsDocument, | ||
| variables: { | ||
| filter, | ||
| }, | ||
| }), | ||
| }) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really needed? This is the first app ignoring this folder...