Introduce V1 schema

This commit is contained in:
Vardan Bansal 2023-09-13 14:49:41 -07:00
parent 7f2b179711
commit 2c71ca207b
4 changed files with 697 additions and 75 deletions

View File

@ -207,7 +207,7 @@ export const PluginsPanel = ({ version = YamlVersion.V0, onPluginAddUpdate }: Pl
case PluginCategory.Harness: case PluginCategory.Harness:
constructedPayload = constructedPayload =
version === YamlVersion.V1 version === YamlVersion.V1
? { type: 'script', spec: constructedPayload } ? { type: 'script', spec: { run: get(constructedPayload, 'script', '') } }
: { name: 'run step', commands: [get(constructedPayload, 'script', '')] } : { name: 'run step', commands: [get(constructedPayload, 'script', '')] }
} }
onPluginAddUpdate?.(isUpdate, constructedPayload) onPluginAddUpdate?.(isUpdate, constructedPayload)

View File

@ -31,27 +31,33 @@ import { getErrorMessage } from 'utils/Utils'
import { decodeGitContent } from 'utils/GitUtils' import { decodeGitContent } from 'utils/GitUtils'
import pipelineSchemaV1 from './schema/pipeline-schema-v1.json' import pipelineSchemaV1 from './schema/pipeline-schema-v1.json'
import pipelineSchemaV0 from './schema/pipeline-schema-v0.json' import pipelineSchemaV0 from './schema/pipeline-schema-v0.json'
import { YamlVersion } from './Constants' import { DRONE_CONFIG_YAML_FILE_SUFFIXES, YamlVersion } from './Constants'
import css from './AddUpdatePipeline.module.scss' import css from './AddUpdatePipeline.module.scss'
const StarterPipelineV1: Record<string, any> = { const StarterPipelineV1: Record<string, any> = {
version: 1, version: 1,
stages: [ kind: 'pipeline',
{ spec: {
type: 'ci', stages: [
spec: { {
steps: [ name: 'build',
{ type: 'ci',
type: 'script', spec: {
spec: { steps: [
run: 'echo hello world' {
name: 'build',
type: 'script',
spec: {
image: 'golang',
run: 'echo "hello world"'
}
} }
} ]
] }
} }
} ]
] }
} }
const StarterPipelineV0: Record<string, any> = { const StarterPipelineV0: Record<string, any> = {
@ -79,15 +85,13 @@ interface PipelineSaveAndRunOption {
} }
const AddUpdatePipeline = (): JSX.Element => { const AddUpdatePipeline = (): JSX.Element => {
const version = YamlVersion.V0
const { routes } = useAppContext() const { routes } = useAppContext()
const { getString } = useStrings() const { getString } = useStrings()
const { pipeline } = useParams<CODEProps>() const { pipeline } = useParams<CODEProps>()
const { repoMetadata } = useGetRepositoryMetadata() const { repoMetadata } = useGetRepositoryMetadata()
const { showError, showSuccess, clear: clearToaster } = useToaster() const { showError, showSuccess, clear: clearToaster } = useToaster()
const [pipelineAsObj, setPipelineAsObj] = useState<Record<string, any>>( const [yamlVersion, setYAMLVersion] = useState<YamlVersion>()
version === YamlVersion.V0 ? StarterPipelineV0 : StarterPipelineV1 const [pipelineAsObj, setPipelineAsObj] = useState<Record<string, any>>({})
)
const [pipelineAsYAML, setPipelineAsYaml] = useState<string>('') const [pipelineAsYAML, setPipelineAsYaml] = useState<string>('')
const { openModal: openRunPipelineModal } = useRunPipelineModal() const { openModal: openRunPipelineModal } = useRunPipelineModal()
const repoPath = useMemo(() => repoMetadata?.path || '', [repoMetadata]) const repoPath = useMemo(() => repoMetadata?.path || '', [repoMetadata])
@ -139,6 +143,15 @@ const AddUpdatePipeline = (): JSX.Element => {
[pipelineYAMLFileContent?.content] [pipelineYAMLFileContent?.content]
) )
// set YAML version for Pipeline setup
useEffect(() => {
setYAMLVersion(
DRONE_CONFIG_YAML_FILE_SUFFIXES.map((suffix: string) => pipelineData?.config_path?.endsWith(suffix))
? YamlVersion.V0
: YamlVersion.V1
)
}, [pipelineData])
// check if file already exists and has some content // check if file already exists and has some content
useEffect(() => { useEffect(() => {
setIsExistingPipeline(!isEmpty(originalPipelineYAMLFileContent) && !isUndefined(originalPipelineYAMLFileContent)) setIsExistingPipeline(!isEmpty(originalPipelineYAMLFileContent) && !isUndefined(originalPipelineYAMLFileContent))
@ -151,12 +164,12 @@ const AddUpdatePipeline = (): JSX.Element => {
} else { } else {
// load with starter pipeline // load with starter pipeline
try { try {
setPipelineAsYaml(stringify(pipelineAsObj)) setPipelineAsYaml(stringify(yamlVersion === YamlVersion.V1 ? StarterPipelineV1 : StarterPipelineV0))
} catch (ex) { } catch (ex) {
// ignore exception // ignore exception
} }
} }
}, [isExistingPipeline, originalPipelineYAMLFileContent, pipelineAsObj]) }, [yamlVersion, isExistingPipeline, originalPipelineYAMLFileContent, pipelineAsObj])
// find if editor content was modified // find if editor content was modified
useEffect(() => { useEffect(() => {
@ -206,7 +219,7 @@ const AddUpdatePipeline = (): JSX.Element => {
const updatePipeline = (payload: Record<string, any>): Record<string, any> => { const updatePipeline = (payload: Record<string, any>): Record<string, any> => {
const pipelineAsObjClone = { ...pipelineAsObj } const pipelineAsObjClone = { ...pipelineAsObj }
const stepInsertPath = version === YamlVersion.V0 ? 'steps' : 'stages.0.spec.steps' const stepInsertPath = yamlVersion === YamlVersion.V1 ? 'spec.stages.0.spec.steps' : 'steps'
let existingSteps: [unknown] = get(pipelineAsObjClone, stepInsertPath, []) let existingSteps: [unknown] = get(pipelineAsObjClone, stepInsertPath, [])
if (existingSteps.length > 0) { if (existingSteps.length > 0) {
existingSteps.push(payload) existingSteps.push(payload)
@ -309,13 +322,13 @@ const AddUpdatePipeline = (): JSX.Element => {
<Container className={css.editorContainer}> <Container className={css.editorContainer}>
<MonacoSourceCodeEditor <MonacoSourceCodeEditor
language={'yaml'} language={'yaml'}
schema={version === YamlVersion.V0 ? pipelineSchemaV0 : pipelineSchemaV1} schema={yamlVersion === YamlVersion.V1 ? pipelineSchemaV1 : pipelineSchemaV0}
source={pipelineAsYAML} source={pipelineAsYAML}
onChange={(value: string) => setPipelineAsYaml(value)} onChange={(value: string) => setPipelineAsYaml(value)}
/> />
</Container> </Container>
<Container className={css.pluginsContainer}> <Container className={css.pluginsContainer}>
<PluginsPanel onPluginAddUpdate={addUpdatePluginToPipelineYAML} /> <PluginsPanel onPluginAddUpdate={addUpdatePluginToPipelineYAML} version={yamlVersion} />
</Container> </Container>
</Layout.Horizontal> </Layout.Horizontal>
</PageBody> </PageBody>

View File

@ -5,3 +5,5 @@ export enum YamlVersion {
export const DEFAULT_YAML_PATH_PREFIX = '.harness/' export const DEFAULT_YAML_PATH_PREFIX = '.harness/'
export const DEFAULT_YAML_PATH_SUFFIX = '.yaml' export const DEFAULT_YAML_PATH_SUFFIX = '.yaml'
export const DRONE_CONFIG_YAML_FILE_SUFFIXES = ['.drone.yml', '.drone.yaml']

View File

@ -1,18 +1,142 @@
{ {
"definitions": { "definitions": {
"Pipeline": { "Config": {
"title": "Pipeline", "title": "Config",
"description": "Pipeline defines the pipeline execution.", "description": "Config defines the a resource configuration.",
"type": "object", "type": "object",
"properties": { "properties": {
"version": { "version": {
"description": "Version defines the schema version.", "description": "Version defines the schema version.",
"type": ["string", "number"] "type": ["string", "number"]
}, },
"name": { "kind": {
"description": "Pipeline provides the pipeline name.", "type": "string",
"type": "string" "description": "Type defines the schema type.",
"enum": ["pipeline", "plugin", "template"]
}, },
"type": {
"type": "string",
"description": "Type defines the schema type.",
"enum": ["pipeline", "stage", "step"]
},
"name": {
"type": "string",
"description": "Name defines an optional resource name."
}
},
"required": ["kind"],
"oneOf": [
{
"allOf": [
{
"properties": {
"kind": {
"const": "pipeline"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/Pipeline"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"kind": {
"const": "template"
},
"type": {
"const": "stage"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/TemplateStage"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"kind": {
"const": "template"
},
"type": {
"const": "step"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/TemplateStep"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"kind": {
"const": "plugin"
},
"type": {
"const": "step"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/PluginStep"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"kind": {
"const": "plugin"
},
"type": {
"const": "stage"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/PluginStage"
}
}
}
]
}
],
"x-go-skip": true,
"x-file": "config.yaml"
},
"Pipeline": {
"title": "Pipeline",
"description": "Pipeline defines the pipeline execution.",
"type": "object",
"properties": {
"stages": { "stages": {
"type": "array", "type": "array",
"description": "Stages defines a list of pipeline stages.", "description": "Stages defines a list of pipeline stages.",
@ -32,7 +156,7 @@
"description": "Options defines global configuration options." "description": "Options defines global configuration options."
} }
}, },
"required": ["version", "stages"], "required": ["stages"],
"examples": [ "examples": [
{ {
"version": 1, "version": 1,
@ -105,8 +229,8 @@
"description": "The stage conditional logic.", "description": "The stage conditional logic.",
"$ref": "#/definitions/When" "$ref": "#/definitions/When"
}, },
"on": { "failure": {
"$ref": "#/definitions/On" "$ref": "#/definitions/FailureList"
} }
}, },
"oneOf": [ "oneOf": [
@ -435,47 +559,26 @@
"x-go-skip": true, "x-go-skip": true,
"x-file": "when_expr.yaml" "x-file": "when_expr.yaml"
}, },
"On": { "FailureList": {
"title": "On", "title": "FailureList",
"type": "object", "oneOf": [
"properties": { {
"failure": { "$ref": "#/definitions/Failure"
"oneOf": [ },
{ {
"$ref": "#/definitions/Failure" "type": "array",
}, "items": {
{ "$ref": "#/definitions/Failure"
"type": "array", }
"items": {
"$ref": "#/definitions/Failure"
}
}
]
} }
}, ],
"x-go-skip": true, "x-go-skip": true,
"x-file": "on.yaml" "x-file": "failure_list.yaml"
}, },
"Failure": { "Failure": {
"title": "Failure", "title": "Failure",
"type": "object", "type": "object",
"description": "Failure defines a failure strategy.",
"properties": { "properties": {
"type": {
"description": "Type defines the failure strategy type.",
"type": "string",
"enum": [
"abort",
"ignore",
"manual-intervention",
"retry",
"success",
"stage-rollback",
"pipeline-rollback",
"retry-step-group",
"fail"
]
},
"errors": { "errors": {
"description": "Errors specifies the types of errors.", "description": "Errors specifies the types of errors.",
"type": "array", "type": "array",
@ -497,9 +600,125 @@
"user-mark-fail" "user-mark-fail"
] ]
} }
},
"action": {
"$ref": "#/definitions/FailureAction"
}
},
"x-file": "failure.yaml"
},
"FailureAction": {
"title": "FailureAction",
"type": "object",
"description": "Failure defines a failure strategy.",
"properties": {
"type": {
"description": "Type defines the failure strategy type.",
"type": "string",
"enum": [
"abort",
"fail",
"ignore",
"manual-intervention",
"pipeline-rollback",
"retry",
"retry-step-group",
"stage-rollback",
"success"
]
} }
}, },
"oneOf": [ "oneOf": [
{
"allOf": [
{
"properties": {
"type": {
"const": "success"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "fail"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "retry-step-group"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "stage-rollback"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "pipeline-rollback"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{ {
"allOf": [ "allOf": [
{ {
@ -573,7 +792,13 @@
] ]
} }
], ],
"x-file": "failure.yaml" "x-file": "failure_action.yaml"
},
"EmptySpec": {
"title": "EmptySpec",
"type": "object",
"properties": {},
"x-file": "empty_spec.yaml"
}, },
"Abort": { "Abort": {
"title": "Abort", "title": "Abort",
@ -611,18 +836,169 @@
} }
] ]
}, },
"on": { "failure": {
"$ref": "#/definitions/On" "$ref": "#/definitions/RetryFailure"
} }
}, },
"type": "object", "type": "object",
"x-file": "failure_retry.yaml" "x-file": "failure_retry.yaml"
}, },
"RetryFailure": {
"title": "RetryFailure",
"type": "object",
"properties": {
"action": {
"$ref": "#/definitions/RetryFailureAction"
}
},
"x-file": "retry_failure.yaml"
},
"RetryFailureAction": {
"title": "RetryFailureAction",
"type": "object",
"description": "Failure action on failure for all retries",
"properties": {
"type": {
"description": "Type defines the failure strategy type.",
"type": "string",
"enum": ["abort", "fail", "ignore", "manual-intervention", "pipeline-rollback", "stage-rollback", "success"]
}
},
"oneOf": [
{
"allOf": [
{
"properties": {
"type": {
"const": "success"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "fail"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "stage-rollback"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "pipeline-rollback"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "abort"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/Abort"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "ignore"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/Ignore"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "manual-intervention"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/ManualIntervention"
}
}
}
]
}
],
"x-file": "retry_failure_action.yaml"
},
"ManualIntervention": { "ManualIntervention": {
"title": "ManualIntervention", "title": "ManualIntervention",
"properties": { "properties": {
"on": { "timeout_action": {
"$ref": "#/definitions/On" "$ref": "#/definitions/TimeoutAction"
}, },
"timeout": { "timeout": {
"format": "duration", "format": "duration",
@ -633,6 +1009,129 @@
"type": "object", "type": "object",
"x-file": "failure_manual.yaml" "x-file": "failure_manual.yaml"
}, },
"TimeoutAction": {
"title": "TimeoutAction",
"type": "object",
"description": "Manual intervention for timeout failure action",
"properties": {
"type": {
"description": "Type defines the failure strategy type.",
"type": "string",
"enum": ["abort", "ignore", "success", "stage-rollback", "pipeline-rollback", "fail"]
}
},
"oneOf": [
{
"allOf": [
{
"properties": {
"type": {
"const": "success"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "fail"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "stage-rollback"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "pipeline-rollback"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/EmptySpec"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "abort"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/Abort"
}
}
}
]
},
{
"allOf": [
{
"properties": {
"type": {
"const": "ignore"
}
}
},
{
"properties": {
"spec": {
"$ref": "#/definitions/Ignore"
}
}
}
]
}
],
"x-file": "timeout_action.yaml"
},
"StageCI": { "StageCI": {
"properties": { "properties": {
"cache": { "cache": {
@ -1080,8 +1579,8 @@
"description": "The stage conditional logic.", "description": "The stage conditional logic.",
"$ref": "#/definitions/When" "$ref": "#/definitions/When"
}, },
"on": { "failure": {
"$ref": "#/definitions/On" "$ref": "#/definitions/FailureList"
} }
}, },
"oneOf": [ "oneOf": [
@ -2138,6 +2637,10 @@
}, },
"description": "Enum defines a list of accepted input values.", "description": "Enum defines a list of accepted input values.",
"x-go-type": "[]string" "x-go-type": "[]string"
},
"mask": {
"type": "boolean",
"description": "Mask indicates the input should be masked."
} }
}, },
"x-file": "input.yaml" "x-file": "input.yaml"
@ -2362,11 +2865,115 @@
} }
}, },
"x-file": "status.yaml" "x-file": "status.yaml"
},
"TemplateStage": {
"title": "TemplateStage",
"description": "TemplateStage defines a stage-level template",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The template name."
},
"description": {
"type": "string",
"description": "The template description."
},
"stage": {
"$ref": "#/definitions/Stage"
},
"inputs": {
"type": "object",
"description": "Inputs defines the template input parameters.",
"additionalProperties": {
"$ref": "#/definitions/Input"
}
}
},
"x-file": "template_stage.yaml"
},
"TemplateStep": {
"title": "TemplateStep",
"description": "TemplateStep defines a step-level template",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The template name."
},
"description": {
"type": "string",
"description": "The template description."
},
"step": {
"$ref": "#/definitions/Step"
},
"inputs": {
"type": "object",
"description": "Inputs defines the template input parameters.",
"additionalProperties": {
"$ref": "#/definitions/Input"
}
}
},
"x-file": "template_step.yaml"
},
"PluginStep": {
"title": "PluginStep",
"description": "PluginStep defines a step-level plugin",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The plugin name."
},
"description": {
"type": "string",
"description": "The plugin description."
},
"step": {
"$ref": "#/definitions/Step"
},
"inputs": {
"type": "object",
"description": "Inputs defines the plugin input parameters.",
"additionalProperties": {
"$ref": "#/definitions/Input"
}
}
},
"x-file": "plugin_step.yaml"
},
"PluginStage": {
"title": "PluginStage",
"description": "PluginStage defines a stage-level plugin",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The plugin name."
},
"description": {
"type": "string",
"description": "The plugin description."
},
"stage": {
"$ref": "#/definitions/Stage"
},
"inputs": {
"type": "object",
"description": "Inputs defines the plugin input parameters.",
"additionalProperties": {
"$ref": "#/definitions/Input"
}
}
},
"x-file": "plugin_stage.yaml"
} }
}, },
"oneOf": [ "oneOf": [
{ {
"$ref": "#/definitions/Pipeline" "$ref": "#/definitions/Config"
} }
] ]
} }