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
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_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
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_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
}
end
# rubocop:disable CodeReuse/ActiveRecord, UsageData/LargeTable
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_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
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
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
......
......@@ -289,9 +289,10 @@ RSpec.describe Gitlab::UsageData do
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: 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)
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(:code_owner_rule, merge_request: merge_request, approvals_required: 3)
create(:code_owner_rule, merge_request: merge_request, approvals_required: 7, section: 'new_section')
......@@ -316,8 +317,11 @@ RSpec.describe Gitlab::UsageData do
end
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_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_with_sectional_code_owner_rules: 2,
merge_requests_with_added_rules: 12,
......@@ -333,8 +337,11 @@ RSpec.describe Gitlab::UsageData do
total_number_of_locked_files: 14
)
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_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_with_sectional_code_owner_rules: 1,
merge_requests_with_added_rules: 6,
......
......@@ -133,11 +133,11 @@ module Gitlab
end
def actual_start(start)
start || @relation.unscope(:group).minimum(@column) || 0
start || @relation.unscope(:group, :having).minimum(@column) || 0
end
def actual_finish(finish)
finish || @relation.unscope(:group).maximum(@column) || 0
finish || @relation.unscope(:group, :having).maximum(@column) || 0
end
def check_mode!(mode)
......
......@@ -39,9 +39,9 @@ module Gitlab
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
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
relation.count
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