Skip to content

Commit b50303f

Browse files
authored
Merge pull request #2327 from devtron-labs/feat/bulk-trigger-deployment
feat: bulk trigger deployment in DA workflow
2 parents aadeb7f + 2227223 commit b50303f

File tree

37 files changed

+183
-454
lines changed

37 files changed

+183
-454
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"homepage": "/dashboard",
66
"dependencies": {
7-
"@devtron-labs/devtron-fe-common-lib": "1.4.5",
7+
"@devtron-labs/devtron-fe-common-lib": "1.4.8",
88
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
99
"@rjsf/core": "^5.13.3",
1010
"@rjsf/utils": "^5.13.3",

src/Pages/GlobalConfigurations/Authorization/Shared/components/K8sObjectPermissions/K8sListItemCard.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
SelectPicker,
3131
ButtonVariantType,
3232
ButtonStyleType,
33+
ResourceListPayloadType,
3334
} from '@devtron-labs/devtron-fe-common-lib'
3435
import { K8S_EMPTY_GROUP } from '@Components/ResourceBrowser/Constants'
3536
import {
@@ -44,7 +45,7 @@ import {
4445
getResourceGroupList,
4546
namespaceListByClusterId,
4647
} from '../../../../../../components/ResourceBrowser/ResourceBrowser.service'
47-
import { K8SObjectType, ResourceListPayloadType } from '../../../../../../components/ResourceBrowser/Types'
48+
import { K8SObjectType } from '../../../../../../components/ResourceBrowser/Types'
4849
import { formatOptionLabel } from '../../../../../../components/v2/common/ReactSelect.utils'
4950
import { ReactComponent as Clone } from '../../../../../../assets/icons/ic-copy.svg'
5051
import { ReactComponent as Delete } from '../../../../../../assets/icons/ic-delete-interactive.svg'

src/components/ApplicationGroup/Details/EnvironmentOverview/HibernateStatusListDrawer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ import {
2222
InfoColourBar,
2323
Progressing,
2424
usePrompt,
25+
DEFAULT_ROUTE_PROMPT_MESSAGE
2526
} from '@devtron-labs/devtron-fe-common-lib'
2627
import { Prompt } from 'react-router-dom'
2728
import { HibernateStatusRow } from './HibernateStatusRow'
28-
import { DEFAULT_ROUTE_PROMPT_MESSAGE } from '../../../../config'
2929
import { ReactComponent as Close } from '../../../../assets/icons/ic-cross.svg'
3030
import { ReactComponent as Error } from '../../../../assets/icons/ic-warning.svg'
3131
import { ReactComponent as MechanicalOperation } from '../../../../assets/img/ic-mechanical-operation.svg'

src/components/ApplicationGroup/Details/EnvironmentOverview/RestartWorkloadModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
stopPropagation,
2828
usePrompt,
2929
useSearchString,
30+
DEFAULT_ROUTE_PROMPT_MESSAGE,
3031
ApiQueuingWithBatch,
3132
} from '@devtron-labs/devtron-fe-common-lib'
3233
import { Prompt, useHistory, useLocation } from 'react-router-dom'
@@ -51,7 +52,6 @@ import { RestartStatusListDrawer } from './RestartStatusListDrawer'
5152
import { importComponentFromFELibrary } from '../../../common'
5253
import { AllExpandableDropdown } from './AllExpandableDropdown'
5354
import { ReactComponent as Warn } from '../../../../assets/icons/ic-warning.svg'
54-
import { DEFAULT_ROUTE_PROMPT_MESSAGE } from '../../../../config'
5555

5656
const BulkDeployResistanceTippy = importComponentFromFELibrary('BulkDeployResistanceTippy')
5757

