From 4a6f62173cc002bd2a664a8e6697d0cf863dec22 Mon Sep 17 00:00:00 2001 From: Arturo Herrero Date: Fri, 28 Aug 2020 13:17:21 +0100 Subject: [PATCH] Propagate instance-level integration to groups In https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32331 we introduced the propagation of instance-level integrations to projects. After adding the group_id column to the services table https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38499 we can now save integrations that belongs to a group https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39959. This propagate instance-level integration settings to groups. --- app/models/data_list.rb | 10 ++++--- app/models/service.rb | 2 +- app/models/service_list.rb | 11 ++++---- .../admin/propagate_integration_service.rb | 26 +++++++++++++++++++ .../concerns/admin/propagate_service.rb | 8 +++--- .../propagate_integration_service_spec.rb | 7 ++++- 6 files changed, 49 insertions(+), 15 deletions(-) diff --git a/app/models/data_list.rb b/app/models/data_list.rb index 12011cb17f718b..2cee34478861df 100644 --- a/app/models/data_list.rb +++ b/app/models/data_list.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true class DataList - def initialize(batch, data_fields_hash, klass) - @batch = batch + def initialize(batch_ids, data_fields_hash, klass) + @batch_ids = batch_ids @data_fields_hash = data_fields_hash @klass = klass end @@ -13,13 +13,15 @@ def to_array private - attr_reader :batch, :data_fields_hash, :klass + attr_reader :batch_ids, :data_fields_hash, :klass def columns data_fields_hash.keys << 'service_id' end def values - batch.map { |row| data_fields_hash.values << row['id'] } + batch_ids.map do |row| + data_fields_hash.values << row['id'] + end end end diff --git a/app/models/service.rb b/app/models/service.rb index f2da6905674844..b24de874105560 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -310,7 +310,7 @@ def json_fields end def to_service_hash - as_json(methods: :type, except: %w[id template instance project_id]) + as_json(methods: :type, except: %w[id template instance project_id group_id]) end def to_data_fields_hash diff --git a/app/models/service_list.rb b/app/models/service_list.rb index 2a75567d5ffd3b..9cbc5e680591ad 100644 --- a/app/models/service_list.rb +++ b/app/models/service_list.rb @@ -1,9 +1,10 @@ # frozen_string_literal: true class ServiceList - def initialize(batch_ids, service_hash) + def initialize(batch_ids, service_hash, association) @batch_ids = batch_ids @service_hash = service_hash + @association = association end def to_array @@ -12,15 +13,15 @@ def to_array private - attr_reader :batch_ids, :service_hash + attr_reader :batch_ids, :service_hash, :association def columns - (service_hash.keys << 'project_id') + (service_hash.keys << "#{association}_id") end def values - batch_ids.map do |project_id| - (service_hash.values << project_id) + batch_ids.map do |id| + (service_hash.values << id) end end end diff --git a/app/services/admin/propagate_integration_service.rb b/app/services/admin/propagate_integration_service.rb index 3c27454ffc7a88..34d6008cb6a6a8 100644 --- a/app/services/admin/propagate_integration_service.rb +++ b/app/services/admin/propagate_integration_service.rb @@ -6,6 +6,8 @@ class PropagateIntegrationService def propagate update_inherited_integrations + + create_integration_for_groups_without_integration if Feature.enabled?(:group_level_integrations) create_integration_for_projects_without_integration end @@ -38,9 +40,33 @@ def bulk_update_from_integration(batch) end # rubocop: enable CodeReuse/ActiveRecord + def create_integration_for_groups_without_integration + loop do + batch = Group.uncached { group_ids_without_integration(integration, BATCH_SIZE) } + + bulk_create_from_integration(batch, 'group') unless batch.empty? + + break if batch.size < BATCH_SIZE + end + end + def service_hash @service_hash ||= integration.to_service_hash .tap { |json| json['inherit_from_id'] = integration.id } end + + # rubocop:disable CodeReuse/ActiveRecord + def group_ids_without_integration(integration, limit) + services = Service + .select('1') + .where('services.group_id = namespaces.id') + .where(type: integration.type) + + Group + .where('NOT EXISTS (?)', services) + .limit(limit) + .pluck(:id) + end + # rubocop:enable CodeReuse/ActiveRecord end end diff --git a/app/services/concerns/admin/propagate_service.rb b/app/services/concerns/admin/propagate_service.rb index c7a4bfaa4cac96..974408f678c1b2 100644 --- a/app/services/concerns/admin/propagate_service.rb +++ b/app/services/concerns/admin/propagate_service.rb @@ -26,14 +26,14 @@ def create_integration_for_projects_without_integration loop do batch_ids = Project.uncached { Project.ids_without_integration(integration, BATCH_SIZE) } - bulk_create_from_integration(batch_ids) unless batch_ids.empty? + bulk_create_from_integration(batch_ids, 'project') unless batch_ids.empty? break if batch_ids.size < BATCH_SIZE end end - def bulk_create_from_integration(batch_ids) - service_list = ServiceList.new(batch_ids, service_hash).to_array + def bulk_create_from_integration(batch_ids, association) + service_list = ServiceList.new(batch_ids, service_hash, association).to_array Service.transaction do results = bulk_insert(*service_list) @@ -44,7 +44,7 @@ def bulk_create_from_integration(batch_ids) bulk_insert(*data_list) end - run_callbacks(batch_ids) + run_callbacks(batch_ids) if association == 'project' end end diff --git a/spec/services/admin/propagate_integration_service_spec.rb b/spec/services/admin/propagate_integration_service_spec.rb index 8b895cfb44925e..49d974b7154251 100644 --- a/spec/services/admin/propagate_integration_service_spec.rb +++ b/spec/services/admin/propagate_integration_service_spec.rb @@ -10,8 +10,9 @@ stub_jira_service_test end - let(:excluded_attributes) { %w[id project_id inherit_from_id instance created_at updated_at default] } + let(:excluded_attributes) { %w[id project_id group_id inherit_from_id instance created_at updated_at default] } let!(:project) { create(:project) } + let!(:group) { create(:group) } let!(:instance_integration) do JiraService.create!( instance: true, @@ -109,6 +110,10 @@ it_behaves_like 'inherits settings from integration' do let(:integration) { project.jira_service } end + + it_behaves_like 'inherits settings from integration' do + let(:integration) { Service.find_by(group_id: group.id) } + end end it 'updates project#has_external_issue_tracker for issue tracker services' do -- GitLab