Skip to content

Commit 9cabddb

Browse files
committed
feat: merge calls for security tabs
1 parent f0df456 commit 9cabddb

File tree

8 files changed

+122
-69
lines changed

8 files changed

+122
-69
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { getSecurityScan, useAsync } from '@devtron-labs/devtron-fe-common-lib'
2+
import { getLastExecutionMinByAppAndEnv } from '@Services/service'
3+
import { UseGetAppSecurityDetailsProps, UseGetAppSecurityDetailsReturnType } from './appDetails.type'
4+
5+
export const useGetAppSecurityDetails = ({
6+
appId,
7+
envId,
8+
isSecurityScanV2Enabled,
9+
}: UseGetAppSecurityDetailsProps): UseGetAppSecurityDetailsReturnType => {
10+
const [scanResultLoading, scanResultResponse, scanResultError, reloadScanResult] = useAsync(
11+
() => getSecurityScan({ appId, envId }),
12+
[appId, envId],
13+
isSecurityScanV2Enabled,
14+
)
15+
16+
const [executionDetailsLoading, executionDetailsResponse, executionDetailsError, reloadExecutionDetails] = useAsync(
17+
() => getLastExecutionMinByAppAndEnv(appId, envId),
18+
[appId, envId],
19+
!isSecurityScanV2Enabled,
20+
)
21+
22+
return {
23+
scanDetailsLoading: scanResultLoading || executionDetailsLoading,
24+
scanResultResponse,
25+
executionDetailsResponse,
26+
scanDetailsError: scanResultError || executionDetailsError,
27+
reloadScanDetails: isSecurityScanV2Enabled ? reloadScanResult : reloadExecutionDetails,
28+
}
29+
}

src/components/app/details/appDetails/SecurityVulnerabilityCard.tsx

Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616

1717
import React, { useState } from 'react'
1818
import Tippy from '@tippyjs/react'
19-
import { getSecurityScan, SecurityModal, SeverityCount, useAsync } from '@devtron-labs/devtron-fe-common-lib'
19+
import { getSeverityCountFromSummary, getTotalSeverityCount, SecurityModal, SeverityCount } from '@devtron-labs/devtron-fe-common-lib'
2020
import { ReactComponent as Question } from '../../../../assets/icons/ic-help-outline.svg'
2121
import { ReactComponent as Bug } from '../../../../assets/icons/ic-nav-bug.svg'
2222
import { ReactComponent as Secure } from '../../../../assets/icons/ic-secure.svg'
2323
import { SecurityVulnerabilityCardType } from './appDetails.type'
2424
import LoadingCard from './LoadingCard'
2525
import { importComponentFromFELibrary } from '../../../common'
26-
import { getLastExecutionMinByAppAndEnv } from '../../../../services/service'
26+
import { useGetAppSecurityDetails } from './AppSecurity'
2727

2828
const isFELibAvailable = importComponentFromFELibrary('isFELibAvailable', null, 'function')
2929

