mirror of
https://github.com/harness/drone.git
synced 2025-05-11 14:40:05 +08:00
run pipeline integration
This commit is contained in:
parent
7735f2b7a7
commit
b0a4946d80
@ -39,7 +39,7 @@ const PluginCategories: PluginInterface[] = [
|
|||||||
{ category: PluginCategory.Drone, name: 'Drone', description: 'Run Drone plugins', icon: 'ci-infra' }
|
{ category: PluginCategory.Drone, name: 'Drone', description: 'Run Drone plugins', icon: 'ci-infra' }
|
||||||
]
|
]
|
||||||
|
|
||||||
const pluginSpecMock = {
|
const dronePluginSpecMock = {
|
||||||
inputs: {
|
inputs: {
|
||||||
channel: {
|
channel: {
|
||||||
type: 'string'
|
type: 'string'
|
||||||
@ -61,6 +61,14 @@ const pluginSpecMock = {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const runStepSpec = {
|
||||||
|
inputs: {
|
||||||
|
script: {
|
||||||
|
type: 'string'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export interface PluginsPanelInterface {
|
export interface PluginsPanelInterface {
|
||||||
onPluginAddUpdate?: (isUpdate: boolean, pluginFormData: Record<string, any>) => void
|
onPluginAddUpdate?: (isUpdate: boolean, pluginFormData: Record<string, any>) => void
|
||||||
}
|
}
|
||||||
@ -101,6 +109,9 @@ export const PluginsPanel = ({ onPluginAddUpdate }: PluginsPanelInterface): JSX.
|
|||||||
setCategory(category)
|
setCategory(category)
|
||||||
if (category === PluginCategory.Drone) {
|
if (category === PluginCategory.Drone) {
|
||||||
setPanelView(PluginPanelView.Listing)
|
setPanelView(PluginPanelView.Listing)
|
||||||
|
} else if (category === PluginCategory.Harness) {
|
||||||
|
setPlugin({ uid: getString('run') })
|
||||||
|
setPanelView(PluginPanelView.Configuration)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
key={category}
|
key={category}
|
||||||
@ -187,15 +198,8 @@ export const PluginsPanel = ({ onPluginAddUpdate }: PluginsPanelInterface): JSX.
|
|||||||
}
|
}
|
||||||
|
|
||||||
const renderPluginConfigForm = useCallback((): JSX.Element => {
|
const renderPluginConfigForm = useCallback((): JSX.Element => {
|
||||||
const { uid, spec } = plugin || {}
|
// TODO obtain plugin input spec by parsing YAML
|
||||||
if (spec) {
|
const inputs = get(category === PluginCategory.Drone ? dronePluginSpecMock : runStepSpec, 'inputs', {})
|
||||||
// let specAsObj = {}
|
|
||||||
// try {
|
|
||||||
// specAsObj = parse(spec)
|
|
||||||
// } catch (e) {
|
|
||||||
// // ignore error
|
|
||||||
// }
|
|
||||||
const inputs = get(pluginSpecMock, 'inputs', {})
|
|
||||||
return (
|
return (
|
||||||
<Layout.Vertical
|
<Layout.Vertical
|
||||||
spacing="medium"
|
spacing="medium"
|
||||||
@ -207,13 +211,21 @@ export const PluginsPanel = ({ onPluginAddUpdate }: PluginsPanelInterface): JSX.
|
|||||||
size={18}
|
size={18}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setPlugin(undefined)
|
setPlugin(undefined)
|
||||||
|
if (category === PluginCategory.Drone) {
|
||||||
setPanelView(PluginPanelView.Listing)
|
setPanelView(PluginPanelView.Listing)
|
||||||
|
} else if (category === PluginCategory.Harness) {
|
||||||
|
setPanelView(PluginPanelView.Category)
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
className={css.arrow}
|
className={css.arrow}
|
||||||
/>
|
/>
|
||||||
|
{plugin?.uid ? (
|
||||||
<Text font={{ variation: FontVariation.H5 }}>
|
<Text font={{ variation: FontVariation.H5 }}>
|
||||||
{getString('addLabel')} {uid}
|
{getString('addLabel')} {plugin.uid} {getString('plugins.stepLabel')}
|
||||||
</Text>
|
</Text>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
</Layout.Horizontal>
|
</Layout.Horizontal>
|
||||||
<Container className={css.form}>
|
<Container className={css.form}>
|
||||||
<Formik
|
<Formik
|
||||||
@ -236,9 +248,7 @@ export const PluginsPanel = ({ onPluginAddUpdate }: PluginsPanelInterface): JSX.
|
|||||||
</Container>
|
</Container>
|
||||||
</Layout.Vertical>
|
</Layout.Vertical>
|
||||||
)
|
)
|
||||||
}
|
}, [plugin, category])
|
||||||
return <></>
|
|
||||||
}, [plugin])
|
|
||||||
|
|
||||||
const renderPluginsPanel = useCallback((): JSX.Element => {
|
const renderPluginsPanel = useCallback((): JSX.Element => {
|
||||||
switch (panelView) {
|
switch (panelView) {
|
||||||
@ -251,7 +261,7 @@ export const PluginsPanel = ({ onPluginAddUpdate }: PluginsPanelInterface): JSX.
|
|||||||
default:
|
default:
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
}, [loading, plugins, panelView])
|
}, [loading, plugins, panelView, category])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className={css.main}>
|
<Container className={css.main}>
|
||||||
|
103
web/src/components/RunPipelineModal/RunPipelineModal.tsx
Normal file
103
web/src/components/RunPipelineModal/RunPipelineModal.tsx
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import React, { useMemo, useState } from 'react'
|
||||||
|
import * as yup from 'yup'
|
||||||
|
import { FontVariation } from '@harnessio/design-system'
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
ButtonVariation,
|
||||||
|
Dialog,
|
||||||
|
FormInput,
|
||||||
|
Formik,
|
||||||
|
FormikForm,
|
||||||
|
Layout,
|
||||||
|
Text,
|
||||||
|
useToaster
|
||||||
|
} from '@harnessio/uicore'
|
||||||
|
import { useStrings } from 'framework/strings'
|
||||||
|
import { useModalHook } from 'hooks/useModalHook'
|
||||||
|
import type { OpenapiCreateExecutionRequest, TypesExecution, TypesRepository } from 'services/code'
|
||||||
|
import { useMutate } from 'restful-react'
|
||||||
|
import { getErrorMessage } from 'utils/Utils'
|
||||||
|
import { useHistory } from 'react-router'
|
||||||
|
import { useAppContext } from 'AppContext'
|
||||||
|
|
||||||
|
interface FormData {
|
||||||
|
branch: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const useRunPipelineModal = () => {
|
||||||
|
const { routes } = useAppContext()
|
||||||
|
const { getString } = useStrings()
|
||||||
|
const { showError } = useToaster()
|
||||||
|
const history = useHistory()
|
||||||
|
const [repo, setRepo] = useState<TypesRepository>()
|
||||||
|
const [pipeline, setPipeline] = useState<string>('')
|
||||||
|
const repoPath = useMemo(() => repo?.path || '', [repo])
|
||||||
|
|
||||||
|
const { mutate: startExecution } = useMutate<TypesExecution>({
|
||||||
|
verb: 'POST',
|
||||||
|
path: `/api/v1/repos/${repoPath}/+/pipelines/${pipeline}/executions`
|
||||||
|
})
|
||||||
|
|
||||||
|
const runPipeline = (_formData: FormData): void => {
|
||||||
|
try {
|
||||||
|
const payload: OpenapiCreateExecutionRequest = {
|
||||||
|
status: ''
|
||||||
|
}
|
||||||
|
startExecution(payload, { pathParams: { path: `/api/v1/repos/${repoPath}/+/pipelines/${pipeline}/executions` } })
|
||||||
|
.then(() => {
|
||||||
|
history.push(routes.toCODEExecutions({ repoPath, pipeline }))
|
||||||
|
hideModal()
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
showError(getErrorMessage(error), 0, 'pipelines.failedToRunPipeline')
|
||||||
|
})
|
||||||
|
} catch (exception) {
|
||||||
|
showError(getErrorMessage(exception), 0, 'pipelines.failedToRunPipeline')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [openModal, hideModal] = useModalHook(() => {
|
||||||
|
const onClose = () => {
|
||||||
|
hideModal()
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Dialog isOpen enforceFocus={false} onClose={onClose} title={getString('pipelines.run')}>
|
||||||
|
<Formik
|
||||||
|
formName="run-pipeline-form"
|
||||||
|
initialValues={{ branch: repo?.default_branch || '' }}
|
||||||
|
validationSchema={yup.object().shape({
|
||||||
|
branch: yup
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.required(`${getString('branch')} ${getString('isRequired')}`)
|
||||||
|
})}
|
||||||
|
onSubmit={runPipeline}
|
||||||
|
enableReinitialize>
|
||||||
|
<FormikForm>
|
||||||
|
<Layout.Vertical spacing="medium">
|
||||||
|
<FormInput.Text
|
||||||
|
name="branch"
|
||||||
|
label={<Text font={{ variation: FontVariation.FORM_LABEL }}>{getString('branch')}</Text>}
|
||||||
|
/>
|
||||||
|
<Layout.Horizontal spacing="medium">
|
||||||
|
<Button variation={ButtonVariation.PRIMARY} type="submit" text={getString('pipelines.run')} />
|
||||||
|
<Button variation={ButtonVariation.SECONDARY} text={getString('cancel')} onClick={onClose} />
|
||||||
|
</Layout.Horizontal>
|
||||||
|
</Layout.Vertical>
|
||||||
|
</FormikForm>
|
||||||
|
</Formik>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}, [repo?.default_branch, pipeline])
|
||||||
|
|
||||||
|
return {
|
||||||
|
openModal: ({ repoMetadata, pipeline }: { repoMetadata: TypesRepository; pipeline: string }) => {
|
||||||
|
setRepo(repoMetadata)
|
||||||
|
setPipeline(pipeline)
|
||||||
|
openModal()
|
||||||
|
},
|
||||||
|
hideModal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useRunPipelineModal
|
@ -323,6 +323,7 @@ export interface StringsMap {
|
|||||||
'pipelines.enterPipelineName': string
|
'pipelines.enterPipelineName': string
|
||||||
'pipelines.enterYAMLPath': string
|
'pipelines.enterYAMLPath': string
|
||||||
'pipelines.failedToCreatePipeline': string
|
'pipelines.failedToCreatePipeline': string
|
||||||
|
'pipelines.failedToRunPipeline': string
|
||||||
'pipelines.name': string
|
'pipelines.name': string
|
||||||
'pipelines.newPipelineButton': string
|
'pipelines.newPipelineButton': string
|
||||||
'pipelines.noData': string
|
'pipelines.noData': string
|
||||||
@ -330,6 +331,7 @@ export interface StringsMap {
|
|||||||
'pipelines.saveAndRun': string
|
'pipelines.saveAndRun': string
|
||||||
'pipelines.yamlPath': string
|
'pipelines.yamlPath': string
|
||||||
'plugins.addAPlugin': string
|
'plugins.addAPlugin': string
|
||||||
|
'plugins.stepLabel': string
|
||||||
'plugins.title': string
|
'plugins.title': string
|
||||||
'pr.ableToMerge': string
|
'pr.ableToMerge': string
|
||||||
'pr.addDescription': string
|
'pr.addDescription': string
|
||||||
|
@ -636,6 +636,7 @@ pipelines:
|
|||||||
saveAndRun: Save and Run
|
saveAndRun: Save and Run
|
||||||
editPipeline: Edit pipeline {{pipeline}}
|
editPipeline: Edit pipeline {{pipeline}}
|
||||||
run: Run pipeline
|
run: Run pipeline
|
||||||
|
failedToRunPipeline: Failed to run pipeline
|
||||||
executions:
|
executions:
|
||||||
noData: There are no executions :(
|
noData: There are no executions :(
|
||||||
newExecutionButton: Run Pipeline
|
newExecutionButton: Run Pipeline
|
||||||
@ -657,3 +658,4 @@ run: Run
|
|||||||
plugins:
|
plugins:
|
||||||
title: Plugins
|
title: Plugins
|
||||||
addAPlugin: Add a {{category}} plugin
|
addAPlugin: Add a {{category}} plugin
|
||||||
|
stepLabel: step
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useMemo, useState } from 'react'
|
import React, { useMemo, useState } from 'react'
|
||||||
import { useMutate } from 'restful-react'
|
import { useMutate } from 'restful-react'
|
||||||
import { Link, useParams } from 'react-router-dom'
|
import { Link, useParams } from 'react-router-dom'
|
||||||
import { Drawer } from '@blueprintjs/core'
|
|
||||||
import { Container, PageHeader, PageBody, Button, Layout, ButtonVariation, Text, useToaster } from '@harnessio/uicore'
|
import { Container, PageHeader, PageBody, Button, Layout, ButtonVariation, Text, useToaster } from '@harnessio/uicore'
|
||||||
import { Icon } from '@harnessio/icons'
|
import { Icon } from '@harnessio/icons'
|
||||||
import { Color } from '@harnessio/design-system'
|
import { Color } from '@harnessio/design-system'
|
||||||
@ -10,6 +9,7 @@ import { useStrings } from 'framework/strings'
|
|||||||
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
|
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
|
||||||
import MonacoSourceCodeEditor from 'components/SourceCodeEditor/MonacoSourceCodeEditor'
|
import MonacoSourceCodeEditor from 'components/SourceCodeEditor/MonacoSourceCodeEditor'
|
||||||
import { PluginsPanel } from 'components/PluginsPanel/PluginsPanel'
|
import { PluginsPanel } from 'components/PluginsPanel/PluginsPanel'
|
||||||
|
import useRunPipelineModal from 'components/RunPipelineModal/RunPipelineModal'
|
||||||
import { useAppContext } from 'AppContext'
|
import { useAppContext } from 'AppContext'
|
||||||
import type { CODEProps } from 'RouteDefinitions'
|
import type { CODEProps } from 'RouteDefinitions'
|
||||||
import { getErrorMessage } from 'utils/Utils'
|
import { getErrorMessage } from 'utils/Utils'
|
||||||
@ -24,7 +24,7 @@ const NewPipeline = (): JSX.Element => {
|
|||||||
const { repoMetadata } = useGetRepositoryMetadata()
|
const { repoMetadata } = useGetRepositoryMetadata()
|
||||||
const { showError } = useToaster()
|
const { showError } = useToaster()
|
||||||
const [pipelineAsYAML, setPipelineAsYaml] = useState<string>('')
|
const [pipelineAsYAML, setPipelineAsYaml] = useState<string>('')
|
||||||
const [showDrawer, setShowDrawer] = useState<boolean>(false)
|
const { openModal: openRunPipelineModal } = useRunPipelineModal()
|
||||||
const repoPath = useMemo(() => repoMetadata?.path || '', [repoMetadata])
|
const repoPath = useMemo(() => repoMetadata?.path || '', [repoMetadata])
|
||||||
|
|
||||||
const { mutate, loading } = useMutate<RepoCommitFilesResponse>({
|
const { mutate, loading } = useMutate<RepoCommitFilesResponse>({
|
||||||
@ -36,14 +36,18 @@ const NewPipeline = (): JSX.Element => {
|
|||||||
try {
|
try {
|
||||||
const data: OpenapiCommitFilesRequest = {
|
const data: OpenapiCommitFilesRequest = {
|
||||||
actions: [{ action: 'CREATE', path: `sample_${new Date().getTime()}.txt`, payload: pipelineAsYAML }],
|
actions: [{ action: 'CREATE', path: `sample_${new Date().getTime()}.txt`, payload: pipelineAsYAML }],
|
||||||
branch: 'main',
|
branch: repoMetadata?.default_branch,
|
||||||
new_branch: '',
|
new_branch: '',
|
||||||
title: `Create pipeline ${pipeline}`,
|
title: `Create pipeline ${pipeline}`,
|
||||||
message: ''
|
message: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
mutate(data)
|
mutate(data)
|
||||||
.then(() => setShowDrawer(true))
|
.then(() => {
|
||||||
|
if (repoMetadata && pipeline) {
|
||||||
|
openRunPipelineModal({ repoMetadata, pipeline })
|
||||||
|
}
|
||||||
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
showError(getErrorMessage(error), 0, 'pipelines.failedToSavePipeline')
|
showError(getErrorMessage(error), 0, 'pipelines.failedToSavePipeline')
|
||||||
})
|
})
|
||||||
@ -54,20 +58,6 @@ const NewPipeline = (): JSX.Element => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{showDrawer && (
|
|
||||||
<Drawer isOpen={showDrawer} title={getString('pipelines.run')} onClose={() => setShowDrawer(false)}>
|
|
||||||
<Layout.Vertical padding="xlarge" flex={{ justifyContent: 'flex-end' }} className={css.drawer}>
|
|
||||||
<Layout.Horizontal spacing="medium" flex={{ justifyContent: 'flex-start' }} width="100%">
|
|
||||||
<Button variation={ButtonVariation.PRIMARY} text={getString('run')} />
|
|
||||||
<Button
|
|
||||||
variation={ButtonVariation.SECONDARY}
|
|
||||||
text={getString('cancel')}
|
|
||||||
onClick={() => setShowDrawer(false)}
|
|
||||||
/>
|
|
||||||
</Layout.Horizontal>
|
|
||||||
</Layout.Vertical>
|
|
||||||
</Drawer>
|
|
||||||
)}
|
|
||||||
<Container className={css.main}>
|
<Container className={css.main}>
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title={getString('pipelines.editPipeline', { pipeline })}
|
title={getString('pipelines.editPipeline', { pipeline })}
|
||||||
|
@ -8,6 +8,7 @@ import type { OpenapiCreatePipelineRequest, TypesPipeline, TypesRepository } fro
|
|||||||
import { useStrings } from 'framework/strings'
|
import { useStrings } from 'framework/strings'
|
||||||
import { useAppContext } from 'AppContext'
|
import { useAppContext } from 'AppContext'
|
||||||
import { getErrorMessage } from 'utils/Utils'
|
import { getErrorMessage } from 'utils/Utils'
|
||||||
|
|
||||||
interface FormData {
|
interface FormData {
|
||||||
name: string
|
name: string
|
||||||
branch: string
|
branch: string
|
||||||
|
Loading…
Reference in New Issue
Block a user