diff --git a/app/assets/javascripts/projects/pipelines/charts/components/app.vue b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
index 25bacc1cc4a3c768832651b9b7d00bc0f6c83d84..7379d5caed7aa98654f8281e48e3a96fe833fd07 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/app.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
@@ -11,12 +11,17 @@ export default {
DeploymentFrequencyCharts: () =>
import('ee_component/dora/components/deployment_frequency_charts.vue'),
LeadTimeCharts: () => import('ee_component/dora/components/lead_time_charts.vue'),
+ ProjectQualitySummary: () => import('ee_component/project_quality_summary/app.vue'),
},
inject: {
shouldRenderDoraCharts: {
type: Boolean,
default: false,
},
+ shouldRenderQualitySummary: {
+ type: Boolean,
+ default: false,
+ },
},
data() {
return {
@@ -31,6 +36,10 @@ export default {
chartsToShow.push('deployment-frequency', 'lead-time');
}
+ if (this.shouldRenderQualitySummary) {
+ chartsToShow.push('project-quality');
+ }
+
return chartsToShow;
},
},
@@ -68,6 +77,9 @@ export default {
+
+
+
diff --git a/app/assets/javascripts/projects/pipelines/charts/index.js b/app/assets/javascripts/projects/pipelines/charts/index.js
index 5f5ee44c2048ddc525d945f6e842a79068cf569e..003b61d94b1baa856d61808dc3cd35dfafdbf450 100644
--- a/app/assets/javascripts/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/projects/pipelines/charts/index.js
@@ -14,6 +14,7 @@ const mountPipelineChartsApp = (el) => {
const { projectPath } = el.dataset;
const shouldRenderDoraCharts = parseBoolean(el.dataset.shouldRenderDoraCharts);
+ const shouldRenderQualitySummary = parseBoolean(el.dataset.shouldRenderQualitySummary);
return new Vue({
el,
@@ -25,6 +26,7 @@ const mountPipelineChartsApp = (el) => {
provide: {
projectPath,
shouldRenderDoraCharts,
+ shouldRenderQualitySummary,
},
render: (createElement) => createElement(ProjectPipelinesCharts, {}),
});
diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb
index 3a94f7d47c22fb6923d4ef86e1b8568e464483f3..45ca820f7b3e7105ec6a97222853707122cdcb75 100644
--- a/app/helpers/graph_helper.rb
+++ b/app/helpers/graph_helper.rb
@@ -26,6 +26,10 @@ def success_ratio(counts)
def should_render_dora_charts
false
end
+
+ def should_render_quality_summary
+ false
+ end
end
GraphHelper.prepend_mod_with('GraphHelper')
diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml
index 992407adf715e2171cd519facef6620a10f17b42..21e871246d72cbe4d4b32d55c411658e86506b88 100644
--- a/app/views/projects/pipelines/charts.html.haml
+++ b/app/views/projects/pipelines/charts.html.haml
@@ -1,4 +1,5 @@
- page_title _('CI/CD Analytics')
#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 } }
diff --git a/ee/app/assets/javascripts/project_quality_summary/app.vue b/ee/app/assets/javascripts/project_quality_summary/app.vue
new file mode 100644
index 0000000000000000000000000000000000000000..3a452daa5be23491555fcb12a921d949b0f3a93d
--- /dev/null
+++ b/ee/app/assets/javascripts/project_quality_summary/app.vue
@@ -0,0 +1,4 @@
+
+
diff --git a/ee/app/helpers/ee/graph_helper.rb b/ee/app/helpers/ee/graph_helper.rb
index a959b4e7fce306f90fee8aed613d85c96a7109e4..81631d776544451a5edfbe813d6cc0be3d0738ac 100644
--- a/ee/app/helpers/ee/graph_helper.rb
+++ b/ee/app/helpers/ee/graph_helper.rb
@@ -12,5 +12,11 @@ def should_render_dora_charts
can?(current_user, :read_dora4_analytics, container)
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
diff --git a/ee/app/models/license.rb b/ee/app/models/license.rb
index ee2e135c47fe7771d4dbd840f8a2b50485a17f31..eb70a00a98a3736cbe619dc751841e8d0b333ac9 100644
--- a/ee/app/models/license.rb
+++ b/ee/app/models/license.rb
@@ -177,6 +177,7 @@ class License < ApplicationRecord
kubernetes_cluster_vulnerabilities
license_scanning
personal_access_token_expiration_policy
+ project_quality_summary
prometheus_alerts
pseudonymizer
quality_management
diff --git a/ee/config/feature_flags/development/project_quality_summary_page.yml b/ee/config/feature_flags/development/project_quality_summary_page.yml
new file mode 100644
index 0000000000000000000000000000000000000000..eac7db4e99f4f862a195c448ac5e6e28b305b5e8
--- /dev/null
+++ b/ee/config/feature_flags/development/project_quality_summary_page.yml
@@ -0,0 +1,8 @@
+---
+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
diff --git a/ee/spec/helpers/ee/graph_helper_spec.rb b/ee/spec/helpers/ee/graph_helper_spec.rb
index 8d59bd1824ab2ca578a5f85c24228e8755b013b8..3ff2635b4a303b8dcfbd5503e9109e3e288565d0 100644
--- a/ee/spec/helpers/ee/graph_helper_spec.rb
+++ b/ee/spec/helpers/ee/graph_helper_spec.rb
@@ -58,4 +58,38 @@
it_behaves_like '#should_render_dora_charts for a specific type of container'
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
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 1720b2be13f7c0490a9a5e0b1337be38311052af..26aaf2fa9c9634ee2b63d4d9fee7b33c35bc3ced 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -28215,6 +28215,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js
index 987a215eb4cccaf1c16189c67585061868805813..b4067f6a72ba7c8ab1105e0c26536156eb69fabf 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js
@@ -11,6 +11,7 @@ jest.mock('~/lib/utils/url_utility');
const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} };
const LeadTimeChartsStub = { name: 'LeadTimeCharts', render: () => {} };
+const ProjectQualitySummaryStub = { name: 'ProjectQualitySummary', render: () => {} };
describe('ProjectsPipelinesChartsApp', () => {
let wrapper;
@@ -23,10 +24,12 @@ describe('ProjectsPipelinesChartsApp', () => {
{
provide: {
shouldRenderDoraCharts: true,
+ shouldRenderQualitySummary: true,
},
stubs: {
DeploymentFrequencyCharts: DeploymentFrequencyChartsStub,
LeadTimeCharts: LeadTimeChartsStub,
+ ProjectQualitySummary: ProjectQualitySummaryStub,
},
},
mountOptions,
@@ -44,6 +47,7 @@ describe('ProjectsPipelinesChartsApp', () => {
const findLeadTimeCharts = () => wrapper.find(LeadTimeChartsStub);
const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub);
const findPipelineCharts = () => wrapper.find(PipelineCharts);
+ const findProjectQualitySummary = () => wrapper.find(ProjectQualitySummaryStub);
describe('when all charts are available', () => {
beforeEach(() => {
@@ -70,6 +74,10 @@ describe('ProjectsPipelinesChartsApp', () => {
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 () => {
let chartsPath;
setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`);
@@ -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(() => {
- createComponent({ provide: { shouldRenderDoraCharts: false } });
+ createComponent({
+ provide: { shouldRenderDoraCharts: false, shouldRenderQualitySummary: false },
+ });
});
it('does not render tabs', () => {
@@ -176,4 +186,14 @@ describe('ProjectsPipelinesChartsApp', () => {
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);
+ });
+ });
});
diff --git a/spec/helpers/graph_helper_spec.rb b/spec/helpers/graph_helper_spec.rb
index 0930417accb8da7266b615d5e0f854778911236a..a5d4e1313e11727509582471d33cac2de13d8bfc 100644
--- a/spec/helpers/graph_helper_spec.rb
+++ b/spec/helpers/graph_helper_spec.rb
@@ -27,4 +27,16 @@
expect(should_render_dora_charts).to be(false)
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