@@ -39,56 +39,35 @@ export const SecurityVulnerabilityCard = ({
3939

4040
const handleModalClose = () => setShowScanDetailsModal(false)
4141

42-
const [scanResultLoading, scanResultResponse, scanResultError, reloadScanResult] = useAsync(
43-
() => getSecurityScan({ appId, envId }),
44-
[appId, envId],
45-
isSecurityScanV2Enabled,
46-
)
47-
48-
const [executionDetailsLoading, executionDetailsResponse, executionDetailsError, reloadExecutionDetails] = useAsync(
49-
() => getLastExecutionMinByAppAndEnv(appId, envId),
50-
[appId, envId],
51-
!isSecurityScanV2Enabled,
52-
)
42+
const { scanDetailsLoading, scanResultResponse, executionDetailsResponse, scanDetailsError, reloadScanDetails } =
43+
useGetAppSecurityDetails({ appId, envId, isSecurityScanV2Enabled })
5344

54-
const imageScanErrored = scanResultError || executionDetailsError
5545
const imageScanFailed = scanResultResponse?.result.codeScan.status === 'Failed'
5646
const imageScanProgressing = scanResultResponse?.result.codeScan.status === 'Progressing'
5747

5848
const handleOnCardClick = () => {
59-
if (!cardLoading && !imageScanErrored && !showScanDetailsModal) {
49+
if (!cardLoading && !scanDetailsError && !showScanDetailsModal) {
6050
// hack: added timeout to prevent click outside
6151
setTimeout(() => setShowScanDetailsModal(true), 100)
6252
}
6353
}
6454

65-
const imageScanSeverities = scanResultResponse?.result.imageScan.vulnerability?.summary.severities // For scan-result Api
55+
const scanResultSeverities = scanResultResponse?.result.imageScan.vulnerability?.summary.severities // For scan-result Api
6656
const severityCount: SeverityCount = isSecurityScanV2Enabled
67-
? {
68-
critical: imageScanSeverities?.CRITICAL || 0,
69-
high: imageScanSeverities?.HIGH || 0,
70-
medium: imageScanSeverities?.MEDIUM || 0,
71-
low: imageScanSeverities?.LOW || 0,
72-
unknown: imageScanSeverities?.UNKNOWN || 0,
73-
}
57+
? getSeverityCountFromSummary(scanResultSeverities)
7458
: executionDetailsResponse?.result.severityCount ?? { critical: 0, high: 0, medium: 0, low: 0, unknown: 0 }
7559

76-
const totalCount =
77-
(severityCount?.critical || 0) +
78-
(severityCount?.high || 0) +
79-
(severityCount?.medium || 0) +
80-
(severityCount?.low || 0) +
81-
(severityCount?.unknown || 0)
60+
const totalCount = getTotalSeverityCount(severityCount)
8261

8362
const getIcon = () => {
84-
if (imageScanErrored || imageScanFailed || imageScanProgressing || totalCount) {
63+
if (scanDetailsError || imageScanFailed || imageScanProgressing || totalCount) {
8564
return <Bug className="scy-7" />
8665
}
8766
return <Secure />
8867
}
8968

9069
const getTitle = () => {
91-
if (imageScanErrored) {
70+
if (scanDetailsError) {
9271
return '--'
9372
}
9473
if (imageScanFailed) {
@@ -108,7 +87,7 @@ export const SecurityVulnerabilityCard = ({
10887
}
10988

11089
const getSubtitle = () => {
111-
if (imageScanErrored) {
90+
if (scanDetailsError) {
11291
return 'Failed to fetch'
11392
}
11493
if (imageScanFailed) {
@@ -136,11 +115,11 @@ export const SecurityVulnerabilityCard = ({
136115
}
137116

138117
const getActionButton = () => {
139-
if (imageScanErrored) {
118+
if (scanDetailsError) {
140119
return (
141120
<button
142121
className="app-details-info-card__bottom-container__details fs-12 fw-6 dc__unset-button-styles"
143-
onClick={isSecurityScanV2Enabled ? reloadScanResult : reloadExecutionDetails}
122+
onClick={reloadScanDetails}
144123
data-testid="security-card-handle-refetch-button"
145124
>
146125
Refetch
@@ -157,7 +136,7 @@ export const SecurityVulnerabilityCard = ({
157136
)
158137
}
159138

160-
if (cardLoading || scanResultLoading || executionDetailsLoading) {
139+
if (cardLoading || scanDetailsLoading) {
161140
return <LoadingCard />
162141
}
163142

@@ -172,7 +151,7 @@ export const SecurityVulnerabilityCard = ({
172151
<button type="button" className="dc__unset-button-styles" onClick={handleOnCardClick}>
173152
<div
174153
data-testid="security-vulnerability-card"
175-
className={`app-details-info-card flex left bcn-0 br-8 mr-12 lh-20 w-200 ${cardLoading || imageScanErrored ? '' : 'pointer'}`}
154+
className={`app-details-info-card flex left bcn-0 br-8 mr-12 lh-20 w-200 ${cardLoading || scanDetailsError ? '' : 'pointer'}`}
176155
>
177156
<div className="app-details-info-card__top-container flex">
178157
<div className="app-details-info-card__top-container__content">

src/components/app/details/appDetails/appDetails.type.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { ACTION_STATE, ResponseType } from '@devtron-labs/devtron-fe-common-lib'
17+
import { ACTION_STATE, getSecurityScan, ResponseType } from '@devtron-labs/devtron-fe-common-lib'
18+
import { getLastExecutionMinByAppAndEnv } from '@Services/service'
1819
import { AggregatedNodes, OptionType } from '../../types'
1920
import { SyncErrorType, AppDetails } from '../../../v2/appDetails/appDetails.type'
2021

@@ -257,3 +258,16 @@ export interface LastUpdatedCardType {
257258
triggeredBy: string
258259
cardLoading: boolean
259260
}
261+
262+
export interface UseGetAppSecurityDetailsProps {
263+
appId: string
264+
envId: string
265+
isSecurityScanV2Enabled: boolean
266+
}
267+
export interface UseGetAppSecurityDetailsReturnType {
268+
scanDetailsLoading: boolean
269+
scanResultResponse: Awaited<ReturnType<typeof getSecurityScan>>
270+
executionDetailsResponse: Awaited<ReturnType<typeof getLastExecutionMinByAppAndEnv>>
271+
scanDetailsError: any
272+
reloadScanDetails: () => void
273+
}

src/components/app/details/cIDetails/CIDetails.tsx

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@ import {
4141
ModuleNameMap,
4242
EMPTY_STATE_STATUS,
4343
SecuritySummaryCard,
44-
getSecurityScan,
4544
SeverityCount,
4645
TabGroup,
4746
TRIGGER_STATUS_PROGRESSING,
4847
SCAN_TOOL_ID_TRIVY,
48+
ErrorScreenManager,
49+
getTotalSeverityCount,
50+
getSeverityCountFromSummary,
4951
} from '@devtron-labs/devtron-fe-common-lib'
5052
import { Switch, Route, Redirect, useRouteMatch, useParams, useHistory, generatePath } from 'react-router-dom'
5153
import {
@@ -57,7 +59,6 @@ import {
5759
} from '../../service'
5860
import { URLS, Routes } from '../../../../config'
5961
import { BuildDetails, CIPipeline, HistoryLogsType, SecurityTabType } from './types'
60-
import { getLastExecutionByAppArtifactId } from '../../../../services/service'
6162
import { ScanDisabledView, ImageNotScannedView, CIRunningView } from './cIDetails.util'
6263
import './ciDetails.scss'
6364
import { getModuleInfo } from '../../../v2/devtronStackManager/DevtronStackManager.service'
@@ -67,6 +68,7 @@ import { ReactComponent as NoVulnerability } from '../../../../assets/img/ic-vul
6768
import { CIPipelineBuildType } from '../../../ciPipeline/types'
6869
import { renderCIListHeader, renderDeploymentHistoryTriggerMetaText } from '../cdDetails/utils'
6970
import { importComponentFromFELibrary } from '@Components/common'
71+
import { useGetCISecurityDetails } from './CISecurity.utils'
7072

7173
const isFELibAvailable = importComponentFromFELibrary('isFELibAvailable', null, 'function')
7274
const terminalStatus = new Set(['succeeded', 'failed', 'error', 'cancelled', 'nottriggered', 'notbuilt'])
@@ -678,17 +680,12 @@ const SecurityTab = ({ ciPipelineId, artifactId, status, appIdFromParent, isJobC
678680

679681
const computedAppId = appId ?? appIdFromParent
680682

681-
const [scanResultLoading, scanResultResponse, scanResultError, reloadScanResult] = useAsync(
682-
() => getSecurityScan({ artifactId, ...((isJobCI || isJobView) && { appId: computedAppId }) }),
683-
[artifactId, computedAppId],
683+
const { scanDetailsLoading, scanResultResponse, executionDetailsResponse, scanDetailsError, reloadScanDetails } = useGetCISecurityDetails({
684+
appId: computedAppId,
685+
artifactId,
686+
isJobCard: isJobCI || isJobView,
684687
isSecurityScanV2Enabled,
685-
)
686-
687-
const [executionDetailsLoading, executionDetailsResponse, executionDetailsError, reloadExecutionDetails] = useAsync(
688-
() => getLastExecutionByAppArtifactId(artifactId, isJobCI || isJobView ? computedAppId : null),
689-
[artifactId, computedAppId],
690-
!isSecurityScanV2Enabled,
691-
)
688+
})
692689

693690
const redirectToCreate = () => {
694691
if (!ciPipelineId) {
@@ -714,11 +711,11 @@ const SecurityTab = ({ ciPipelineId, artifactId, status, appIdFromParent, isJobC
714711
)
715712
}
716713

717-
if (scanResultLoading || executionDetailsLoading) {
714+
if (scanDetailsLoading) {
718715
return <Progressing pageLoader />
719716
}
720-
if (scanResultError || executionDetailsError) {
721-
return <Reload reload={isSecurityScanV2Enabled ? reloadScanResult : reloadExecutionDetails} />
717+
if (scanDetailsError) {
718+
return <ErrorScreenManager code={scanDetailsError.code} reload={reloadScanDetails} />
722719
}
723720
if (
724721
(executionDetailsResponse && !executionDetailsResponse.result.scanned) ||
@@ -730,23 +727,12 @@ const SecurityTab = ({ ciPipelineId, artifactId, status, appIdFromParent, isJobC
730727
return <ImageNotScannedView />
731728
}
732729

733-
const imageScanSeverities = scanResultResponse?.result.imageScan.vulnerability.summary.severities // For scan-result Api
730+
const scanResultSeverities = scanResultResponse?.result.imageScan.vulnerability?.summary.severities // For scan-result Api
734731
const severityCount: SeverityCount = isSecurityScanV2Enabled
735-
? {
736-
critical: imageScanSeverities.CRITICAL || 0,
737-
high: imageScanSeverities.HIGH || 0,
738-
medium: imageScanSeverities.MEDIUM || 0,
739-
low: imageScanSeverities.LOW || 0,
740-
unknown: imageScanSeverities.UNKNOWN || 0,
741-
}
732+
? getSeverityCountFromSummary(scanResultSeverities)
742733
: executionDetailsResponse?.result.severityCount ?? { critical: 0, high: 0, medium: 0, low: 0, unknown: 0 }
743734

744-
const totalSeverities =
745-
(severityCount.critical || 0) +
746-
(severityCount.high || 0) +
747-
(severityCount.medium || 0) +
748-
(severityCount.low || 0) +
749-
(severityCount.unknown || 0)
735+
const totalSeverities = getTotalSeverityCount(severityCount)
750736

751737
if (artifactId && !totalSeverities) {
752738
return (
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { getSecurityScan, useAsync } from '@devtron-labs/devtron-fe-common-lib'
2+
import { getLastExecutionByAppArtifactId } from '@Services/service'
3+
import { UseGetCISecurityDetailsProps, UseGetCISecurityDetailsReturnType } from './types'
4+
5+
export const useGetCISecurityDetails = ({
6+
appId,
7+
artifactId,
8+
isJobCard,
9+
isSecurityScanV2Enabled,
10+
}: UseGetCISecurityDetailsProps): UseGetCISecurityDetailsReturnType => {
11+
const [scanResultLoading, scanResultResponse, scanResultError, reloadScanResult] = useAsync(
12+
() => getSecurityScan({ artifactId, ...(isJobCard && { appId }) }),
13+
[artifactId, appId],
14+
isSecurityScanV2Enabled,
15+
)
16+
17+
const [executionDetailsLoading, executionDetailsResponse, executionDetailsError, reloadExecutionDetails] = useAsync(
18+
() => getLastExecutionByAppArtifactId(artifactId, isJobCard ? appId : null),
19+
[artifactId, appId],
20+
!isSecurityScanV2Enabled,
21+
)
22+
23+
return {
24+
scanDetailsLoading: scanResultLoading || executionDetailsLoading,
25+
scanResultResponse,
26+
executionDetailsResponse,
27+
scanDetailsError: scanResultError || executionDetailsError,
28+
reloadScanDetails: isSecurityScanV2Enabled ? reloadScanResult : reloadExecutionDetails,
29+
}
30+
}

src/components/app/details/cIDetails/cIDetails.util.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
* limitations under the License.
1515
*/
1616

17-
import React from 'react'
1817
import { GenericEmptyState } from '@devtron-labs/devtron-fe-common-lib'
1918
import notScanned from '../../../../assets/img/not-scanned.png'
2019
import scannedDisabled from '../../../../assets/img/ic-empty-scanner-disabled.png'

src/components/app/details/cIDetails/types.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
import { FetchIdDataStatus, History, useScrollable } from '@devtron-labs/devtron-fe-common-lib'
16+
import { FetchIdDataStatus, getSecurityScan, History, useScrollable } from '@devtron-labs/devtron-fe-common-lib'
17+
import { getLastExecutionByAppArtifactId } from '@Services/service'
1718

1819
export interface CIPipeline {
1920
name: string
@@ -64,3 +65,18 @@ export interface SecurityTabType {
6465
isJobCI: boolean
6566
isJobView: boolean
6667
}
68+
69+
export interface UseGetCISecurityDetailsProps {
70+
appId: string
71+
artifactId: number
72+
isJobCard: boolean
73+
isSecurityScanV2Enabled: boolean
74+
}
75+
76+
export interface UseGetCISecurityDetailsReturnType {
77+
scanDetailsLoading: boolean
78+
scanResultResponse: Awaited<ReturnType<typeof getSecurityScan>>
79+
executionDetailsResponse: Awaited<ReturnType<typeof getLastExecutionByAppArtifactId>>
80+
scanDetailsError: any
81+
reloadScanDetails: () => void
82+
}

src/components/v2/chartDeploymentHistory/ChartDeploymentHistory.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ const ChartDeploymentHistory = ({
111111
DEPLOYMENT_HISTORY_TAB.SOURCE,
112112
DEPLOYMENT_HISTORY_TAB.VALUES_YAML,
113113
DEPLOYMENT_HISTORY_TAB.HELM_GENERATED_MANIFEST,
114-
DEPLOYMENT_HISTORY_TAB.SECURITY,
114+
(ChartSecurityTab && isScanV2Enabled && DEPLOYMENT_HISTORY_TAB.SECURITY),
115115
]
116116
if (installedAppInfo?.deploymentType === DeploymentAppTypes.GITOPS) {
117117
tabs.unshift(DEPLOYMENT_HISTORY_TAB.STEPS)

0 commit comments

Comments
 (0)