2017-06-02 09:24:42 -04:00
< script >
2020-09-23 14:10:15 -04:00
import { GlAlert , GlButton , GlLoadingIcon , GlModal , GlModalDirective } from '@gitlab/ui' ;
2021-02-14 13:09:20 -05:00
import { setUrlFragment , redirectTo } from '~/lib/utils/url_utility' ;
2019-06-25 02:10:25 -04:00
import { _ _ } from '~/locale' ;
2020-09-23 14:10:15 -04:00
import ciHeader from '~/vue_shared/components/header_ci_component.vue' ;
2021-02-14 13:09:20 -05:00
import { LOAD _FAILURE , POST _FAILURE , DELETE _FAILURE , DEFAULT } from '../constants' ;
import cancelPipelineMutation from '../graphql/mutations/cancel_pipeline.mutation.graphql' ;
2020-11-09 19:08:52 -05:00
import deletePipelineMutation from '../graphql/mutations/delete_pipeline.mutation.graphql' ;
import retryPipelineMutation from '../graphql/mutations/retry_pipeline.mutation.graphql' ;
2021-02-14 13:09:20 -05:00
import getPipelineQuery from '../graphql/queries/get_pipeline_header_data.query.graphql' ;
2021-03-16 05:11:17 -04:00
import { getQueryHeaders } from './graph/utils' ;
2017-06-02 09:24:42 -04:00
2020-01-08 07:07:59 -05:00
const DELETE _MODAL _ID = 'pipeline-delete-modal' ;
2020-11-09 19:08:52 -05:00
const POLL _INTERVAL = 10000 ;
2020-01-08 07:07:59 -05:00
2018-06-27 10:28:05 -04:00
export default {
name : 'PipelineHeaderSection' ,
2020-11-09 19:08:52 -05:00
pipelineCancel : 'pipelineCancel' ,
pipelineRetry : 'pipelineRetry' ,
2020-11-13 10:09:24 -05:00
finishedStatuses : [ 'FAILED' , 'SUCCESS' , 'CANCELED' ] ,
2018-06-27 10:28:05 -04:00
components : {
ciHeader ,
2020-09-23 14:10:15 -04:00
GlAlert ,
GlButton ,
2018-11-07 05:06:15 -05:00
GlLoadingIcon ,
2020-01-08 07:07:59 -05:00
GlModal ,
2020-01-29 16:09:22 -05:00
} ,
directives : {
GlModal : GlModalDirective ,
2018-06-27 10:28:05 -04:00
} ,
2020-09-23 14:10:15 -04:00
errorTexts : {
[ LOAD _FAILURE ] : _ _ ( 'We are currently unable to fetch data for the pipeline header.' ) ,
[ POST _FAILURE ] : _ _ ( 'An error occurred while making the request.' ) ,
[ DELETE _FAILURE ] : _ _ ( 'An error occurred while deleting the pipeline.' ) ,
[ DEFAULT ] : _ _ ( 'An unknown error occurred.' ) ,
} ,
inject : {
2021-03-16 05:11:17 -04:00
graphqlResourceEtag : {
default : '' ,
} ,
2020-09-23 14:10:15 -04:00
paths : {
default : { } ,
} ,
pipelineId : {
default : '' ,
2017-06-02 09:24:42 -04:00
} ,
2020-09-23 14:10:15 -04:00
pipelineIid : {
default : '' ,
} ,
} ,
apollo : {
pipeline : {
2021-03-16 05:11:17 -04:00
context ( ) {
return getQueryHeaders ( this . graphqlResourceEtag ) ;
} ,
2020-09-23 14:10:15 -04:00
query : getPipelineQuery ,
variables ( ) {
return {
fullPath : this . paths . fullProject ,
iid : this . pipelineIid ,
} ;
} ,
2020-12-23 19:10:25 -05:00
update : ( data ) => data . project . pipeline ,
2020-09-23 14:10:15 -04:00
error ( ) {
this . reportFailure ( LOAD _FAILURE ) ;
} ,
2020-11-09 19:08:52 -05:00
pollInterval : POLL _INTERVAL ,
2020-09-23 14:10:15 -04:00
watchLoading ( isLoading ) {
if ( ! isLoading ) {
// To ensure apollo has updated the cache,
// we only remove the loading state in sync with GraphQL
this . isCanceling = false ;
this . isRetrying = false ;
}
} ,
2017-06-02 09:24:42 -04:00
} ,
2018-06-27 10:28:05 -04:00
} ,
data ( ) {
return {
2020-09-23 14:10:15 -04:00
pipeline : null ,
failureType : null ,
2020-01-29 16:09:22 -05:00
isCanceling : false ,
isRetrying : false ,
isDeleting : false ,
2018-06-27 10:28:05 -04:00
} ;
} ,
computed : {
2020-01-08 07:07:59 -05:00
deleteModalConfirmationText ( ) {
return _ _ (
'Are you sure you want to delete this pipeline? Doing so will expire all pipeline caches and delete all related objects, such as builds, logs, artifacts, and triggers. This action cannot be undone.' ,
) ;
} ,
2020-09-23 14:10:15 -04:00
hasError ( ) {
return this . failureType ;
} ,
hasPipelineData ( ) {
return Boolean ( this . pipeline ) ;
} ,
isLoadingInitialQuery ( ) {
return this . $apollo . queries . pipeline . loading && ! this . hasPipelineData ;
} ,
status ( ) {
return this . pipeline ? . status ;
} ,
2020-11-13 10:09:24 -05:00
isFinished ( ) {
return this . $options . finishedStatuses . includes ( this . status ) ;
} ,
2020-09-23 14:10:15 -04:00
shouldRenderContent ( ) {
return ! this . isLoadingInitialQuery && this . hasPipelineData ;
} ,
failure ( ) {
switch ( this . failureType ) {
case LOAD _FAILURE :
return {
text : this . $options . errorTexts [ LOAD _FAILURE ] ,
variant : 'danger' ,
} ;
case POST _FAILURE :
return {
text : this . $options . errorTexts [ POST _FAILURE ] ,
variant : 'danger' ,
} ;
case DELETE _FAILURE :
return {
text : this . $options . errorTexts [ DELETE _FAILURE ] ,
variant : 'danger' ,
} ;
default :
return {
text : this . $options . errorTexts [ DEFAULT ] ,
variant : 'danger' ,
} ;
}
} ,
2021-05-25 08:10:23 -04:00
canRetryPipeline ( ) {
const { retryable , userPermissions } = this . pipeline ;
return retryable && userPermissions . updatePipeline ;
} ,
canCancelPipeline ( ) {
const { cancelable , userPermissions } = this . pipeline ;
return cancelable && userPermissions . updatePipeline ;
} ,
2018-06-27 10:28:05 -04:00
} ,
2020-11-13 10:09:24 -05:00
watch : {
isFinished ( finished ) {
if ( finished ) {
this . $apollo . queries . pipeline . stopPolling ( ) ;
}
} ,
} ,
2018-06-27 10:28:05 -04:00
methods : {
2020-09-23 14:10:15 -04:00
reportFailure ( errorType ) {
this . failureType = errorType ;
} ,
2020-11-09 19:08:52 -05:00
async postPipelineAction ( name , mutation ) {
2020-09-23 14:10:15 -04:00
try {
2020-11-09 19:08:52 -05:00
const {
data : {
[ name ] : { errors } ,
} ,
} = await this . $apollo . mutate ( {
mutation ,
variables : { id : this . pipeline . id } ,
} ) ;
if ( errors . length > 0 ) {
this . reportFailure ( POST _FAILURE ) ;
} else {
2020-11-13 10:09:24 -05:00
await this . $apollo . queries . pipeline . refetch ( ) ;
if ( ! this . isFinished ) {
this . $apollo . queries . pipeline . startPolling ( POLL _INTERVAL ) ;
}
2020-11-09 19:08:52 -05:00
}
2020-09-23 14:10:15 -04:00
} catch {
this . reportFailure ( POST _FAILURE ) ;
}
} ,
2020-11-09 19:08:52 -05:00
cancelPipeline ( ) {
2020-01-29 16:09:22 -05:00
this . isCanceling = true ;
2020-11-09 19:08:52 -05:00
this . postPipelineAction ( this . $options . pipelineCancel , cancelPipelineMutation ) ;
2020-01-08 07:07:59 -05:00
} ,
2020-11-09 19:08:52 -05:00
retryPipeline ( ) {
2020-01-29 16:09:22 -05:00
this . isRetrying = true ;
2020-11-09 19:08:52 -05:00
this . postPipelineAction ( this . $options . pipelineRetry , retryPipelineMutation ) ;
2018-06-27 10:28:05 -04:00
} ,
2020-09-23 14:10:15 -04:00
async deletePipeline ( ) {
2020-01-29 16:09:22 -05:00
this . isDeleting = true ;
2020-09-23 14:10:15 -04:00
this . $apollo . queries . pipeline . stopPolling ( ) ;
try {
2020-11-09 19:08:52 -05:00
const {
data : {
pipelineDestroy : { errors } ,
} ,
} = await this . $apollo . mutate ( {
mutation : deletePipelineMutation ,
variables : {
id : this . pipeline . id ,
} ,
} ) ;
if ( errors . length > 0 ) {
this . reportFailure ( DELETE _FAILURE ) ;
this . isDeleting = false ;
} else {
redirectTo ( setUrlFragment ( this . paths . pipelinesPath , 'delete_success' ) ) ;
}
2020-09-23 14:10:15 -04:00
} catch {
2020-11-09 19:08:52 -05:00
this . $apollo . queries . pipeline . startPolling ( POLL _INTERVAL ) ;
2020-09-23 14:10:15 -04:00
this . reportFailure ( DELETE _FAILURE ) ;
this . isDeleting = false ;
}
2017-06-02 09:24:42 -04:00
} ,
2018-06-27 10:28:05 -04:00
} ,
2020-01-08 07:07:59 -05:00
DELETE _MODAL _ID ,
2018-06-27 10:28:05 -04:00
} ;
2017-06-02 09:24:42 -04:00
< / script >
< template >
< div class = "pipeline-header-container" >
2020-09-23 14:10:15 -04:00
< gl-alert v-if = "hasError" :variant="failure.variant" > {{ failure.text }} < / gl -alert >
2017-06-02 09:24:42 -04:00
< ci-header
v - if = "shouldRenderContent"
2020-09-23 14:10:15 -04:00
: status = "pipeline.detailedStatus"
: time = "pipeline.createdAt"
2017-06-02 09:24:42 -04:00
: user = "pipeline.user"
2020-09-23 14:10:15 -04:00
: item - id = "Number(pipelineId)"
2018-06-11 05:49:47 -04:00
item - name = "Pipeline"
2020-01-29 16:09:22 -05:00
>
2020-08-10 14:09:54 -04:00
< gl-button
2021-05-25 08:10:23 -04:00
v - if = "canRetryPipeline"
2020-01-29 16:09:22 -05:00
: loading = "isRetrying"
: disabled = "isRetrying"
2020-08-10 14:09:54 -04:00
category = "secondary"
variant = "info"
2020-09-23 14:10:15 -04:00
data - testid = "retryPipeline"
class = "js-retry-button"
2020-01-29 16:09:22 -05:00
@ click = "retryPipeline()"
2020-08-10 14:09:54 -04:00
>
{ { _ _ ( 'Retry' ) } }
< / gl-button >
2020-01-29 16:09:22 -05:00
2020-08-10 14:09:54 -04:00
< gl-button
2021-05-25 08:10:23 -04:00
v - if = "canCancelPipeline"
2020-01-29 16:09:22 -05:00
: loading = "isCanceling"
: disabled = "isCanceling"
2020-11-30 16:09:16 -05:00
class = "gl-ml-3"
2020-08-10 14:09:54 -04:00
variant = "danger"
2020-09-23 14:10:15 -04:00
data - testid = "cancelPipeline"
2020-01-29 16:09:22 -05:00
@ click = "cancelPipeline()"
2020-08-10 14:09:54 -04:00
>
{ { _ _ ( 'Cancel running' ) } }
< / gl-button >
2020-01-29 16:09:22 -05:00
2020-08-10 14:09:54 -04:00
< gl-button
2020-09-23 14:10:15 -04:00
v - if = "pipeline.userPermissions.destroyPipeline"
2020-01-29 16:09:22 -05:00
v - gl - modal = "$options.DELETE_MODAL_ID"
: loading = "isDeleting"
: disabled = "isDeleting"
2020-08-10 14:09:54 -04:00
class = "gl-ml-3"
variant = "danger"
2020-09-23 14:10:15 -04:00
category = "secondary"
data - testid = "deletePipeline"
2020-08-10 14:09:54 -04:00
>
{ { _ _ ( 'Delete' ) } }
< / gl-button >
2020-01-29 16:09:22 -05:00
< / ci-header >
2020-09-23 14:10:15 -04:00
< gl-loading-icon v-if = "isLoadingInitialQuery" size="lg" class="gl-mt-3 gl-mb-3" / >
2020-01-08 07:07:59 -05:00
< gl-modal
: modal - id = "$options.DELETE_MODAL_ID"
: title = "__('Delete pipeline')"
: ok - title = "__('Delete pipeline')"
ok - variant = "danger"
@ ok = "deletePipeline()"
>
< p >
{ { deleteModalConfirmationText } }
< / p >
< / gl-modal >
2017-06-02 09:24:42 -04:00
< / div >
< / template >