diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue b/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue index 87bb5d16fe6d4e0bffaf7458bb90332f85689ee3..5a584ea1e40ddad58039aaf4f3f58f1116f1bbf8 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue @@ -5,6 +5,7 @@ import { __, s__, sprintf } from '~/locale'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import CiIcon from '~/vue_shared/components/ci_icon.vue'; import SafeHtml from '~/vue_shared/directives/safe_html'; +import { BRIDGE_KIND } from '~/pipelines/components/graph/constants'; import RetryMrFailedJobMutation from '../../../graphql/mutations/retry_mr_failed_job.mutation.graphql'; export default { @@ -37,7 +38,10 @@ export default { return this.job.userPermissions.readBuild; }, canRetryJob() { - return this.job.retryable && this.job.userPermissions.updateBuild; + return this.job.retryable && this.job.userPermissions.updateBuild && !this.isBridgeJob; + }, + isBridgeJob() { + return this.job.kind === BRIDGE_KIND; }, isVisibleId() { return `log-${this.isJobLogVisible ? 'is-visible' : 'is-hidden'}`; @@ -55,6 +59,11 @@ export default { parsedJobId() { return getIdFromGraphQLId(this.job.id); }, + tooltipErrorText() { + return this.isBridgeJob + ? this.$options.i18n.cannotRetryTrigger + : this.$options.i18n.cannotRetry; + }, tooltipText() { return sprintf(this.$options.i18n.jobActionTooltipText, { jobName: this.job.name }); }, @@ -99,8 +108,9 @@ export default { }, }, i18n: { - cannotReadBuild: s__("Job|You do not have permission to read this job's log"), - cannotRetry: s__('Job|You do not have permission to retry this job'), + cannotReadBuild: s__("Job|You do not have permission to read this job's log."), + cannotRetry: s__('Job|You do not have permission to run this job again.'), + cannotRetryTrigger: s__('Job|You cannot rerun trigger jobs from this list.'), jobActionTooltipText: s__('Pipelines|Retry %{jobName} Job'), noTraceText: s__('Job|No job log'), retry: __('Retry'), @@ -129,10 +139,10 @@ export default { </div> <div class="col-2 gl-text-left">{{ job.stage.name }}</div> <div class="col-2 gl-text-left"> - <gl-link :href="job.webPath">#{{ parsedJobId }}</gl-link> + <gl-link :href="job.detailedStatus.detailsPath">#{{ parsedJobId }}</gl-link> </div> <gl-tooltip v-if="!canRetryJob" :target="() => $refs.retryBtn" placement="top"> - {{ $options.i18n.cannotRetry }} + {{ tooltipErrorText }} </gl-tooltip> <div class="col-2 gl-text-right"> <span ref="retryBtn"> diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_failed_jobs.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_failed_jobs.query.graphql index 3d69c5e451b4616427bea6f003780ca11984ddc6..6b553866f639b9e3fab9fd6fb0fe4eeb2968e868 100644 --- a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_failed_jobs.query.graphql +++ b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_failed_jobs.query.graphql @@ -4,13 +4,14 @@ query getPipelineFailedJobs($fullPath: ID!, $pipelineIid: ID!) { pipeline(iid: $pipelineIid) { id active - jobs(statuses: [FAILED], retried: false, jobKind: BUILD) { + jobs(statuses: [FAILED], retried: false) { count nodes { id allowFailure detailedStatus { id + detailsPath group icon action { @@ -19,6 +20,7 @@ query getPipelineFailedJobs($fullPath: ID!, $pipelineIid: ID!) { icon } } + kind name retried retryable @@ -33,7 +35,6 @@ query getPipelineFailedJobs($fullPath: ID!, $pipelineIid: ID!) { readBuild updateBuild } - webPath } } } diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 9b8aa6d91363642df2bac512e3118aadb526ffee..bc68eae008880704b2fe022b0a9efab8c092060b 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -26764,10 +26764,13 @@ msgstr "" msgid "Job|We could not find this element" msgstr "" -msgid "Job|You do not have permission to read this job's log" +msgid "Job|You cannot rerun trigger jobs from this list." msgstr "" -msgid "Job|You do not have permission to retry this job" +msgid "Job|You do not have permission to read this job's log." +msgstr "" + +msgid "Job|You do not have permission to run this job again." msgstr "" msgid "Job|allowed to fail" diff --git a/spec/frontend/pipelines/components/pipelines_list/failure_widget/failed_job_details_spec.js b/spec/frontend/pipelines/components/pipelines_list/failure_widget/failed_job_details_spec.js index 4ba1b82e971e46e19a92566be1989502636c94d2..9cd8ea66797678f84c4b6c84af60944789bb5023 100644 --- a/spec/frontend/pipelines/components/pipelines_list/failure_widget/failed_job_details_spec.js +++ b/spec/frontend/pipelines/components/pipelines_list/failure_widget/failed_job_details_spec.js @@ -8,6 +8,7 @@ import { createAlert } from '~/alert'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import FailedJobDetails from '~/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue'; import RetryMrFailedJobMutation from '~/pipelines/graphql/mutations/retry_mr_failed_job.mutation.graphql'; +import { BRIDGE_KIND } from '~/pipelines/components/graph/constants'; import { job } from './mock'; Vue.use(VueApollo); @@ -94,6 +95,16 @@ describe('FailedJobDetails component', () => { }); }); + describe('when the job is a bridge', () => { + beforeEach(() => { + createComponent({ props: { job: { ...job, kind: BRIDGE_KIND } } }); + }); + + it('disables the retry button', () => { + expect(findRetryButton().props().disabled).toBe(true); + }); + }); + describe('when the job is retryable', () => { describe('and user has permission to update the build', () => { beforeEach(() => { @@ -183,7 +194,7 @@ describe('FailedJobDetails component', () => { it('shows a permission error message', () => { expect(findVisibleJobLog().text()).toBe( - "You do not have permission to read this job's log", + "You do not have permission to read this job's log.", ); }); }); diff --git a/spec/frontend/pipelines/components/pipelines_list/failure_widget/mock.js b/spec/frontend/pipelines/components/pipelines_list/failure_widget/mock.js index b047b57fc3431c32c9d4e5fb38edf1de3a2e2d73..318d787a9840e2f86d261c4edffe3780002aa050 100644 --- a/spec/frontend/pipelines/components/pipelines_list/failure_widget/mock.js +++ b/spec/frontend/pipelines/components/pipelines_list/failure_widget/mock.js @@ -3,17 +3,19 @@ export const job = { allowFailure: false, detailedStatus: { id: 'status', + detailsPath: '/jobs/5241', action: { id: 'action', path: '/retry', icon: 'retry', }, group: 'running', - icon: 'running-icon', + icon: 'status_running_icon', }, name: 'job-name', retried: false, retryable: true, + kind: 'BUILD', stage: { id: '1', name: 'build', @@ -25,7 +27,6 @@ export const job = { readBuild: true, updateBuild: true, }, - webPath: '/', }; export const allowedToFailJob = {