src/components/ApplicationGroup/Details/TriggerView/EnvTriggerView.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,13 @@ import {
4949
getStageTitle,
5050
TriggerBlockType,
5151
RuntimePluginVariables,
52+
DEFAULT_ROUTE_PROMPT_MESSAGE,
53+
triggerCDNode,
5254
} from '@devtron-labs/devtron-fe-common-lib'
5355
import Tippy from '@tippyjs/react'
5456
import {
5557
BUILD_STATUS,
5658
DEFAULT_GIT_BRANCH_VALUE,
57-
DEFAULT_ROUTE_PROMPT_MESSAGE,
5859
NO_COMMIT_SELECTED,
5960
URLS,
6061
ViewType,
@@ -73,7 +74,6 @@ import {
7374
getCIMaterialList,
7475
getGitMaterialByCommitHash,
7576
refreshGitMaterial,
76-
triggerCDNode,
7777
triggerCINode,
7878
triggerBranchChange,
7979
} from '../../../app/service'
@@ -1492,12 +1492,15 @@ export default function EnvTriggerView({ filteredAppIds, isVirtualEnv }: AppGrou
14921492
if (ciArtifact) {
14931493
_CDTriggerPromiseFunctionList.push(() =>
14941494
triggerCDNode({
1495-
pipelineId: node.id,
1496-
ciArtifactId: ciArtifact.id,
1497-
appId: currentAppId,
1495+
pipelineId: Number(node.id),
1496+
ciArtifactId: Number(ciArtifact.id),
1497+
appId: Number(currentAppId),
14981498
stageType: bulkTriggerType,
1499-
runtimeParams: runtimeParams[currentAppId] || [],
1500-
isRollbackTrigger: false,
1499+
...(
1500+
getRuntimeParamsPayload
1501+
? { runtimeParamsPayload: getRuntimeParamsPayload(runtimeParams[currentAppId] ?? [])}
1502+
: {}
1503+
),
15011504
}),
15021505
)
15031506
} else {

src/components/ApplicationGroup/Details/TriggerView/TriggerModalTableRow.tsx

Lines changed: 11 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,19 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { useState } from 'react'
18-
import { Progressing, useDownload } from '@devtron-labs/devtron-fe-common-lib'
17+
import { useDownload } from '@devtron-labs/devtron-fe-common-lib'
1918
import { ResponseRowType, TriggerModalRowType } from '../../AppGroup.types'
2019
import { ReactComponent as Error } from '../../../../assets/icons/ic-error-exclamation.svg'
2120
import { ReactComponent as Success } from '../../../../assets/icons/appstatus/healthy.svg'
22-
import { ReactComponent as Download } from '../../../../assets/icons/ic-arrow-line-down.svg'
2321
import { ReactComponent as UnAuthorized } from '../../../../assets/icons/ic-locked.svg'
2422
import { ReactComponent as ICInfoFilled } from '../../../../assets/icons/ic-info-filled.svg'
2523
import { BulkResponseStatus } from '../../Constants'
2624
import { importComponentFromFELibrary } from '../../../common'
2725

28-
const getDownloadManifestUrl = importComponentFromFELibrary('getDownloadManifestUrl', null, 'function')
26+
const DownloadManifestForVirtualEnvironmentButton = importComponentFromFELibrary('DownloadManifestForVirtualEnvironmentButton', null, 'function')
2927

3028
export const TriggerModalRow = ({ rowData, index, isVirtualEnv, envName }: TriggerModalRowType) => {
31-
const { isDownloading, handleDownload } = useDownload()
32-
const [isDownloaded, setIsDownloaded] = useState(false)
33-
const params = {
34-
appId: rowData.appId,
35-
envId: rowData.envId,
36-
appName: `${rowData.appName}-${envName}`,
37-
}
29+
const { handleDownload } = useDownload()
3830

3931
const renderStatusIcon = (rowData: ResponseRowType): JSX.Element => {
4032
if (rowData.status === BulkResponseStatus.SKIP) {
@@ -49,21 +41,9 @@ export const TriggerModalRow = ({ rowData, index, isVirtualEnv, envName }: Trigg
4941
return <Error className="mr-8 icon-dim-18" />
5042
}
5143

52-
const downloadPackage = (e) => {
53-
e.stopPropagation()
54-
if (!getDownloadManifestUrl) {
55-
return
56-
}
57-
const downloadUrl = getDownloadManifestUrl(params)
58-
const downloadError = handleDownload({ downloadUrl, fileName: params.appName, showSuccessfulToast: false })
59-
if (!downloadError) {
60-
setIsDownloaded(true)
61-
}
62-
}
63-
6444
return (
6545
<div
66-
className={`response-row pt-8 pb-8 ${isVirtualEnv ? 'is-virtual' : ''}`}
46+
className={`response-row py-8 ${isVirtualEnv ? 'is-virtual' : ''}`}
6747
key={`response-${rowData.appId}`}
6848
>
6949
<div className="fs-13 fw-4 cn-9">{rowData.appName}</div>
@@ -73,23 +53,13 @@ export const TriggerModalRow = ({ rowData, index, isVirtualEnv, envName }: Trigg
7353
</div>
7454
<div className="fs-13 fw-4 cn-9">{rowData.message}</div>
7555
{isVirtualEnv && rowData.status === BulkResponseStatus.PASS && (
76-
<div
77-
className="flex right cursor"
78-
data-testid={`bulk-cd-manifest-download-button-${index}`}
79-
onClick={downloadPackage}
80-
>
81-
{isDownloading ? (
82-
<span className="flex">
83-
<Progressing />
84-
<span className="fs-13 flex fw-4 ml-6 cn-7">Downloading</span>
85-
</span>
86-
) : (
87-
<span className={`flex ${isDownloaded ? 'cn-5 scn-5' : 'cb-5'} `}>
88-
<Download className="icon-dim-16" />
89-
<span className="ml-6 fw-6 fs-13">Download</span>
90-
</span>
91-
)}
92-
</div>
56+
<DownloadManifestForVirtualEnvironmentButton
57+
appId={rowData.appId}
58+
envId={rowData.envId}
59+
appName={`${rowData.appName}-${envName}`}
60+
handleDownload={handleDownload}
61+
showSuccessfulToast={false}
62+
/>
9363
)}
9464
</div>
9565
)

src/components/ClusterNodes/NodeActions/DeleteNodeModal.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@
1515
*/
1616

1717
import { useState } from 'react'
18-
import { showError, DeleteDialog, InfoColourBar, ToastVariantType, ToastManager } from '@devtron-labs/devtron-fe-common-lib'
18+
import { showError, DeleteDialog, InfoColourBar, ToastVariantType, ToastManager, deleteNodeCapacity } from '@devtron-labs/devtron-fe-common-lib'
1919
import { useParams } from 'react-router-dom'
2020
import { ReactComponent as Help } from '../../../assets/icons/ic-help.svg'
2121
import { NodeActionModalPropType } from '../types'
22-
import { deleteNodeCapacity } from '../clusterNodes.service'
2322
import { DELETE_NODE_MODAL_MESSAGING } from '../constants'
2423

2524
export default function DeleteNodeModal({ name, version, kind, closePopup }: NodeActionModalPropType) {

src/components/ClusterNodes/clusterNodes.service.tsx

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,12 @@
1414
* limitations under the License.
1515
*/
1616

17-
import {
18-
get,
19-
post,
20-
put,
21-
ResponseType,
22-
trash,
23-
APIOptions,
24-
ROUTES as COMMON_ROUTES,
25-
} from '@devtron-labs/devtron-fe-common-lib'
17+
import { get, post, put, ResponseType, APIOptions, ROUTES as COMMON_ROUTES } from '@devtron-labs/devtron-fe-common-lib'
2618
import { Routes } from '../../config'
2719
import {
2820
ClusterCapacityResponse,
2921
ClusterListResponse,
3022
NodeCordonRequest,
31-
NodeActionRequest,
3223
NodeDetailResponse,
3324
NodeDrainRequest,
3425
UpdateNodeRequestBody,
@@ -64,22 +55,19 @@ export const updateClusterShortDescription = (
6455
): Promise<ResponseType> => put(`${Routes.CLUSTER_DESCRIPTION}`, requestPayload)
6556

6657
export const getNodeCapacity = (clusterId: string, nodeName: string): Promise<NodeDetailResponse> =>
67-
get(`${Routes.NODE_CAPACITY}?clusterId=${clusterId}&name=${nodeName}`)
58+
get(`${COMMON_ROUTES.NODE_CAPACITY}?clusterId=${clusterId}&name=${nodeName}`)
6859

6960
export const cordonNodeCapacity = (requestPayload: NodeCordonRequest): Promise<ResponseType> =>
70-
put(`${Routes.NODE_CAPACITY}/cordon`, requestPayload)
61+
put(`${COMMON_ROUTES.NODE_CAPACITY}/cordon`, requestPayload)
7162

7263
export const drainNodeCapacity = (requestPayload: NodeDrainRequest): Promise<ResponseType> =>
73-
put(`${Routes.NODE_CAPACITY}/drain`, requestPayload)
74-
75-
export const deleteNodeCapacity = (requestPayload: NodeActionRequest, signal?: AbortSignal): Promise<ResponseType> =>
76-
trash(Routes.NODE_CAPACITY, requestPayload, signal ? { signal } : {})
64+
put(`${COMMON_ROUTES.NODE_CAPACITY}/drain`, requestPayload)
7765

7866
export const updateNodeManifest = (
7967
clusterId: string,
8068
nodeName: string,
8169
nodeData: UpdateNodeRequestBody,
82-
): Promise<ResponseType> => put(`${Routes.NODE_CAPACITY}?clusterId=${clusterId}&name=${nodeName}`, nodeData)
70+
): Promise<ResponseType> => put(`${COMMON_ROUTES.NODE_CAPACITY}?clusterId=${clusterId}&name=${nodeName}`, nodeData)
8371

8472
export const clusterTerminalStart = (data: TerminalDataType, option: APIOptions): Promise<ResponseType> =>
8573
post(`${Routes.CLUSTER_TERMINAL}/${Routes.START}`, data, option)

src/components/ClusterNodes/types.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
ClusterCapacityType,
2222
ClusterDetail,
2323
NodeTaintType,
24+
NodeActionRequest,
2425
} from '@devtron-labs/devtron-fe-common-lib'
2526
import { UpdateTabUrlParamsType } from '@Components/common/DynamicTabs/Types'
2627
import { LabelTag, OptionType } from '../app/types'
@@ -172,12 +173,6 @@ export interface TaintErrorObj {
172173
}[]
173174
}
174175

175-
export interface NodeActionRequest {
176-
clusterId?: number
177-
name: string
178-
version: string
179-
kind: string
180-
}
181176
export interface NodeActionModalPropType extends NodeActionRequest {
182177
closePopup: (refreshData?: boolean) => void
183178
}

src/components/ResourceBrowser/ResourceBrowser.service.tsx

Lines changed: 1 addition & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,18 @@
1717
import {
1818
ApiResourceType,
1919
get,
20-
post,
2120
ResponseType,
22-
convertJSONPointerToJSONPath,
2321
getK8sResourceList,
2422
getIsRequestAborted,
2523
showError,
2624
getUrlWithSearchParams,
2725
getK8sResourceListPayload,
2826
stringComparatorBySortOrder,
2927
} from '@devtron-labs/devtron-fe-common-lib'
30-
import {
31-
getManifestResource,
32-
updateManifestResourceHelmApps,
33-
} from '@Components/v2/appDetails/k8Resource/nodeDetail/nodeDetail.api'
34-
import { applyOperation, escapePathComponent } from 'fast-json-patch'
35-
import { JSONPath } from 'jsonpath-plus'
36-
import { SelectedResourceType } from '@Components/v2/appDetails/appDetails.type'
3728
import { RefObject } from 'react'
3829
import { Routes } from '../../config'
3930
import { ClusterListResponse } from '../../services/service.types'
40-
import { ResourceListPayloadType, ResourceType, GetResourceDataType, NodeRowDetail, URLParams } from './Types'
31+
import { GetResourceDataType, NodeRowDetail, URLParams } from './Types'
4132
import { SIDEBAR_KEYS } from './Constants'
4233
import { parseNodeList } from './Utils'
4334

@@ -64,82 +55,6 @@ export const getResourceGroupList = (clusterId: string, signal?: AbortSignal): P
6455
signal,
6556
})
6657

67-
export const deleteResource = (
68-
resourceListPayload: ResourceListPayloadType,
69-
signal?: AbortSignal,
70-
): Promise<ResponseType<ResourceType[]>> => post(Routes.DELETE_RESOURCE, resourceListPayload, signal ? { signal } : {})
71-
72-
export const restartWorkload = async (resource: SelectedResourceType, signal: AbortSignal) => {
73-
const {
74-
result: {
75-
manifestResponse: { manifest },
76-
},
77-
} = await getManifestResource(null, '', '', true, resource, signal)
78-
79-
if (!manifest) {
80-
return
81-
}
82-
83-
const metadataPath = '/spec/template/metadata'
84-
const annotationsPath = `${metadataPath}/annotations`
85-
const restartLabel = 'devtron/restart'
86-
87-
const jsonpathProps = {
88-
json: manifest,
89-
wrap: false,
90-
resultType: 'value',
91-
} as const
92-
93-
const dateString = new Date().toISOString()
94-
95-
if (!JSONPath({ path: convertJSONPointerToJSONPath(metadataPath), ...jsonpathProps })) {
96-
applyOperation(
97-
manifest,
98-
{
99-
op: 'add',
100-
path: metadataPath,
101-
value: {
102-
annotations: {
103-
[restartLabel]: dateString,
104-
},
105-
},
106-
},
107-
false,
108-
true,
109-
)
110-
} else if (
111-
!JSONPath({
112-
path: convertJSONPointerToJSONPath(annotationsPath),
113-
...jsonpathProps,
114-
})
115-
) {
116-
applyOperation(
117-
manifest,
118-
{
119-
op: 'add',
120-
path: annotationsPath,
121-
value: { [restartLabel]: dateString },
122-
},
123-
false,
124-
true,
125-
)
126-
} else {
127-
applyOperation(
128-
manifest,
129-
{
130-
op: 'add',
131-
// NOTE: we only need to escape / in restartLabel when making a path out of it
132-
path: `${annotationsPath}/${escapePathComponent(restartLabel)}t`,
133-
value: dateString,
134-
},
135-
false,
136-
true,
137-
)
138-
}
139-
140-
await updateManifestResourceHelmApps(null, '', '', JSON.stringify(manifest), true, resource, signal)
141-
}
142-
14358
export const getNodeList = (
14459
clusterId: string,
14560
abortControllerRef: RefObject<AbortController>,

0 commit comments

Comments
 (0)