Skip to content

Commit 6e0ba21

Browse files
authored
Merge pull request #2962 from devtron-labs/feat/reserved-output-path
feat: add validation for reserved output directory path
2 parents 69044b3 + 69b8bd6 commit 6e0ba21

File tree

6 files changed

+62
-10
lines changed

6 files changed

+62
-10
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.20.6",
7+
"@devtron-labs/devtron-fe-common-lib": "1.20.7",
88
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
99
"@rjsf/core": "^5.13.3",
1010
"@rjsf/utils": "^5.13.3",

src/components/CIPipelineN/OutputDirectoryPath.tsx

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

17-
import React, { useContext } from 'react'
17+
import { useContext } from 'react'
1818
import { CustomInput } from '@devtron-labs/devtron-fe-common-lib'
1919
import { TaskFieldDescription, TaskFieldLabel } from '../ciPipeline/types'
2020
import { ReactComponent as Close } from '../../assets/icons/ic-close.svg'
2121
import { ReactComponent as Add } from '../../assets/icons/ic-add.svg'
2222
import TaskFieldTippyDescription from './TaskFieldTippyDescription'
2323
import { pipelineContext } from '../workflowEditor/workflowEditor'
24+
import { ValidationRules } from '@Components/ciPipeline/validationRules'
2425

