Commit 56ef10a6 authored by Igor Drozdov's avatar Igor Drozdov

Add approval rules with approvers to usage ping

It adds the number of:

- Number of required approvals = Number of eligible approvers
- Number of required approvals < Number of eligible approvers
- Number of required approvals > Number of eligible approvers
parent 09e608d8
---
title: Add approval rules with approvers to usage ping
merge_request: 36737
author:
type: added
# frozen_string_literal: true
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddIndicesToApprovalProjectRules < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
RULE_TYPE_INDEX_NAME = 'index_approval_project_rules_on_id_with_regular_type'
RULE_ID_INDEX_NAME = 'index_approval_project_rules_users_on_approval_project_rule_id'
def up
add_concurrent_index :approval_project_rules, :id, where: 'rule_type = 0', name: RULE_TYPE_INDEX_NAME
add_concurrent_index :approval_project_rules_users, :approval_project_rule_id, name: RULE_ID_INDEX_NAME
end
def down
remove_concurrent_index :approval_project_rules, :id, where: 'rule_type = 0', name: RULE_TYPE_INDEX_NAME
remove_concurrent_index :approval_project_rules_users, :approval_project_rule_id, name: RULE_ID_INDEX_NAME
end
end
dd630c76819641ad64a5f6ae40ad4f49e7fbe1c783398d97886dc7e9852a245e
\ No newline at end of file
...@@ -19448,6 +19448,8 @@ CREATE UNIQUE INDEX index_approval_project_rules_groups_1 ON approval_project_ru ...@@ -19448,6 +19448,8 @@ CREATE UNIQUE INDEX index_approval_project_rules_groups_1 ON approval_project_ru
CREATE INDEX index_approval_project_rules_groups_2 ON approval_project_rules_groups USING btree (group_id); CREATE INDEX index_approval_project_rules_groups_2 ON approval_project_rules_groups USING btree (group_id);
CREATE INDEX index_approval_project_rules_on_id_with_regular_type ON approval_project_rules USING btree (id) WHERE (rule_type = 0);
CREATE INDEX index_approval_project_rules_on_project_id ON approval_project_rules USING btree (project_id); CREATE INDEX index_approval_project_rules_on_project_id ON approval_project_rules USING btree (project_id);
CREATE INDEX index_approval_project_rules_on_rule_type ON approval_project_rules USING btree (rule_type); CREATE INDEX index_approval_project_rules_on_rule_type ON approval_project_rules USING btree (rule_type);
...@@ -19460,6 +19462,8 @@ CREATE UNIQUE INDEX index_approval_project_rules_users_1 ON approval_project_rul ...@@ -19460,6 +19462,8 @@ CREATE UNIQUE INDEX index_approval_project_rules_users_1 ON approval_project_rul
CREATE INDEX index_approval_project_rules_users_2 ON approval_project_rules_users USING btree (user_id); CREATE INDEX index_approval_project_rules_users_2 ON approval_project_rules_users USING btree (user_id);
CREATE INDEX index_approval_project_rules_users_on_approval_project_rule_id ON approval_project_rules_users USING btree (approval_project_rule_id);
CREATE UNIQUE INDEX index_approval_rule_name_for_code_owners_rule_type ON approval_merge_request_rules USING btree (merge_request_id, name) WHERE ((rule_type = 2) AND (section IS NULL)); CREATE UNIQUE INDEX index_approval_rule_name_for_code_owners_rule_type ON approval_merge_request_rules USING btree (merge_request_id, name) WHERE ((rule_type = 2) AND (section IS NULL));
CREATE UNIQUE INDEX index_approval_rule_name_for_sectional_code_owners_rule_type ON approval_merge_request_rules USING btree (merge_request_id, name, section) WHERE (rule_type = 2); CREATE UNIQUE INDEX index_approval_rule_name_for_sectional_code_owners_rule_type ON approval_merge_request_rules USING btree (merge_request_id, name, section) WHERE (rule_type = 2);
......
...@@ -102,13 +102,28 @@ module EE ...@@ -102,13 +102,28 @@ module EE
} }
end end
# rubocop:disable CodeReuse/ActiveRecord, UsageData/LargeTable
def approval_rules_counts def approval_rules_counts
approval_project_rules_with_users =
ApprovalProjectRule
.regular
.joins('INNER JOIN approval_project_rules_users ON approval_project_rules_users.approval_project_rule_id = approval_project_rules.id')
.group(:id)
{ {
approval_project_rules: count(ApprovalProjectRule), approval_project_rules: count(ApprovalProjectRule),
approval_project_rules_with_target_branch: count(ApprovalProjectRulesProtectedBranch, :approval_project_rule_id) approval_project_rules_with_target_branch: count(ApprovalProjectRulesProtectedBranch, :approval_project_rule_id),
approval_project_rules_with_more_approvers_than_required: count_approval_rules_with_users(approval_project_rules_with_users.having('COUNT(approval_project_rules_users) > approvals_required')),
approval_project_rules_with_less_approvers_than_required: count_approval_rules_with_users(approval_project_rules_with_users.having('COUNT(approval_project_rules_users) < approvals_required')),
approval_project_rules_with_exact_required_approvers: count_approval_rules_with_users(approval_project_rules_with_users.having('COUNT(approval_project_rules_users) = approvals_required'))
} }
end end
def count_approval_rules_with_users(relation)
count(relation, batch_size: 10_000, start: ApprovalProjectRule.regular.minimum(:id), finish: ApprovalProjectRule.regular.maximum(:id)).size
end
# rubocop:enable CodeReuse/ActiveRecord, UsageData/LargeTable
def security_products_usage def security_products_usage
results = SECURE_PRODUCT_TYPES.each_with_object({}) do |(secure_type, attribs), response| results = SECURE_PRODUCT_TYPES.each_with_object({}) do |(secure_type, attribs), response|
response[attribs[:name]] = count(::Ci::Build.where(name: secure_type)) # rubocop:disable CodeReuse/ActiveRecord response[attribs[:name]] = count(::Ci::Build.where(name: secure_type)) # rubocop:disable CodeReuse/ActiveRecord
......
...@@ -289,9 +289,10 @@ RSpec.describe Gitlab::UsageData do ...@@ -289,9 +289,10 @@ RSpec.describe Gitlab::UsageData do
create(:project, creator: user) create(:project, creator: user)
create(:project, creator: user, disable_overriding_approvers_per_merge_request: true) create(:project, creator: user, disable_overriding_approvers_per_merge_request: true)
create(:project, creator: user, disable_overriding_approvers_per_merge_request: false) create(:project, creator: user, disable_overriding_approvers_per_merge_request: false)
create(:approval_project_rule, project: project) create(:approval_project_rule, project: project, users: create_list(:user, 2), approvals_required: 1)
create(:approval_project_rule, project: project, users: [create(:user)], approvals_required: 1)
protected_branch = create(:protected_branch, project: project) protected_branch = create(:protected_branch, project: project)
create(:approval_project_rule, protected_branches: [protected_branch], project: project) create(:approval_project_rule, protected_branches: [protected_branch], users: [create(:user)], approvals_required: 2, project: project)
create(:suggestion, note: create(:note, project: project)) create(:suggestion, note: create(:note, project: project))
create(:code_owner_rule, merge_request: merge_request, approvals_required: 3) create(:code_owner_rule, merge_request: merge_request, approvals_required: 3)
create(:code_owner_rule, merge_request: merge_request, approvals_required: 7, section: 'new_section') create(:code_owner_rule, merge_request: merge_request, approvals_required: 7, section: 'new_section')
...@@ -316,8 +317,11 @@ RSpec.describe Gitlab::UsageData do ...@@ -316,8 +317,11 @@ RSpec.describe Gitlab::UsageData do
end end
expect(described_class.usage_activity_by_stage_create({})).to include( expect(described_class.usage_activity_by_stage_create({})).to include(
approval_project_rules: 6, approval_project_rules: 8,
approval_project_rules_with_target_branch: 2, approval_project_rules_with_target_branch: 2,
approval_project_rules_with_more_approvers_than_required: 2,
approval_project_rules_with_less_approvers_than_required: 2,
approval_project_rules_with_exact_required_approvers: 2,
projects_enforcing_code_owner_approval: 0, projects_enforcing_code_owner_approval: 0,
projects_with_sectional_code_owner_rules: 2, projects_with_sectional_code_owner_rules: 2,
merge_requests_with_added_rules: 12, merge_requests_with_added_rules: 12,
...@@ -333,8 +337,11 @@ RSpec.describe Gitlab::UsageData do ...@@ -333,8 +337,11 @@ RSpec.describe Gitlab::UsageData do
total_number_of_locked_files: 14 total_number_of_locked_files: 14
) )
expect(described_class.usage_activity_by_stage_create(described_class.last_28_days_time_period)).to include( expect(described_class.usage_activity_by_stage_create(described_class.last_28_days_time_period)).to include(
approval_project_rules: 6, approval_project_rules: 8,
approval_project_rules_with_target_branch: 2, approval_project_rules_with_target_branch: 2,
approval_project_rules_with_more_approvers_than_required: 2,
approval_project_rules_with_less_approvers_than_required: 2,
approval_project_rules_with_exact_required_approvers: 2,
projects_enforcing_code_owner_approval: 0, projects_enforcing_code_owner_approval: 0,
projects_with_sectional_code_owner_rules: 1, projects_with_sectional_code_owner_rules: 1,
merge_requests_with_added_rules: 6, merge_requests_with_added_rules: 6,
......
...@@ -133,11 +133,11 @@ module Gitlab ...@@ -133,11 +133,11 @@ module Gitlab
end end
def actual_start(start) def actual_start(start)
start || @relation.unscope(:group).minimum(@column) || 0 start || @relation.unscope(:group, :having).minimum(@column) || 0
end end
def actual_finish(finish) def actual_finish(finish)
finish || @relation.unscope(:group).maximum(@column) || 0 finish || @relation.unscope(:group, :having).maximum(@column) || 0
end end
def check_mode!(mode) def check_mode!(mode)
......
...@@ -39,9 +39,9 @@ module Gitlab ...@@ -39,9 +39,9 @@ module Gitlab
FALLBACK = -1 FALLBACK = -1
def count(relation, column = nil, batch: true, start: nil, finish: nil) def count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
if batch if batch
Gitlab::Database::BatchCount.batch_count(relation, column, start: start, finish: finish) Gitlab::Database::BatchCount.batch_count(relation, column, batch_size: batch_size, start: start, finish: finish)
else else
relation.count relation.count
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