From 4c377392bf15fadbce962592e62fb8fccceeb7a3 Mon Sep 17 00:00:00 2001 From: Jose Ivan Vargas <jvargas@gitlab.com> Date: Tue, 23 Jul 2024 21:59:29 +0000 Subject: [PATCH] Change Troubleshoot button position This moves the Troubleshoot button from the top bar of the job logs to the bottom just underneath the log itself --- .../components/root_cause_analysis_button.vue | 4 ++ .../javascripts/ci/job_details/job_app.vue | 14 ++++- .../components/job_log_top_bar.vue | 34 +----------- .../components/root_cause_analysis_button.vue | 52 +++++++++++++++++++ .../root_cause_analysis_button_spec.js | 45 ++++++++++++++++ qa/qa/ee/page/project/job/show.rb | 2 +- 6 files changed, 117 insertions(+), 34 deletions(-) create mode 100644 app/assets/javascripts/ci/job_details/components/root_cause_analysis_button.vue create mode 100644 ee/app/assets/javascripts/ci/job_details/components/root_cause_analysis_button.vue create mode 100644 ee/spec/frontend/ci/job_details/components/root_cause_analysis_button_spec.js diff --git a/app/assets/javascripts/ci/job_details/components/root_cause_analysis_button.vue b/app/assets/javascripts/ci/job_details/components/root_cause_analysis_button.vue new file mode 100644 index 0000000000000..ad7d4c52ee6bf --- /dev/null +++ b/app/assets/javascripts/ci/job_details/components/root_cause_analysis_button.vue @@ -0,0 +1,4 @@ +<template> + <!--NOOP in FOSS--> + <div></div> +</template> diff --git a/app/assets/javascripts/ci/job_details/job_app.vue b/app/assets/javascripts/ci/job_details/job_app.vue index 36f61da79f0fd..ed6daa0a43ab4 100644 --- a/app/assets/javascripts/ci/job_details/job_app.vue +++ b/app/assets/javascripts/ci/job_details/job_app.vue @@ -5,7 +5,10 @@ import { throttle, isEmpty } from 'lodash'; // eslint-disable-next-line no-restricted-imports import { mapGetters, mapState, mapActions } from 'vuex'; import JobLogTopBar from 'ee_else_ce/ci/job_details/components/job_log_top_bar.vue'; +import RootCauseAnalysisButton from 'ee_else_ce/ci/job_details/components/root_cause_analysis_button.vue'; import SafeHtml from '~/vue_shared/directives/safe_html'; +import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import glAbilitiesMixin from '~/vue_shared/mixins/gl_abilities_mixin'; import { isScrolledToBottom } from '~/lib/utils/scroll_utils'; import { __, sprintf } from '~/locale'; import delayedJobMixin from '~/ci/mixins/delayed_job_mixin'; @@ -29,6 +32,7 @@ export default { GlIcon, Log, JobLogTopBar, + RootCauseAnalysisButton, StuckBlock, UnmetPrerequisitesBlock, Sidebar, @@ -39,7 +43,7 @@ export default { directives: { SafeHtml, }, - mixins: [delayedJobMixin], + mixins: [delayedJobMixin, glAbilitiesMixin(), glFeatureFlagMixin()], props: { artifactHelpUrl: { type: String, @@ -132,6 +136,13 @@ export default { jobConfirmationMessage() { return this.job.status?.action?.confirmation_message; }, + jobFailed() { + const { status } = this.job; + + const failedGroups = ['failed', 'failed-with-warnings']; + + return failedGroups.includes(status.group); + }, }, watch: { // Once the job log is loaded, @@ -314,6 +325,7 @@ export default { @exitFullscreen="exitFullscreen" /> <log :search-results="searchResults" /> + <root-cause-analysis-button :job-failed="jobFailed" /> </div> <!-- EO job log --> diff --git a/ee/app/assets/javascripts/ci/job_details/components/job_log_top_bar.vue b/ee/app/assets/javascripts/ci/job_details/components/job_log_top_bar.vue index 3741d8fd5afe8..db73cebcce6aa 100644 --- a/ee/app/assets/javascripts/ci/job_details/components/job_log_top_bar.vue +++ b/ee/app/assets/javascripts/ci/job_details/components/job_log_top_bar.vue @@ -2,13 +2,10 @@ import { GlButton } from '@gitlab/ui'; // eslint-disable-next-line no-restricted-imports import { mapState } from 'vuex'; -import glAbilitiesMixin from '~/vue_shared/mixins/gl_abilities_mixin'; -import { sendDuoChatCommand } from 'ee/ai/utils'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { convertToGraphQLId } from '~/graphql_shared/utils'; import { TYPENAME_CI_BUILD } from '~/graphql_shared/constants'; import CeJobLogTopBar from '~/ci/job_details/components/job_log_top_bar.vue'; -import { duoChatGlobalState } from '~/super_sidebar/constants'; import RootCauseAnalysis from './sidebar/root_cause_analysis/root_cause_analysis_app.vue'; export default { @@ -17,7 +14,7 @@ export default { GlButton, RootCauseAnalysis, }, - mixins: [glAbilitiesMixin(), glFeatureFlagMixin()], + mixins: [glFeatureFlagMixin()], inject: ['aiRootCauseAnalysisAvailable', 'duoFeaturesEnabled', 'jobGid'], props: { size: { @@ -78,15 +75,6 @@ export default { !this.glFeatures.rootCauseAnalysisDuo ); }, - rootCauseAnalysisDuoIsAvailable() { - return ( - this.glFeatures.aiBuildFailureCause && - this.aiRootCauseAnalysisAvailable && - this.duoFeaturesEnabled && - this.glFeatures.rootCauseAnalysisDuo && - this.glAbilities.troubleshootJobWithAi - ); - }, jobFailed() { const { status } = this.job; @@ -97,9 +85,6 @@ export default { jobId() { return convertToGraphQLId(TYPENAME_CI_BUILD, this.job.id); }, - duoDrawerOpen() { - return duoChatGlobalState.isShown; - }, ...mapState(['job', 'isLoading']), }, methods: { @@ -121,12 +106,6 @@ export default { handleExitFullscreen() { this.$emit('exitFullscreen'); }, - callDuo() { - sendDuoChatCommand({ - question: '/troubleshoot', - resourceId: this.jobId, - }); - }, }, }; </script> @@ -158,6 +137,7 @@ export default { @exitFullscreen="handleExitFullscreen" > <template #controllers> + <!-- TODO: Remove the previous implementation of the RCA drawer https://gitlab.com/gitlab-org/gitlab/-/issues/473797 --> <gl-button v-if="rootCauseAnalysisIsAvailable && jobFailed" icon="tanuki-ai" @@ -167,16 +147,6 @@ export default { > {{ s__('Jobs|Troubleshoot') }} </gl-button> - <gl-button - v-if="rootCauseAnalysisDuoIsAvailable && jobFailed" - :disabled="duoDrawerOpen" - icon="tanuki-ai" - class="gl-mr-3" - data-testid="rca-duo-button" - @click="callDuo" - > - {{ s__('Jobs|Troubleshoot') }} - </gl-button> </template> </ce-job-log-top-bar> </div> diff --git a/ee/app/assets/javascripts/ci/job_details/components/root_cause_analysis_button.vue b/ee/app/assets/javascripts/ci/job_details/components/root_cause_analysis_button.vue new file mode 100644 index 0000000000000..26105bfde663d --- /dev/null +++ b/ee/app/assets/javascripts/ci/job_details/components/root_cause_analysis_button.vue @@ -0,0 +1,52 @@ +<script> +import { GlButton } from '@gitlab/ui'; +import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import glAbilitiesMixin from '~/vue_shared/mixins/gl_abilities_mixin'; +import { sendDuoChatCommand } from 'ee/ai/utils'; + +export default { + components: { + GlButton, + }, + mixins: [glAbilitiesMixin(), glFeatureFlagMixin()], + inject: ['aiRootCauseAnalysisAvailable', 'duoFeaturesEnabled', 'jobGid'], + props: { + jobFailed: { + type: Boolean, + required: false, + default: false, + }, + }, + computed: { + rootCauseAnalysisDuoIsAvailable() { + return ( + this.glFeatures.aiBuildFailureCause && + this.aiRootCauseAnalysisAvailable && + this.duoFeaturesEnabled && + this.glFeatures.rootCauseAnalysisDuo && + this.glAbilities.troubleshootJobWithAi + ); + }, + }, + methods: { + callDuo() { + sendDuoChatCommand({ + question: '/troubleshoot', + resourceId: this.jobGid, + }); + }, + }, +}; +</script> +<template> + <gl-button + v-if="rootCauseAnalysisDuoIsAvailable && jobFailed" + icon="tanuki-ai" + class="gl-mr-3" + variant="confirm" + data-testid="rca-duo-button" + @click="callDuo" + > + {{ s__('Jobs|Troubleshoot') }} + </gl-button> +</template> diff --git a/ee/spec/frontend/ci/job_details/components/root_cause_analysis_button_spec.js b/ee/spec/frontend/ci/job_details/components/root_cause_analysis_button_spec.js new file mode 100644 index 0000000000000..3d82614bedf89 --- /dev/null +++ b/ee/spec/frontend/ci/job_details/components/root_cause_analysis_button_spec.js @@ -0,0 +1,45 @@ +import RootCauseAnalysisButton from 'ee/ci/job_details/components/root_cause_analysis_button.vue'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; + +describe('Root cause analysis button', () => { + let wrapper; + + const defaultProps = { + jobFailed: true, + }; + + const createComponent = (props) => { + wrapper = shallowMountExtended(RootCauseAnalysisButton, { + propsData: { + ...defaultProps, + ...props, + }, + provide: { + aiRootCauseAnalysisAvailable: true, + duoFeaturesEnabled: true, + glFeatures: { + aiBuildFailureCause: true, + rootCauseAnalysisDuo: true, + }, + glAbilities: { + troubleshootJobWithAi: true, + }, + jobGid: 'gid://gitlab/Ci::Build/123', + }, + }); + }; + + const findTroubleshootButton = () => wrapper.findByTestId('rca-duo-button'); + + it('should display the Troubleshoot button', () => { + createComponent(); + + expect(findTroubleshootButton().exists()).toBe(true); + }); + + it('should not display the Troubleshoot button when no failure is detected', () => { + createComponent({ jobFailed: false }); + + expect(findTroubleshootButton().exists()).toBe(false); + }); +}); diff --git a/qa/qa/ee/page/project/job/show.rb b/qa/qa/ee/page/project/job/show.rb index c96bab64f46f3..58783d030f0c8 100644 --- a/qa/qa/ee/page/project/job/show.rb +++ b/qa/qa/ee/page/project/job/show.rb @@ -12,7 +12,7 @@ def self.prepended(base) super base.class_eval do - view 'ee/app/assets/javascripts/ci/job_details/components/job_log_top_bar.vue' do + view 'ee/app/assets/javascripts/ci/job_details/components/root_cause_analysis_button.vue' do element 'rca-duo-button' end end -- GitLab