Commit 448531bd authored by Dheeraj Joshi's avatar Dheeraj Joshi Committed by Kushal Pandya

Improve language when MR Security Report is outdated

This is an attempt to improve message for an Outdated
security report and also provide direct link to run
a new pipeline for target branch
parent eda4dc77
...@@ -180,6 +180,7 @@ export default class MergeRequestStore { ...@@ -180,6 +180,7 @@ export default class MergeRequestStore {
this.mergeRequestAddCiConfigPath = data.merge_request_add_ci_config_path; this.mergeRequestAddCiConfigPath = data.merge_request_add_ci_config_path;
this.pipelinesEmptySvgPath = data.pipelines_empty_svg_path; this.pipelinesEmptySvgPath = data.pipelines_empty_svg_path;
this.humanAccess = data.human_access; this.humanAccess = data.human_access;
this.newPipelinePath = data.new_project_pipeline_path;
} }
get isNothingToMergeState() { get isNothingToMergeState() {
......
...@@ -64,6 +64,10 @@ class MergeRequestWidgetEntity < Grape::Entity ...@@ -64,6 +64,10 @@ class MergeRequestWidgetEntity < Grape::Entity
merge_request.project.team.human_max_access(current_user&.id) merge_request.project.team.human_max_access(current_user&.id)
end end
expose :new_project_pipeline_path do |merge_request|
new_project_pipeline_path(merge_request.project)
end
# Rendering and redacting Markdown can be expensive. These links are # Rendering and redacting Markdown can be expensive. These links are
# just nice to have in the merge request widget, so only # just nice to have in the merge request widget, so only
# include them if they are explicitly requested on first load. # include them if they are explicitly requested on first load.
......
...@@ -328,6 +328,8 @@ export default { ...@@ -328,6 +328,8 @@ export default {
:can-dismiss-vulnerability="mr.canDismissVulnerability" :can-dismiss-vulnerability="mr.canDismissVulnerability"
:diverged-commits-count="mr.divergedCommitsCount" :diverged-commits-count="mr.divergedCommitsCount"
:mr-state="mr.state" :mr-state="mr.state"
:target-branch-tree-path="mr.targetBranchTreePath"
:new-pipeline-path="mr.newPipelinePath"
class="js-security-widget" class="js-security-widget"
/> />
<mr-widget-licenses <mr-widget-licenses
......
...@@ -9,7 +9,7 @@ import Icon from '~/vue_shared/components/icon.vue'; ...@@ -9,7 +9,7 @@ import Icon from '~/vue_shared/components/icon.vue';
import IssueModal from './components/modal.vue'; import IssueModal from './components/modal.vue';
import securityReportsMixin from './mixins/security_report_mixin'; import securityReportsMixin from './mixins/security_report_mixin';
import createStore from './store'; import createStore from './store';
import { s__, sprintf } from '~/locale'; import { GlSprintf, GlLink } from '@gitlab/ui';
import { mrStates } from '~/mr_popover/constants'; import { mrStates } from '~/mr_popover/constants';
export default { export default {
...@@ -20,6 +20,8 @@ export default { ...@@ -20,6 +20,8 @@ export default {
IssuesList, IssuesList,
IssueModal, IssueModal,
Icon, Icon,
GlSprintf,
GlLink,
}, },
mixins: [securityReportsMixin, glFeatureFlagsMixin()], mixins: [securityReportsMixin, glFeatureFlagsMixin()],
props: { props: {
...@@ -124,6 +126,16 @@ export default { ...@@ -124,6 +126,16 @@ export default {
required: false, required: false,
default: null, default: null,
}, },
targetBranchTreePath: {
type: String,
required: false,
default: '',
},
newPipelinePath: {
type: String,
required: false,
default: '',
},
}, },
componentNames, componentNames,
computed: { computed: {
...@@ -164,25 +176,12 @@ export default { ...@@ -164,25 +176,12 @@ export default {
hasSastReports() { hasSastReports() {
return this.enabledReports.sast; return this.enabledReports.sast;
}, },
subHeadingText() {
const isMRBranchOutdated = this.divergedCommitsCount > 0;
if (isMRBranchOutdated) {
return sprintf(
s__(
'Security report is out of date. Please incorporate latest changes from %{targetBranchName}',
),
{
targetBranchName: this.targetBranch,
},
);
}
return sprintf(
s__('Security report is out of date. Retry the pipeline for the target branch.'),
);
},
isMRActive() { isMRActive() {
return this.mrState !== mrStates.merged && this.mrState !== mrStates.closed; return this.mrState !== mrStates.merged && this.mrState !== mrStates.closed;
}, },
isMRBranchOutdated() {
return this.divergedCommitsCount > 0;
},
}, },
created() { created() {
...@@ -294,7 +293,36 @@ export default { ...@@ -294,7 +293,36 @@ export default {
<template v-if="isMRActive && isBaseSecurityReportOutOfDate" #subHeading> <template v-if="isMRActive && isBaseSecurityReportOutOfDate" #subHeading>
<div class="text-secondary-700 text-1"> <div class="text-secondary-700 text-1">
<span>{{ subHeadingText }}</span> <gl-sprintf
v-if="isMRBranchOutdated"
:message="
__(
'Security report is out of date. Please update your branch with the latest changes from the target branch (%{targetBranchName})',
)
"
>
<template #targetBranchName>
<gl-link class="text-1" :href="targetBranchTreePath">{{ targetBranch }}</gl-link>
</template>
</gl-sprintf>
<gl-sprintf
v-else
:message="
__(
'Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})',
)
"
>
<template #newPipelineLink="{ content }">
<gl-link class="text-1" :href="`${newPipelinePath}?ref=${targetBranch}`">{{
content
}}</gl-link>
</template>
<template #targetBranchName>
<gl-link class="text-1" :href="targetBranchTreePath">{{ targetBranch }}</gl-link>
</template>
</gl-sprintf>
</div> </div>
</template> </template>
......
---
title: Improve language when MR Security Report is outdated
merge_request: 26150
author:
type: changed
...@@ -395,7 +395,7 @@ describe('Grouped security reports app', () => { ...@@ -395,7 +395,7 @@ describe('Grouped security reports app', () => {
it('should display out of date message', () => { it('should display out of date message', () => {
expect(wrapper.vm.$el.textContent).toContain( expect(wrapper.vm.$el.textContent).toContain(
'Security report is out of date. Retry the pipeline for the target branch', 'Security report is out of date. Run a new pipeline for the target branch (master)',
); );
}); });
}); });
...@@ -407,7 +407,7 @@ describe('Grouped security reports app', () => { ...@@ -407,7 +407,7 @@ describe('Grouped security reports app', () => {
it('should display out of date message', () => { it('should display out of date message', () => {
expect(wrapper.vm.$el.textContent).toContain( expect(wrapper.vm.$el.textContent).toContain(
'Security report is out of date. Please incorporate latest changes from master', 'Security report is out of date. Please update your branch with the latest changes from the target branch (master)',
); );
}); });
}); });
......
...@@ -17201,10 +17201,10 @@ msgstr "" ...@@ -17201,10 +17201,10 @@ msgstr ""
msgid "Security dashboard" msgid "Security dashboard"
msgstr "" msgstr ""
msgid "Security report is out of date. Please incorporate latest changes from %{targetBranchName}" msgid "Security report is out of date. Please update your branch with the latest changes from the target branch (%{targetBranchName})"
msgstr "" msgstr ""
msgid "Security report is out of date. Retry the pipeline for the target branch." msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr "" msgstr ""
msgid "SecurityConfiguration|Configured" msgid "SecurityConfiguration|Configured"
......
...@@ -37,6 +37,7 @@ export default { ...@@ -37,6 +37,7 @@ export default {
target_project_id: 19, target_project_id: 19,
target_project_full_path: '/group2/project2', target_project_full_path: '/group2/project2',
merge_request_add_ci_config_path: '/group2/project2/new/pipeline', merge_request_add_ci_config_path: '/group2/project2/new/pipeline',
new_project_pipeline_path: '/group2/project2/pipelines/new',
metrics: { metrics: {
merged_by: { merged_by: {
name: 'Administrator', name: 'Administrator',
......
...@@ -102,5 +102,11 @@ describe('MergeRequestStore', () => { ...@@ -102,5 +102,11 @@ describe('MergeRequestStore', () => {
expect(store.pipelinesEmptySvgPath).toBe('/path/to/svg'); expect(store.pipelinesEmptySvgPath).toBe('/path/to/svg');
}); });
it('should set newPipelinePath', () => {
store.setData({ ...mockData });
expect(store.newPipelinePath).toBe('/group2/project2/pipelines/new');
});
}); });
}); });
...@@ -162,6 +162,13 @@ describe MergeRequestWidgetEntity do ...@@ -162,6 +162,13 @@ describe MergeRequestWidgetEntity do
.to eq('Maintainer') .to eq('Maintainer')
end end
it 'has new pipeline path for project' do
project.add_maintainer(user)
expect(subject[:new_project_pipeline_path])
.to eq("/#{resource.project.full_path}/pipelines/new")
end
describe 'when source project is deleted' do describe 'when source project is deleted' do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:forked_project) { fork_project(project) } let(:forked_project) { fork_project(project) }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment