Commit 8a30ee45 authored by Kerri Miller's avatar Kerri Miller

Merge branch 'propagate-group-level-integrations' into 'master'

Propagate group-level integrations

See merge request gitlab-org/gitlab!44023
parents c94aa77f c6d58ae4
...@@ -7,8 +7,13 @@ module Admin ...@@ -7,8 +7,13 @@ module Admin
def propagate def propagate
update_inherited_integrations update_inherited_integrations
if integration.instance?
create_integration_for_groups_without_integration if Feature.enabled?(:group_level_integrations) create_integration_for_groups_without_integration if Feature.enabled?(:group_level_integrations)
create_integration_for_projects_without_integration create_integration_for_projects_without_integration
else
create_integration_for_groups_without_integration_belonging_to_group
create_integration_for_projects_without_integration_belonging_to_group
end
end end
private private
...@@ -28,5 +33,19 @@ module Admin ...@@ -28,5 +33,19 @@ module Admin
PropagateIntegrationGroupWorker.perform_async(integration.id, min_id, max_id) PropagateIntegrationGroupWorker.perform_async(integration.id, min_id, max_id)
end end
end end
def create_integration_for_groups_without_integration_belonging_to_group
integration.group.descendants.without_integration(integration).each_batch(of: BATCH_SIZE) do |groups|
min_id, max_id = groups.pick("MIN(namespaces.id), MAX(namespaces.id)")
PropagateIntegrationGroupWorker.perform_async(integration.id, min_id, max_id)
end
end
def create_integration_for_projects_without_integration_belonging_to_group
Project.without_integration(integration).in_namespace(integration.group.self_and_descendants).each_batch(of: BATCH_SIZE) do |projects|
min_id, max_id = projects.pick("MIN(projects.id), MAX(projects.id)")
PropagateIntegrationProjectWorker.perform_async(integration.id, min_id, max_id)
end
end
end end
end end
...@@ -11,7 +11,13 @@ class PropagateIntegrationGroupWorker ...@@ -11,7 +11,13 @@ class PropagateIntegrationGroupWorker
integration = Service.find_by_id(integration_id) integration = Service.find_by_id(integration_id)
return unless integration return unless integration
batch = Group.where(id: min_id..max_id).without_integration(integration) batch = if integration.instance?
Group.where(id: min_id..max_id).without_integration(integration)
else
integration.group.descendants.where(id: min_id..max_id).without_integration(integration)
end
return if batch.empty?
BulkCreateIntegrationService.new(integration, batch, 'group').execute BulkCreateIntegrationService.new(integration, batch, 'group').execute
end end
......
...@@ -12,6 +12,9 @@ class PropagateIntegrationProjectWorker ...@@ -12,6 +12,9 @@ class PropagateIntegrationProjectWorker
return unless integration return unless integration
batch = Project.where(id: min_id..max_id).without_integration(integration) batch = Project.where(id: min_id..max_id).without_integration(integration)
batch = batch.in_namespace(integration.group.self_and_descendants) if integration.group_id
return if batch.empty?
BulkCreateIntegrationService.new(integration, batch, 'project').execute BulkCreateIntegrationService.new(integration, batch, 'project').execute
end end
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Integration do RSpec.describe Integration do
let!(:project_1) { create(:project) } let_it_be(:project_1) { create(:project) }
let!(:project_2) { create(:project) } let_it_be(:project_2) { create(:project) }
let!(:project_3) { create(:project) } let_it_be(:project_3) { create(:project) }
let(:instance_integration) { create(:jira_service, :instance) } let_it_be(:instance_integration) { create(:jira_service, :instance) }
before do before do
create(:jira_service, project: project_1, inherit_from_id: instance_integration.id) create(:jira_service, project: project_1, inherit_from_id: instance_integration.id)
......
...@@ -10,56 +10,16 @@ RSpec.describe Admin::PropagateIntegrationService do ...@@ -10,56 +10,16 @@ RSpec.describe Admin::PropagateIntegrationService do
stub_jira_service_test stub_jira_service_test
end end
let_it_be(:project) { create(:project) } let(:group) { create(:group) }
let!(:instance_integration) do
JiraService.create!(
instance: true,
active: true,
push_events: true,
url: 'http://update-jira.instance.com',
username: 'user',
password: 'secret'
)
end
let!(:inherited_integration) do
JiraService.create!(
project: create(:project),
inherit_from_id: instance_integration.id,
instance: false,
active: true,
push_events: false,
url: 'http://jira.instance.com',
username: 'user',
password: 'secret'
)
end
let!(:not_inherited_integration) do let_it_be(:project) { create(:project) }
JiraService.create!( let_it_be(:instance_integration) { create(:jira_service, :instance) }
project: project, let_it_be(:not_inherited_integration) { create(:jira_service, project: project) }
inherit_from_id: nil, let_it_be(:inherited_integration) do
instance: false, create(:jira_service, project: create(:project), inherit_from_id: instance_integration.id)
active: true,
push_events: false,
url: 'http://jira.instance.com',
username: 'user',
password: 'secret'
)
end end
let_it_be(:different_type_inherited_integration) do
let!(:different_type_inherited_integration) do create(:redmine_service, project: project, inherit_from_id: instance_integration.id)
BambooService.create!(
project: project,
inherit_from_id: instance_integration.id,
instance: false,
active: true,
push_events: false,
bamboo_url: 'http://gitlab.com',
username: 'mic',
password: 'password',
build_key: 'build'
)
end end
context 'with inherited integration' do context 'with inherited integration' do
...@@ -74,7 +34,7 @@ RSpec.describe Admin::PropagateIntegrationService do ...@@ -74,7 +34,7 @@ RSpec.describe Admin::PropagateIntegrationService do
end end
context 'with a project without integration' do context 'with a project without integration' do
let!(:another_project) { create(:project) } let(:another_project) { create(:project) }
it 'calls to PropagateIntegrationProjectWorker' do it 'calls to PropagateIntegrationProjectWorker' do
expect(PropagateIntegrationProjectWorker).to receive(:perform_async) expect(PropagateIntegrationProjectWorker).to receive(:perform_async)
...@@ -85,8 +45,6 @@ RSpec.describe Admin::PropagateIntegrationService do ...@@ -85,8 +45,6 @@ RSpec.describe Admin::PropagateIntegrationService do
end end
context 'with a group without integration' do context 'with a group without integration' do
let!(:group) { create(:group) }
it 'calls to PropagateIntegrationProjectWorker' do it 'calls to PropagateIntegrationProjectWorker' do
expect(PropagateIntegrationGroupWorker).to receive(:perform_async) expect(PropagateIntegrationGroupWorker).to receive(:perform_async)
.with(instance_integration.id, group.id, group.id) .with(instance_integration.id, group.id, group.id)
...@@ -94,5 +52,31 @@ RSpec.describe Admin::PropagateIntegrationService do ...@@ -94,5 +52,31 @@ RSpec.describe Admin::PropagateIntegrationService do
described_class.propagate(instance_integration) described_class.propagate(instance_integration)
end end
end end
context 'for a group-level integration' do
let(:group_integration) { create(:jira_service, group: group, project: nil) }
context 'with a project without integration' do
let(:another_project) { create(:project, group: group) }
it 'calls to PropagateIntegrationProjectWorker' do
expect(PropagateIntegrationProjectWorker).to receive(:perform_async)
.with(group_integration.id, another_project.id, another_project.id)
described_class.propagate(group_integration)
end
end
context 'with a group without integration' do
let(:subgroup) { create(:group, parent: group) }
it 'calls to PropagateIntegrationGroupWorker' do
expect(PropagateIntegrationGroupWorker).to receive(:perform_async)
.with(group_integration.id, subgroup.id, subgroup.id)
described_class.propagate(group_integration)
end
end
end
end end
end end
...@@ -4,33 +4,40 @@ require 'spec_helper' ...@@ -4,33 +4,40 @@ require 'spec_helper'
RSpec.describe PropagateIntegrationGroupWorker do RSpec.describe PropagateIntegrationGroupWorker do
describe '#perform' do describe '#perform' do
let_it_be(:group1) { create(:group) } let_it_be(:group) { create(:group) }
let_it_be(:group2) { create(:group) } let_it_be(:another_group) { create(:group) }
let_it_be(:subgroup1) { create(:group, parent: group) }
let_it_be(:subgroup2) { create(:group, parent: group) }
let_it_be(:integration) { create(:redmine_service, :instance) } let_it_be(:integration) { create(:redmine_service, :instance) }
let(:job_args) { [integration.id, group.id, subgroup2.id] }
before do it_behaves_like 'an idempotent worker' do
allow(BulkCreateIntegrationService).to receive(:new) it 'calls to BulkCreateIntegrationService' do
.with(integration, match_array([group1, group2]), 'group') expect(BulkCreateIntegrationService).to receive(:new)
.with(integration, match_array([group, another_group, subgroup1, subgroup2]), 'group').twice
.and_return(double(execute: nil)) .and_return(double(execute: nil))
subject
end end
it_behaves_like 'an idempotent worker' do context 'with a group integration' do
let(:job_args) { [integration.id, group1.id, group2.id] } let_it_be(:integration) { create(:redmine_service, group: group, project: nil) }
it 'calls to BulkCreateIntegrationService' do it 'calls to BulkCreateIntegrationService' do
expect(BulkCreateIntegrationService).to receive(:new) expect(BulkCreateIntegrationService).to receive(:new)
.with(integration, match_array([group1, group2]), 'group') .with(integration, match_array([subgroup1, subgroup2]), 'group').twice
.and_return(double(execute: nil)) .and_return(double(execute: nil))
subject subject
end end
end end
end
context 'with an invalid integration id' do context 'with an invalid integration id' do
it 'returns without failure' do it 'returns without failure' do
expect(BulkCreateIntegrationService).not_to receive(:new) expect(BulkCreateIntegrationService).not_to receive(:new)
subject.perform(0, group1.id, group2.id) subject.perform(0, 1, 100)
end end
end end
end end
......
...@@ -9,18 +9,12 @@ RSpec.describe PropagateIntegrationInheritWorker do ...@@ -9,18 +9,12 @@ RSpec.describe PropagateIntegrationInheritWorker do
let_it_be(:integration2) { create(:bugzilla_service, inherit_from_id: integration.id) } let_it_be(:integration2) { create(:bugzilla_service, inherit_from_id: integration.id) }
let_it_be(:integration3) { create(:redmine_service) } let_it_be(:integration3) { create(:redmine_service) }
before do
allow(BulkUpdateIntegrationService).to receive(:new)
.with(integration, match_array(integration1))
.and_return(double(execute: nil))
end
it_behaves_like 'an idempotent worker' do it_behaves_like 'an idempotent worker' do
let(:job_args) { [integration.id, integration1.id, integration3.id] } let(:job_args) { [integration.id, integration1.id, integration3.id] }
it 'calls to BulkCreateIntegrationService' do it 'calls to BulkCreateIntegrationService' do
expect(BulkUpdateIntegrationService).to receive(:new) expect(BulkUpdateIntegrationService).to receive(:new)
.with(integration, match_array(integration1)) .with(integration, match_array(integration1)).twice
.and_return(double(execute: nil)) .and_return(double(execute: nil))
subject subject
......
...@@ -4,33 +4,40 @@ require 'spec_helper' ...@@ -4,33 +4,40 @@ require 'spec_helper'
RSpec.describe PropagateIntegrationProjectWorker do RSpec.describe PropagateIntegrationProjectWorker do
describe '#perform' do describe '#perform' do
let_it_be(:group) { create(:group) }
let_it_be(:project1) { create(:project) } let_it_be(:project1) { create(:project) }
let_it_be(:project2) { create(:project) } let_it_be(:project2) { create(:project, group: group) }
let_it_be(:project3) { create(:project, group: group) }
let_it_be(:integration) { create(:redmine_service, :instance) } let_it_be(:integration) { create(:redmine_service, :instance) }
let(:job_args) { [integration.id, project1.id, project3.id] }
before do it_behaves_like 'an idempotent worker' do
allow(BulkCreateIntegrationService).to receive(:new) it 'calls to BulkCreateIntegrationService' do
.with(integration, match_array([project1, project2]), 'project') expect(BulkCreateIntegrationService).to receive(:new)
.with(integration, match_array([project1, project2, project3]), 'project').twice
.and_return(double(execute: nil)) .and_return(double(execute: nil))
subject
end end
it_behaves_like 'an idempotent worker' do context 'with a group integration' do
let(:job_args) { [integration.id, project1.id, project2.id] } let_it_be(:integration) { create(:redmine_service, group: group, project: nil) }
it 'calls to BulkCreateIntegrationService' do it 'calls to BulkCreateIntegrationService' do
expect(BulkCreateIntegrationService).to receive(:new) expect(BulkCreateIntegrationService).to receive(:new)
.with(integration, match_array([project1, project2]), 'project') .with(integration, match_array([project2, project3]), 'project').twice
.and_return(double(execute: nil)) .and_return(double(execute: nil))
subject subject
end end
end end
end
context 'with an invalid integration id' do context 'with an invalid integration id' do
it 'returns without failure' do it 'returns without failure' do
expect(BulkCreateIntegrationService).not_to receive(:new) expect(BulkCreateIntegrationService).not_to receive(:new)
subject.perform(0, project1.id, project2.id) subject.perform(0, 1, 100)
end end
end end
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