Commit 7f72a2b0 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 6d36417e bc216c6b
...@@ -157,7 +157,7 @@ gem 'github-markup', '~> 1.7.0', require: 'github/markup' ...@@ -157,7 +157,7 @@ gem 'github-markup', '~> 1.7.0', require: 'github/markup'
gem 'commonmarker', '~> 0.21' gem 'commonmarker', '~> 0.21'
gem 'kramdown', '~> 2.3.1' gem 'kramdown', '~> 2.3.1'
gem 'RedCloth', '~> 4.3.2' gem 'RedCloth', '~> 4.3.2'
gem 'gitlab-rdoc', '~> 6.3.2', require: 'rdoc' # We need this fork until rdoc releases a new version. See https://gitlab.com/gitlab-org/gitlab/-/issues/334695 gem 'rdoc', '~> 6.3.2'
gem 'org-ruby', '~> 0.9.12' gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0' gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1' gem 'wikicloth', '0.8.1'
...@@ -197,7 +197,7 @@ gem 'acts-as-taggable-on', '~> 7.0' ...@@ -197,7 +197,7 @@ gem 'acts-as-taggable-on', '~> 7.0'
# Background jobs # Background jobs
gem 'sidekiq', '~> 5.2.7' gem 'sidekiq', '~> 5.2.7'
gem 'sidekiq-cron', '~> 1.0' gem 'sidekiq-cron', '~> 1.0'
gem 'redis-namespace', '~> 1.7.0' gem 'redis-namespace', '~> 1.8.1'
gem 'gitlab-sidekiq-fetcher', '0.5.6', require: 'sidekiq-reliable-fetch' gem 'gitlab-sidekiq-fetcher', '0.5.6', require: 'sidekiq-reliable-fetch'
# Cron Parser # Cron Parser
...@@ -229,7 +229,7 @@ gem 'js_regex', '~> 3.4' ...@@ -229,7 +229,7 @@ gem 'js_regex', '~> 3.4'
gem 'device_detector' gem 'device_detector'
# Redis # Redis
gem 'redis', '~> 4.0' gem 'redis', '~> 4.1.4'
gem 'connection_pool', '~> 2.0' gem 'connection_pool', '~> 2.0'
# Redis session store # Redis session store
......
...@@ -499,7 +499,6 @@ GEM ...@@ -499,7 +499,6 @@ GEM
openid_connect (~> 1.2) openid_connect (~> 1.2)
gitlab-pg_query (2.0.4) gitlab-pg_query (2.0.4)
google-protobuf (>= 3.17.1) google-protobuf (>= 3.17.1)
gitlab-rdoc (6.3.2)
gitlab-sidekiq-fetcher (0.5.6) gitlab-sidekiq-fetcher (0.5.6)
sidekiq (~> 5) sidekiq (~> 5)
gitlab-styles (6.2.0) gitlab-styles (6.2.0)
...@@ -1026,11 +1025,12 @@ GEM ...@@ -1026,11 +1025,12 @@ GEM
msgpack (>= 0.4.3) msgpack (>= 0.4.3)
optimist (>= 3.0.0) optimist (>= 3.0.0)
rchardet (1.8.0) rchardet (1.8.0)
rdoc (6.3.2)
re2 (1.2.0) re2 (1.2.0)
recaptcha (4.13.1) recaptcha (4.13.1)
json json
recursive-open-struct (1.1.2) recursive-open-struct (1.1.2)
redis (4.1.3) redis (4.1.4)
redis-actionpack (5.2.0) redis-actionpack (5.2.0)
actionpack (>= 5, < 7) actionpack (>= 5, < 7)
redis-rack (>= 2.1.0, < 3) redis-rack (>= 2.1.0, < 3)
...@@ -1038,7 +1038,7 @@ GEM ...@@ -1038,7 +1038,7 @@ GEM
redis-activesupport (5.2.0) redis-activesupport (5.2.0)
activesupport (>= 3, < 7) activesupport (>= 3, < 7)
redis-store (>= 1.3, < 2) redis-store (>= 1.3, < 2)
redis-namespace (1.7.0) redis-namespace (1.8.1)
redis (>= 3.0.4) redis (>= 3.0.4)
redis-rack (2.1.2) redis-rack (2.1.2)
rack (>= 2.0.8, < 3) rack (>= 2.0.8, < 3)
...@@ -1497,7 +1497,6 @@ DEPENDENCIES ...@@ -1497,7 +1497,6 @@ DEPENDENCIES
gitlab-markup (~> 1.7.1) gitlab-markup (~> 1.7.1)
gitlab-net-dns (~> 0.9.1) gitlab-net-dns (~> 0.9.1)
gitlab-omniauth-openid-connect (~> 0.4.0) gitlab-omniauth-openid-connect (~> 0.4.0)
gitlab-rdoc (~> 6.3.2)
gitlab-sidekiq-fetcher (= 0.5.6) gitlab-sidekiq-fetcher (= 0.5.6)
gitlab-styles (~> 6.2.0) gitlab-styles (~> 6.2.0)
gitlab_chronic_duration (~> 0.10.6.2) gitlab_chronic_duration (~> 0.10.6.2)
...@@ -1607,10 +1606,11 @@ DEPENDENCIES ...@@ -1607,10 +1606,11 @@ DEPENDENCIES
rainbow (~> 3.0) rainbow (~> 3.0)
rblineprof (~> 0.3.6) rblineprof (~> 0.3.6)
rbtrace (~> 0.4) rbtrace (~> 0.4)
rdoc (~> 6.3.2)
re2 (~> 1.2.0) re2 (~> 1.2.0)
recaptcha (~> 4.11) recaptcha (~> 4.11)
redis (~> 4.0) redis (~> 4.1.4)
redis-namespace (~> 1.7.0) redis-namespace (~> 1.8.1)
redis-rails (~> 5.0.2) redis-rails (~> 5.0.2)
request_store (~> 1.5) request_store (~> 1.5)
responders (~> 3.0) responders (~> 3.0)
......
...@@ -56,24 +56,19 @@ $notification-box-shadow-color: rgba(0, 0, 0, 0.25); ...@@ -56,24 +56,19 @@ $notification-box-shadow-color: rgba(0, 0, 0, 0.25);
} }
.flash-alert { .flash-alert {
background-color: $red-100; background-color: $red-50;
color: $red-700;
} }
.flash-notice { .flash-notice {
background-color: $blue-100; background-color: $blue-50;
color: $blue-700;
} }
.flash-success { .flash-success {
background-color: $theme-green-100; background-color: $green-50;
color: $green-700;
} }
.flash-warning { .flash-warning {
background-color: $orange-50; background-color: $orange-50;
color: $gray-900;
cursor: default;
} }
.flash-text, .flash-text,
......
...@@ -9237,6 +9237,7 @@ four standard [pagination arguments](#connection-pagination-arguments): ...@@ -9237,6 +9237,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupcustomemoji"></a>`customEmoji` | [`CustomEmojiConnection`](#customemojiconnection) | Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled. (see [Connections](#connections)) | | <a id="groupcustomemoji"></a>`customEmoji` | [`CustomEmojiConnection`](#customemojiconnection) | Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled. (see [Connections](#connections)) |
| <a id="groupdescription"></a>`description` | [`String`](#string) | Description of the namespace. | | <a id="groupdescription"></a>`description` | [`String`](#string) | Description of the namespace. |
| <a id="groupdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. | | <a id="groupdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| <a id="groupdora"></a>`dora` | [`Dora`](#dora) | The group's DORA metrics. |
| <a id="groupemailsdisabled"></a>`emailsDisabled` | [`Boolean`](#boolean) | Indicates if a group has email notifications disabled. | | <a id="groupemailsdisabled"></a>`emailsDisabled` | [`Boolean`](#boolean) | Indicates if a group has email notifications disabled. |
| <a id="groupepicboards"></a>`epicBoards` | [`EpicBoardConnection`](#epicboardconnection) | Find epic boards. (see [Connections](#connections)) | | <a id="groupepicboards"></a>`epicBoards` | [`EpicBoardConnection`](#epicboardconnection) | Find epic boards. (see [Connections](#connections)) |
| <a id="groupepicsenabled"></a>`epicsEnabled` | [`Boolean`](#boolean) | Indicates if Epics are enabled for namespace. | | <a id="groupepicsenabled"></a>`epicsEnabled` | [`Boolean`](#boolean) | Indicates if Epics are enabled for namespace. |
......
...@@ -86,6 +86,12 @@ module EE ...@@ -86,6 +86,12 @@ module EE
field :billable_members_count, ::GraphQL::INT_TYPE, field :billable_members_count, ::GraphQL::INT_TYPE,
null: true, null: true,
description: 'The number of billable users in the group.' description: 'The number of billable users in the group.'
field :dora,
::Types::DoraType,
null: true,
method: :itself,
description: "The group's DORA metrics."
end end
end end
end end
......
...@@ -74,4 +74,10 @@ RSpec.describe GitlabSchema.types['Group'] do ...@@ -74,4 +74,10 @@ RSpec.describe GitlabSchema.types['Group'] do
expect(vulnerabilities.first['severity']).to eq('CRITICAL') expect(vulnerabilities.first['severity']).to eq('CRITICAL')
end end
end end
describe 'dora field' do
subject { described_class.fields['dora'] }
it { is_expected.to have_graphql_type(Types::DoraType) }
end
end end
...@@ -6,61 +6,103 @@ RSpec.describe 'Query.project(fullPath).dora.metrics' do ...@@ -6,61 +6,103 @@ RSpec.describe 'Query.project(fullPath).dora.metrics' do
include GraphqlHelpers include GraphqlHelpers
let_it_be(:reporter) { create(:user) } let_it_be(:reporter) { create(:user) }
let_it_be(:project) { create(:project) } let_it_be(:group) { create(:group) }
let_it_be(:production) { create(:environment, :production, project: project) } let_it_be(:project_1) { create(:project, group: group) }
let_it_be(:project_2) { create(:project, group: group) }
let(:query) do let_it_be(:project_not_in_group) { create(:project) }
graphql_query_for(:project, { fullPath: project.full_path }, let_it_be(:production_in_project_1) { create(:environment, :production, project: project_1) }
<<~QUERY let_it_be(:staging_in_project_1) { create(:environment, :staging, project: project_1) }
dora { let_it_be(:production_in_project_2) { create(:environment, :production, project: project_2) }
metrics(metric: DEPLOYMENT_FREQUENCY) { let_it_be(:production_not_in_group) { create(:environment, :production, project: project_not_in_group) }
date
value
}
}
QUERY
)
end
let(:post_query) { post_graphql(query, current_user: reporter) } let(:post_query) { post_graphql(query, current_user: reporter) }
let(:path_prefix) { %w[project dora metrics] }
let(:data) { graphql_data.dig(*path_prefix) } let(:data) { graphql_data.dig(*path_prefix) }
let(:query_body) do
<<~QUERY
dora {
metrics(metric: DEPLOYMENT_FREQUENCY) {
date
value
}
}
QUERY
end
around do |example| around do |example|
travel_to '2021-01-08'.to_time do travel_to '2021-02-01'.to_time do
example.run example.run
end end
end end
before_all do before_all do
project.add_reporter(reporter) group.add_reporter(reporter)
create(:dora_daily_metrics, deployment_frequency: 3, environment: production, date: '2021-01-01') create(:dora_daily_metrics, deployment_frequency: 3, environment: production_in_project_1, date: '2021-01-01')
create(:dora_daily_metrics, deployment_frequency: 3, environment: production, date: '2021-01-02') create(:dora_daily_metrics, deployment_frequency: 3, environment: production_in_project_1, date: '2021-01-02')
create(:dora_daily_metrics, deployment_frequency: 2, environment: production, date: '2021-01-03') create(:dora_daily_metrics, deployment_frequency: 2, environment: production_in_project_1, date: '2021-01-03')
create(:dora_daily_metrics, deployment_frequency: 2, environment: production, date: '2021-01-04') create(:dora_daily_metrics, deployment_frequency: 2, environment: production_in_project_1, date: '2021-01-04')
create(:dora_daily_metrics, deployment_frequency: 1, environment: production, date: '2021-01-05') create(:dora_daily_metrics, deployment_frequency: 1, environment: production_in_project_1, date: '2021-01-05')
create(:dora_daily_metrics, deployment_frequency: 1, environment: production, date: '2021-01-06') create(:dora_daily_metrics, deployment_frequency: 1, environment: production_in_project_1, date: '2021-01-06')
create(:dora_daily_metrics, deployment_frequency: nil, environment: production, date: '2021-01-07') create(:dora_daily_metrics, deployment_frequency: nil, environment: production_in_project_1, date: '2021-01-07')
create(:dora_daily_metrics, deployment_frequency: 4, environment: staging_in_project_1, date: '2021-01-08')
create(:dora_daily_metrics, deployment_frequency: 4, environment: production_in_project_2, date: '2021-01-09')
create(:dora_daily_metrics, deployment_frequency: 5, environment: production_not_in_group, date: '2021-01-10')
end end
before do before do
stub_licensed_features(dora4_analytics: true) stub_licensed_features(dora4_analytics: true)
end end
it 'returns the expected DORA metrics' do context 'when querying for project-level metrics' do
post_query let(:path_prefix) { %w[project dora metrics] }
expect(data).to eq( let(:query) do
[ graphql_query_for(:project, { fullPath: project_1.full_path }, query_body)
{ 'value' => 3, 'date' => '2021-01-01' }, end
{ 'value' => 3, 'date' => '2021-01-02' },
{ 'value' => 2, 'date' => '2021-01-03' }, it 'returns the expected project-level DORA metrics' do
{ 'value' => 2, 'date' => '2021-01-04' }, post_query
{ 'value' => 1, 'date' => '2021-01-05' },
{ 'value' => 1, 'date' => '2021-01-06' }, expect(data).to eq(
{ 'value' => nil, 'date' => '2021-01-07' } [
] { 'value' => 3, 'date' => '2021-01-01' },
) { 'value' => 3, 'date' => '2021-01-02' },
{ 'value' => 2, 'date' => '2021-01-03' },
{ 'value' => 2, 'date' => '2021-01-04' },
{ 'value' => 1, 'date' => '2021-01-05' },
{ 'value' => 1, 'date' => '2021-01-06' },
{ 'value' => nil, 'date' => '2021-01-07' }
]
)
end
end
context 'when querying for group-level metrics' do
let(:path_prefix) { %w[group dora metrics] }
let(:query) do
graphql_query_for(:group, { fullPath: group.full_path }, query_body)
end
it 'returns the expected group-level DORA metrics' do
post_query
expect(data).to eq(
[
{ 'value' => 3, 'date' => '2021-01-01' },
{ 'value' => 3, 'date' => '2021-01-02' },
{ 'value' => 2, 'date' => '2021-01-03' },
{ 'value' => 2, 'date' => '2021-01-04' },
{ 'value' => 1, 'date' => '2021-01-05' },
{ 'value' => 1, 'date' => '2021-01-06' },
{ 'value' => nil, 'date' => '2021-01-07' },
{ 'value' => 4, 'date' => '2021-01-09' }
]
)
end
end end
end end
...@@ -276,7 +276,7 @@ RSpec.describe API::StatusChecks do ...@@ -276,7 +276,7 @@ RSpec.describe API::StatusChecks do
it 'paginates correctly' do it 'paginates correctly' do
get api(collection_url, project.owner), params: { per_page: 1 } get api(collection_url, project.owner), params: { per_page: 1 }
expect_paginated_array_response([1]) expect_paginated_array_response([rule.id])
end end
context 'when feature is disabled, unlicensed or user has permission' do context 'when feature is disabled, unlicensed or user has permission' do
......
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