Commit a76602c9 authored by Scott Hampton's avatar Scott Hampton

Merge branch '341972-create-project-quality-summary-page' into 'master'

Add blank Project Quality tab to project CI/CD analytics

See merge request gitlab-org/gitlab!72724
parents abe8a30c 1fa5509a
...@@ -11,12 +11,17 @@ export default { ...@@ -11,12 +11,17 @@ export default {
DeploymentFrequencyCharts: () => DeploymentFrequencyCharts: () =>
import('ee_component/dora/components/deployment_frequency_charts.vue'), import('ee_component/dora/components/deployment_frequency_charts.vue'),
LeadTimeCharts: () => import('ee_component/dora/components/lead_time_charts.vue'), LeadTimeCharts: () => import('ee_component/dora/components/lead_time_charts.vue'),
ProjectQualitySummary: () => import('ee_component/project_quality_summary/app.vue'),
}, },
inject: { inject: {
shouldRenderDoraCharts: { shouldRenderDoraCharts: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
shouldRenderQualitySummary: {
type: Boolean,
default: false,
},
}, },
data() { data() {
return { return {
...@@ -31,6 +36,10 @@ export default { ...@@ -31,6 +36,10 @@ export default {
chartsToShow.push('deployment-frequency', 'lead-time'); chartsToShow.push('deployment-frequency', 'lead-time');
} }
if (this.shouldRenderQualitySummary) {
chartsToShow.push('project-quality');
}
return chartsToShow; return chartsToShow;
}, },
}, },
...@@ -68,6 +77,9 @@ export default { ...@@ -68,6 +77,9 @@ export default {
<lead-time-charts /> <lead-time-charts />
</gl-tab> </gl-tab>
</template> </template>
<gl-tab v-if="shouldRenderQualitySummary" :title="s__('QualitySummary|Project quality')">
<project-quality-summary />
</gl-tab>
</gl-tabs> </gl-tabs>
<pipeline-charts v-else /> <pipeline-charts v-else />
</div> </div>
......
...@@ -14,6 +14,7 @@ const mountPipelineChartsApp = (el) => { ...@@ -14,6 +14,7 @@ const mountPipelineChartsApp = (el) => {
const { projectPath } = el.dataset; const { projectPath } = el.dataset;
const shouldRenderDoraCharts = parseBoolean(el.dataset.shouldRenderDoraCharts); const shouldRenderDoraCharts = parseBoolean(el.dataset.shouldRenderDoraCharts);
const shouldRenderQualitySummary = parseBoolean(el.dataset.shouldRenderQualitySummary);
return new Vue({ return new Vue({
el, el,
...@@ -25,6 +26,7 @@ const mountPipelineChartsApp = (el) => { ...@@ -25,6 +26,7 @@ const mountPipelineChartsApp = (el) => {
provide: { provide: {
projectPath, projectPath,
shouldRenderDoraCharts, shouldRenderDoraCharts,
shouldRenderQualitySummary,
}, },
render: (createElement) => createElement(ProjectPipelinesCharts, {}), render: (createElement) => createElement(ProjectPipelinesCharts, {}),
}); });
......
...@@ -26,6 +26,10 @@ module GraphHelper ...@@ -26,6 +26,10 @@ module GraphHelper
def should_render_dora_charts def should_render_dora_charts
false false
end end
def should_render_quality_summary
false
end
end end
GraphHelper.prepend_mod_with('GraphHelper') GraphHelper.prepend_mod_with('GraphHelper')
- page_title _('CI/CD Analytics') - page_title _('CI/CD Analytics')
#js-project-pipelines-charts-app{ data: { project_path: @project.full_path, #js-project-pipelines-charts-app{ data: { project_path: @project.full_path,
should_render_dora_charts: should_render_dora_charts.to_s } } should_render_dora_charts: should_render_dora_charts.to_s,
should_render_quality_summary: should_render_quality_summary.to_s } }
<script>
export default {};
</script>
<template><div></div></template>
...@@ -12,5 +12,11 @@ module EE ...@@ -12,5 +12,11 @@ module EE
can?(current_user, :read_dora4_analytics, container) can?(current_user, :read_dora4_analytics, container)
end end
override :should_render_quality_summary
def should_render_quality_summary
@project.feature_available?(:project_quality_summary) &&
::Feature.enabled?(:project_quality_summary_page, @project, default_enabled: :yaml)
end
end end
end end
...@@ -177,6 +177,7 @@ class License < ApplicationRecord ...@@ -177,6 +177,7 @@ class License < ApplicationRecord
kubernetes_cluster_vulnerabilities kubernetes_cluster_vulnerabilities
license_scanning license_scanning
personal_access_token_expiration_policy personal_access_token_expiration_policy
project_quality_summary
prometheus_alerts prometheus_alerts
pseudonymizer pseudonymizer
quality_management quality_management
......
---
name: project_quality_summary_page
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72724
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343687
milestone: '14.4'
type: development
group: group::testing
default_enabled: false
...@@ -58,4 +58,38 @@ RSpec.describe EE::GraphHelper do ...@@ -58,4 +58,38 @@ RSpec.describe EE::GraphHelper do
it_behaves_like '#should_render_dora_charts for a specific type of container' it_behaves_like '#should_render_dora_charts for a specific type of container'
end end
end end
describe '#should_render_quality_summary' do
subject { helper.should_render_quality_summary }
before do
self.instance_variable_set(:@project, project)
end
context 'when licensed feature is available' do
before do
stub_licensed_features(project_quality_summary: true)
end
context 'when feature flag is enabled' do
it { is_expected.to eq(true) }
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(project_quality_summary_page: false)
end
it { is_expected.to eq(false) }
end
end
context 'when licensed feature is not available' do
before do
stub_licensed_features(project_quality_summary: false)
end
it { is_expected.to eq(false) }
end
end
end end
...@@ -28215,6 +28215,9 @@ msgstr "" ...@@ -28215,6 +28215,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}" msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr "" msgstr ""
msgid "QualitySummary|Project quality"
msgstr ""
msgid "Quarters" msgid "Quarters"
msgstr "" msgstr ""
......
...@@ -11,6 +11,7 @@ jest.mock('~/lib/utils/url_utility'); ...@@ -11,6 +11,7 @@ jest.mock('~/lib/utils/url_utility');
const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} }; const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} };
const LeadTimeChartsStub = { name: 'LeadTimeCharts', render: () => {} }; const LeadTimeChartsStub = { name: 'LeadTimeCharts', render: () => {} };
const ProjectQualitySummaryStub = { name: 'ProjectQualitySummary', render: () => {} };
describe('ProjectsPipelinesChartsApp', () => { describe('ProjectsPipelinesChartsApp', () => {
let wrapper; let wrapper;
...@@ -23,10 +24,12 @@ describe('ProjectsPipelinesChartsApp', () => { ...@@ -23,10 +24,12 @@ describe('ProjectsPipelinesChartsApp', () => {
{ {
provide: { provide: {
shouldRenderDoraCharts: true, shouldRenderDoraCharts: true,
shouldRenderQualitySummary: true,
}, },
stubs: { stubs: {
DeploymentFrequencyCharts: DeploymentFrequencyChartsStub, DeploymentFrequencyCharts: DeploymentFrequencyChartsStub,
LeadTimeCharts: LeadTimeChartsStub, LeadTimeCharts: LeadTimeChartsStub,
ProjectQualitySummary: ProjectQualitySummaryStub,
}, },
}, },
mountOptions, mountOptions,
...@@ -44,6 +47,7 @@ describe('ProjectsPipelinesChartsApp', () => { ...@@ -44,6 +47,7 @@ describe('ProjectsPipelinesChartsApp', () => {
const findLeadTimeCharts = () => wrapper.find(LeadTimeChartsStub); const findLeadTimeCharts = () => wrapper.find(LeadTimeChartsStub);
const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub); const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub);
const findPipelineCharts = () => wrapper.find(PipelineCharts); const findPipelineCharts = () => wrapper.find(PipelineCharts);
const findProjectQualitySummary = () => wrapper.find(ProjectQualitySummaryStub);
describe('when all charts are available', () => { describe('when all charts are available', () => {
beforeEach(() => { beforeEach(() => {
...@@ -70,6 +74,10 @@ describe('ProjectsPipelinesChartsApp', () => { ...@@ -70,6 +74,10 @@ describe('ProjectsPipelinesChartsApp', () => {
expect(findLeadTimeCharts().exists()).toBe(true); expect(findLeadTimeCharts().exists()).toBe(true);
}); });
it('renders the project quality summary', () => {
expect(findProjectQualitySummary().exists()).toBe(true);
});
it('sets the tab and url when a tab is clicked', async () => { it('sets the tab and url when a tab is clicked', async () => {
let chartsPath; let chartsPath;
setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`); setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`);
...@@ -163,9 +171,11 @@ describe('ProjectsPipelinesChartsApp', () => { ...@@ -163,9 +171,11 @@ describe('ProjectsPipelinesChartsApp', () => {
}); });
}); });
describe('when the dora charts are not available', () => { describe('when the dora charts are not available and project quality summary is not available', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ provide: { shouldRenderDoraCharts: false } }); createComponent({
provide: { shouldRenderDoraCharts: false, shouldRenderQualitySummary: false },
});
}); });
it('does not render tabs', () => { it('does not render tabs', () => {
...@@ -176,4 +186,14 @@ describe('ProjectsPipelinesChartsApp', () => { ...@@ -176,4 +186,14 @@ describe('ProjectsPipelinesChartsApp', () => {
expect(findPipelineCharts().exists()).toBe(true); expect(findPipelineCharts().exists()).toBe(true);
}); });
}); });
describe('when the project quality summary is not available', () => {
beforeEach(() => {
createComponent({ provide: { shouldRenderQualitySummary: false } });
});
it('does not render the tab', () => {
expect(findProjectQualitySummary().exists()).toBe(false);
});
});
}); });
...@@ -27,4 +27,16 @@ RSpec.describe GraphHelper do ...@@ -27,4 +27,16 @@ RSpec.describe GraphHelper do
expect(should_render_dora_charts).to be(false) expect(should_render_dora_charts).to be(false)
end end
end end
describe '#should_render_quality_summary' do
let(:project) { create(:project, :private) }
before do
self.instance_variable_set(:@project, project)
end
it 'always returns false' do
expect(should_render_quality_summary).to be(false)
end
end
end end
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