2526
const OutputDirectoryPath = () => {
26-
const { selectedTaskIndex, formData, setFormData, activeStageName } = useContext(pipelineContext)
27+
const { selectedTaskIndex, formData, setFormData, activeStageName, formDataErrorObj, setFormDataErrorObj } =
28+
useContext(pipelineContext)
2729

2830
const addOutputDirectoryPath = (): void => {
2931
const _formData = { ...formData }
@@ -33,18 +35,50 @@ const OutputDirectoryPath = () => {
3335
}
3436
_formData[activeStageName].steps[selectedTaskIndex].outputDirectoryPath.unshift('')
3537
setFormData(_formData)
38+
39+
const updatedErrorObj = { ...formDataErrorObj }
40+
if (!updatedErrorObj[activeStageName].steps[selectedTaskIndex].outputDirectoryPath) {
41+
updatedErrorObj[activeStageName].steps[selectedTaskIndex].outputDirectoryPath = []
42+
}
43+
updatedErrorObj[activeStageName].steps[selectedTaskIndex].outputDirectoryPath.unshift({
44+
isValid: true,
45+
message: '',
46+
})
47+
setFormDataErrorObj(updatedErrorObj)
3648
}
3749

3850
const handleStoreArtifact = (ev, index) => {
3951
const _formData = { ...formData }
40-
_formData[activeStageName].steps[selectedTaskIndex].outputDirectoryPath[index] = ev.target.value
52+
const value = ev.target.value
53+
54+
const currentOutputPaths = _formData[activeStageName].steps[selectedTaskIndex].outputDirectoryPath
55+
currentOutputPaths[index] = value
4156
setFormData(_formData)
57+
58+
const updatedErrorObj = { ...formDataErrorObj }
59+
const outputPathErrors = updatedErrorObj[activeStageName].steps[selectedTaskIndex].outputDirectoryPath
60+
61+
// If already saved, create valid error array of same length
62+
if (!outputPathErrors?.length && currentOutputPaths?.length) {
63+
updatedErrorObj[activeStageName].steps[selectedTaskIndex].outputDirectoryPath = new Array(
64+
currentOutputPaths.length,
65+
{ isValid: true, message: '' },
66+
)
67+
}
68+
69+
updatedErrorObj[activeStageName].steps[selectedTaskIndex].outputDirectoryPath[index] =
70+
new ValidationRules().outputDirectoryPath(value)
71+
setFormDataErrorObj(updatedErrorObj)
4272
}
4373

4474
const deleteOutputDirectory = (index) => {
4575
const _formData = { ...formData }
4676
_formData[activeStageName].steps[selectedTaskIndex].outputDirectoryPath.splice(index, 1)
4777
setFormData(_formData)
78+
79+
const updatedErrorObj = { ...formDataErrorObj }
80+
updatedErrorObj[activeStageName].steps[selectedTaskIndex].outputDirectoryPath.splice(index, 1)
81+
setFormDataErrorObj(updatedErrorObj)
4882
}
4983

5084
return (
@@ -72,6 +106,10 @@ const OutputDirectoryPath = () => {
72106
value={elm}
73107
onChange={(e) => handleStoreArtifact(e, index)}
74108
name="directory-path"
109+
error={
110+
formDataErrorObj[activeStageName].steps[selectedTaskIndex].outputDirectoryPath?.[index]
111+
?.message
112+
}
75113
/>
76114
<Close
77115
className="icon-dim-24 pointer mt-6 ml-6"

src/components/cdPipeline/cdpipeline.util.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ export const validateTask = (
7777
taskErrorObj.name = validationRules.requiredField(taskData.name)
7878
taskErrorObj.isValid = taskErrorObj.name.isValid
7979

80+
taskErrorObj.isValid =
81+
taskErrorObj.isValid && (taskErrorObj.outputDirectoryPath?.every(({ isValid }) => isValid) ?? true)
82+
8083
if (taskData.stepType) {
8184
const currentStepTypeVariable =
8285
taskData.stepType === PluginType.INLINE ? 'inlineStepDetail' : 'pluginRefStepDetail'
@@ -521,4 +524,4 @@ export const getIsExternalAppLinkable = (migrateToDevtronFormState: MigrateToDev
521524
const { deploymentAppType } = migrateToDevtronFormState
522525
const { validationResponse } = migrateToDevtronFormState[SELECTED_FORM_STATE_KEY[deploymentAppType]]
523526
return validationResponse.isLinkable
524-
}
527+
}

src/components/ciPipeline/validationRules.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import {
2323
CustomErrorMessage,
2424
MAX_LENGTH_30,
2525
REPO_NAME_VALIDATION,
26+
RESERVED_DIRECTORY_PATH_MSG,
27+
RESERVED_OUTPUT_DIRECTORY_PATH,
2628
} from '../../config/constantMessaging'
2729
import { validateInputOutputVariableCell } from '@Components/CIPipelineN/VariableDataTable/validations'
2830
import { validateConditionDataCell } from '@Components/CIPipelineN/ConditionDataTable/utils'
@@ -176,4 +178,11 @@ export class ValidationRules {
176178
}
177179
return { isValid: true, message: '' }
178180
}
181+
182+
outputDirectoryPath = (value: string): { message: string | null; isValid: boolean } => {
183+
if (value.startsWith(RESERVED_OUTPUT_DIRECTORY_PATH)) {
184+
return { isValid: false, message: RESERVED_DIRECTORY_PATH_MSG }
185+
}
186+
return { isValid: true, message: null }
187+
}
179188
}

src/config/constantMessaging.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export const enum DeleteComponentsName {
7878

7979
// DELETE COMPONENT ENDS
8080

81+
export const RESERVED_OUTPUT_DIRECTORY_PATH = '/devtroncd'
8182
export const LEARN_MORE = 'Learn more'
8283
export const REQUIRED_FIELD_MSG = 'This is a required field'
8384
export const MAX_LENGTH_30 = 'Max 30 characters allowed'
@@ -94,6 +95,7 @@ export const ERROR_MESSAGE_FOR_VALIDATION =
9495
export const CHARACTER_ERROR_MIN = 'At least 2 characters required'
9596
export const CHARACTER_ERROR_MAX = 'Max 50 characters allowed'
9697
export const PROJECT_EXIST_MSG = 'This Project already exists.'
98+
export const RESERVED_DIRECTORY_PATH_MSG = `Path cannot start with '${RESERVED_OUTPUT_DIRECTORY_PATH}' as it is reserved.`
9799

98100
export const CustomErrorMessage = {
99101
CUSTOM_TAG_ERROR_MSG:

yarn.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,9 +1722,9 @@ __metadata:
17221722
languageName: node
17231723
linkType: hard
17241724

1725-
"@devtron-labs/devtron-fe-common-lib@npm:1.20.6":
1726-
version: 1.20.6
1727-
resolution: "@devtron-labs/devtron-fe-common-lib@npm:1.20.6"
1725+
"@devtron-labs/devtron-fe-common-lib@npm:1.20.7":
1726+
version: 1.20.7
1727+
resolution: "@devtron-labs/devtron-fe-common-lib@npm:1.20.7"
17281728
dependencies:
17291729
"@codemirror/autocomplete": "npm:6.18.6"
17301730
"@codemirror/lang-json": "npm:6.0.1"
@@ -1774,7 +1774,7 @@ __metadata:
17741774
react-select: 5.8.0
17751775
rxjs: ^7.8.1
17761776
yaml: ^2.4.1
1777-
checksum: 10c0/d8639234d0c89ecf69cfefa81cc089325ef518eae0ca19709b8276c3a7878f46b1f9166bdfae7da11d42f85ad14654eeb762fa9e559fb0102c5293c8c92057da
1777+
checksum: 10c0/64ed4382ad16cf95657724ad6ae0e568351d78f3fdff4906cc53bd3fddd19a5c3518f83d4474c7f32bff6f8c2e19b9b23fe2a5b20a8d22b598ebd989818261c8
17781778
languageName: node
17791779
linkType: hard
17801780

@@ -5721,7 +5721,7 @@ __metadata:
57215721
version: 0.0.0-use.local
57225722
resolution: "dashboard@workspace:."
57235723
dependencies:
5724-
"@devtron-labs/devtron-fe-common-lib": "npm:1.20.6"
5724+
"@devtron-labs/devtron-fe-common-lib": "npm:1.20.7"
57255725
"@esbuild-plugins/node-globals-polyfill": "npm:0.2.3"
57265726
"@playwright/test": "npm:^1.32.1"
57275727
"@rjsf/core": "npm:^5.13.3"

0 commit comments

Comments
 (0)