Commit 58f27851 authored by Adam Hegyi's avatar Adam Hegyi

Use aggregated DORA API for DF

Use aggregated DORA API for deployment frequency and count in VSA.
parent 4cd14988
...@@ -35,6 +35,10 @@ module Dora ...@@ -35,6 +35,10 @@ module Dora
return error(_('Container must be a project or a group.'), :bad_request) return error(_('Container must be a project or a group.'), :bad_request)
end end
if group_project_ids.present? && !group?
return error(_('The group_project_ids parameter is only allowed for a group'), :bad_request)
end
unless ::Dora::DailyMetrics::AVAILABLE_INTERVALS.include?(interval) unless ::Dora::DailyMetrics::AVAILABLE_INTERVALS.include?(interval)
return error(_("The interval must be one of %{intervals}.") % { intervals: ::Dora::DailyMetrics::AVAILABLE_INTERVALS.join(',') }, return error(_("The interval must be one of %{intervals}.") % { intervals: ::Dora::DailyMetrics::AVAILABLE_INTERVALS.join(',') },
:bad_request) :bad_request)
...@@ -72,7 +76,9 @@ module Dora ...@@ -72,7 +76,9 @@ module Dora
# - In the subsequent projects, the assigned role at the group-level # - In the subsequent projects, the assigned role at the group-level
# can't be lowered. For example, if the user is reporter at group-level, # can't be lowered. For example, if the user is reporter at group-level,
# the user can be developer in subsequent projects, but can't be guest. # the user can be developer in subsequent projects, but can't be guest.
container.all_projects projects = container.all_projects
projects = projects.id_in(group_project_ids) if group_project_ids.any?
projects
end end
end end
...@@ -103,5 +109,9 @@ module Dora ...@@ -103,5 +109,9 @@ module Dora
def metric def metric
params[:metric] params[:metric]
end end
def group_project_ids
Array(params[:group_project_ids])
end
end end
end end
---
name: dora_deployment_frequency_in_vsa
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60367
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329178
milestone: '13.12'
type: development
group: group::optimize
default_enabled: false
...@@ -18,9 +18,16 @@ module Gitlab ...@@ -18,9 +18,16 @@ module Gitlab
private private
# rubocop: disable CodeReuse/ActiveRecord
def deployments_count def deployments_count
@deployments_count ||= begin @deployments_count ||= if Feature.enabled?(:dora_deployment_frequency_in_vsa)
deployment_count_via_dora_api
else
deployment_count_via_finder
end
end
# rubocop: disable CodeReuse/ActiveRecord
def deployment_count_via_finder
deployments = DeploymentsFinder deployments = DeploymentsFinder
.new(group: group, finished_after: options[:from], finished_before: options[:to], status: :success) .new(group: group, finished_after: options[:from], finished_before: options[:to], status: :success)
.execute .execute
...@@ -28,8 +35,31 @@ module Gitlab ...@@ -28,8 +35,31 @@ module Gitlab
deployments = deployments.where(project_id: options[:projects]) if options[:projects].present? deployments = deployments.where(project_id: options[:projects]) if options[:projects].present?
deployments.count deployments.count
end end
end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
def deployment_count_via_dora_api
result = Dora::AggregateMetricsService.new(
container: group,
current_user: options[:current_user],
params: dora_aggregate_metrics_params
).execute
result[:status] == :success ? (result[:data] || 0) : 0
end
def dora_aggregate_metrics_params
params = {
start_date: options[:from].to_date,
end_date: (options[:to] || Date.today).to_date,
interval: 'all',
environment_tier: 'production',
metric: 'deployment_frequency'
}
params[:group_project_ids] = options[:projects] if options[:projects].present?
params
end
end end
end end
end end
......
...@@ -127,13 +127,38 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d ...@@ -127,13 +127,38 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d
end end
end end
def create_deployment(args)
project = args[:project]
environment = project.environments.production.first || create(:environment, :production, project: project)
create(:deployment, :success, args.merge(environment: environment))
# this is needed for the dora_deployment_frequency_in_vsa feature flag so we have aggregated data
::Dora::DailyMetrics::RefreshWorker.new.perform(environment.id, Time.current.to_date.to_s)
end
shared_examples 'VSA deployment related metrics' do
describe "#deploys" do describe "#deploys" do
let(:current_time) { Time.current }
let(:one_day_ago) { current_time - 1.day }
let(:two_days_ago) { current_time - 2.days }
let(:five_days_ago) { current_time - 5.days }
let(:ten_days_ago) { current_time - 10.days }
context 'with from date' do context 'with from date' do
subject { described_class.new(group, options: { from: two_days_ago, current_user: user }).data }
before do before do
travel_to(5.days.ago) { create(:deployment, :success, project: project, finished_at: Time.zone.now) } stub_licensed_features(dora4_analytics: true)
travel_to(5.days.from_now) { create(:deployment, :success, project: project, finished_at: Time.zone.now) }
travel_to(5.days.ago) { create(:deployment, :success, project: project_2, finished_at: Time.zone.now) } travel_to(five_days_ago) do
travel_to(5.days.from_now) { create(:deployment, :success, project: project_2, finished_at: Time.zone.now) } create_deployment(project: project, finished_at: Time.current)
create_deployment(project: project_2, finished_at: Time.current)
end
travel_to(current_time) do
create_deployment(project: project, finished_at: Time.current)
create_deployment(project: project_2, finished_at: Time.current)
end
end end
it "finds the number of deploys made created after it" do it "finds the number of deploys made created after it" do
...@@ -148,8 +173,8 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d ...@@ -148,8 +173,8 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d
context 'with subgroups' do context 'with subgroups' do
before do before do
travel_to(5.days.from_now) do travel_to(current_time) do
create(:deployment, :success, finished_at: Time.zone.now, project: create(:project, :repository, namespace: create(:group, parent: group))) create_deployment(project: project, finished_at: Time.current)
end end
end end
...@@ -160,12 +185,12 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d ...@@ -160,12 +185,12 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d
context 'with projects specified in options' do context 'with projects specified in options' do
before do before do
travel_to(5.days.from_now) do travel_to(Date.today) do
create(:deployment, :success, finished_at: Time.zone.now, project: create(:project, :repository, namespace: group, name: 'not_applicable')) create_deployment(finished_at: current_time, project: create(:project, :repository, namespace: group, name: 'not_applicable'))
end end
end end
subject { described_class.new(group, options: { from: Time.now, current_user: user, projects: [project.id, project_2.id] }).data } subject { described_class.new(group, options: { from: one_day_ago, current_user: user, projects: [project.id, project_2.id] }).data }
it 'shows deploys from those projects' do it 'shows deploys from those projects' do
expect(subject.second[:value]).to eq('2') expect(subject.second[:value]).to eq('2')
...@@ -173,7 +198,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d ...@@ -173,7 +198,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d
end end
context 'when `from` and `to` parameters are provided' do context 'when `from` and `to` parameters are provided' do
subject { described_class.new(group, options: { from: 10.days.ago, to: Time.now, current_user: user }).data } subject { described_class.new(group, options: { from: ten_days_ago, to: one_day_ago, current_user: user }).data }
it 'finds deployments from 5 days ago' do it 'finds deployments from 5 days ago' do
expect(subject.second[:value]).to eq('2') expect(subject.second[:value]).to eq('2')
...@@ -183,8 +208,8 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d ...@@ -183,8 +208,8 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d
context 'with other projects' do context 'with other projects' do
before do before do
travel_to(5.days.from_now) do travel_to(one_day_ago) do
create(:deployment, :success, finished_at: Time.zone.now, project: create(:project, :repository, namespace: create(:group))) create_deployment(finished_at: Time.current, project: create(:project, :repository, namespace: create(:group)))
end end
end end
...@@ -194,7 +219,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d ...@@ -194,7 +219,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d
end end
describe '#deployment_frequency' do describe '#deployment_frequency' do
let(:from) { 6.days.ago } let(:from) { ten_days_ago }
let(:to) { nil } let(:to) { nil }
subject do subject do
...@@ -210,8 +235,10 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d ...@@ -210,8 +235,10 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d
end end
before do before do
travel_to(5.days.ago) do stub_licensed_features(dora4_analytics: true)
create(:deployment, :success, finished_at: Time.zone.now, project: project)
travel_to(five_days_ago) do
create_deployment(finished_at: Time.current, project: project)
end end
end end
...@@ -223,12 +250,12 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d ...@@ -223,12 +250,12 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d
end end
context 'when `to` is given' do context 'when `to` is given' do
let(:from) { 10.days.ago } let(:from) { ten_days_ago }
let(:to) { 10.days.from_now } let(:to) { 10.days.from_now }
before do before do
travel_to(5.days.from_now) do travel_to(Date.yesterday) do
create(:deployment, :success, finished_at: Time.zone.now, project: project) create_deployment(finished_at: Time.current, project: project)
end end
end end
...@@ -239,4 +266,25 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d ...@@ -239,4 +266,25 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Summary::Group::StageSummary d
end end
end end
end end
end
context 'when dora_deployment_frequency_in_vsa feature flag is enabled' do
before do
stub_feature_flags(dora_deployment_frequency_in_vsa: true)
expect(Dora::AggregateMetricsService).to receive(:new).and_call_original
end
it_behaves_like 'VSA deployment related metrics'
end
context 'when dora_deployment_frequency_in_vsa feature flag is disabled' do
before do
stub_feature_flags(dora_deployment_frequency_in_vsa: false)
expect(Dora::AggregateMetricsService).not_to receive(:new)
end
it_behaves_like 'VSA deployment related metrics'
end
end end
...@@ -27,8 +27,13 @@ RSpec.describe Analytics::CycleAnalytics::GroupLevel do ...@@ -27,8 +27,13 @@ RSpec.describe Analytics::CycleAnalytics::GroupLevel do
describe '#summary' do describe '#summary' do
before do before do
stub_licensed_features(dora4_analytics: true)
create_cycle(user, project, issue, mr, milestone, pipeline) create_cycle(user, project, issue, mr, milestone, pipeline)
deploy_master(user, project) deploy_master(user, project)
environment = project.environments.production.first
::Dora::DailyMetrics::RefreshWorker.new.perform(environment.id, pipeline.created_at.to_date.to_s)
end end
it 'returns medians for each stage for a specific group' do it 'returns medians for each stage for a specific group' do
......
...@@ -144,6 +144,15 @@ RSpec.describe Dora::AggregateMetricsService do ...@@ -144,6 +144,15 @@ RSpec.describe Dora::AggregateMetricsService do
expect(subject[:data]).to eq([{ Time.current.to_date.to_s => 1, 'date' => Time.current.to_date.to_s, 'value' => 1 }]) expect(subject[:data]).to eq([{ Time.current.to_date.to_s => 1, 'date' => Time.current.to_date.to_s, 'value' => 1 }])
end end
end end
context 'when group_project_ids parameter is given' do
let(:extra_params) { { interval: Dora::DailyMetrics::INTERVAL_ALL, group_project_ids: [1] } }
it_behaves_like 'request failure' do
let(:message) { 'The group_project_ids parameter is only allowed for a group' }
let(:http_status) { :bad_request }
end
end
end end
context 'when container is a group' do context 'when container is a group' do
...@@ -196,6 +205,15 @@ RSpec.describe Dora::AggregateMetricsService do ...@@ -196,6 +205,15 @@ RSpec.describe Dora::AggregateMetricsService do
expect(subject[:data]).to eq(3) expect(subject[:data]).to eq(3)
end end
end end
context 'when group_project_ids parameter is given' do
let(:extra_params) { { interval: Dora::DailyMetrics::INTERVAL_ALL, group_project_ids: [project_2.id] } }
it 'returns the aggregated data' do
expect(subject[:status]).to eq(:success)
expect(subject[:data]).to eq(1)
end
end
end end
context 'when container is nil' do context 'when container is nil' do
......
...@@ -31862,6 +31862,9 @@ msgstr "" ...@@ -31862,6 +31862,9 @@ msgstr ""
msgid "The group will be placed in 'pending removal' state" msgid "The group will be placed in 'pending removal' state"
msgstr "" msgstr ""
msgid "The group_project_ids parameter is only allowed for a group"
msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination." msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "" msgstr ""
......
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