Commit e8928967 authored by Mayra Cabrera's avatar Mayra Cabrera

Merge branch '233938-admin-integration' into 'master'

Find admin integration with group-level integrations

See merge request gitlab-org/gitlab!41407
parents de2992fc a2f1404b
...@@ -12,7 +12,7 @@ module Groups ...@@ -12,7 +12,7 @@ module Groups
end end
def edit def edit
@admin_integration = Service.instance_for(integration.type) @admin_integration = Service.default_integration(integration.type, group)
super super
end end
......
...@@ -20,7 +20,7 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -20,7 +20,7 @@ class Projects::ServicesController < Projects::ApplicationController
layout "project_settings" layout "project_settings"
def edit def edit
@admin_integration = Service.instance_for(service.type) @admin_integration = Service.default_integration(service.type, project)
end end
def update def update
......
...@@ -35,6 +35,7 @@ class Group < Namespace ...@@ -35,6 +35,7 @@ class Group < Namespace
has_many :milestones has_many :milestones
has_many :iterations has_many :iterations
has_many :services
has_many :shared_group_links, foreign_key: :shared_with_group_id, class_name: 'GroupGroupLink' has_many :shared_group_links, foreign_key: :shared_with_group_id, class_name: 'GroupGroupLink'
has_many :shared_with_group_links, foreign_key: :shared_group_id, class_name: 'GroupGroupLink' has_many :shared_with_group_links, foreign_key: :shared_group_id, class_name: 'GroupGroupLink'
has_many :shared_groups, through: :shared_group_links, source: :shared_group has_many :shared_groups, through: :shared_group_links, source: :shared_group
......
...@@ -46,6 +46,7 @@ class Service < ApplicationRecord ...@@ -46,6 +46,7 @@ class Service < ApplicationRecord
after_commit :cache_project_has_external_wiki after_commit :cache_project_has_external_wiki
belongs_to :project, inverse_of: :services belongs_to :project, inverse_of: :services
belongs_to :group, inverse_of: :services
has_one :service_hook has_one :service_hook
validates :project_id, presence: true, unless: -> { template? || instance? || group_id } validates :project_id, presence: true, unless: -> { template? || instance? || group_id }
...@@ -236,10 +237,25 @@ class Service < ApplicationRecord ...@@ -236,10 +237,25 @@ class Service < ApplicationRecord
exists?(instance: true, type: type) exists?(instance: true, type: type)
end end
def self.instance_for(type) def self.default_integration(type, scope)
find_by(instance: true, type: type) closest_group_integration(type, scope) || instance_level_integration(type)
end end
def self.closest_group_integration(type, scope)
group_ids = scope.ancestors.select(:id)
array = group_ids.to_sql.present? ? "array(#{group_ids.to_sql})" : 'ARRAY[]'
where(type: type, group_id: group_ids)
.order(Arel.sql("array_position(#{array}::bigint[], services.group_id)"))
.first
end
private_class_method :closest_group_integration
def self.instance_level_integration(type)
find_by(type: type, instance: true)
end
private_class_method :instance_level_integration
def activated? def activated?
active active
end end
......
...@@ -14,7 +14,7 @@ RSpec.describe IdInOrdered do ...@@ -14,7 +14,7 @@ RSpec.describe IdInOrdered do
expect(Issue.id_in_ordered([issue3.id, issue1.id, issue4.id, issue5.id, issue2.id])).to eq([ expect(Issue.id_in_ordered([issue3.id, issue1.id, issue4.id, issue5.id, issue2.id])).to eq([
issue3, issue1, issue4, issue5, issue2 issue3, issue1, issue4, issue5, issue2
]) ])
end end
context 'when the ids are not an array of integers' do context 'when the ids are not an array of integers' do
......
...@@ -27,6 +27,7 @@ RSpec.describe Group do ...@@ -27,6 +27,7 @@ RSpec.describe Group do
it { is_expected.to have_many(:milestones) } it { is_expected.to have_many(:milestones) }
it { is_expected.to have_many(:iterations) } it { is_expected.to have_many(:iterations) }
it { is_expected.to have_many(:group_deploy_keys) } it { is_expected.to have_many(:group_deploy_keys) }
it { is_expected.to have_many(:services) }
describe '#members & #requesters' do describe '#members & #requesters' do
let(:requester) { create(:user) } let(:requester) { create(:user) }
......
...@@ -8,6 +8,7 @@ RSpec.describe Service do ...@@ -8,6 +8,7 @@ RSpec.describe Service do
describe "Associations" do describe "Associations" do
it { is_expected.to belong_to :project } it { is_expected.to belong_to :project }
it { is_expected.to belong_to :group }
it { is_expected.to have_one :service_hook } it { is_expected.to have_one :service_hook }
it { is_expected.to have_one :jira_tracker_data } it { is_expected.to have_one :jira_tracker_data }
it { is_expected.to have_one :issue_tracker_data } it { is_expected.to have_one :issue_tracker_data }
...@@ -419,29 +420,49 @@ RSpec.describe Service do ...@@ -419,29 +420,49 @@ RSpec.describe Service do
end end
end end
describe 'instance' do describe '.default_integration' do
describe '.instance_for' do context 'with an instance-level service' do
let_it_be(:jira_service) { create(:jira_service, :instance) } let_it_be(:instance_service) { create(:jira_service, :instance) }
let_it_be(:slack_service) { create(:slack_service, :instance) }
subject { described_class.instance_for(type) } it 'returns the instance service' do
expect(described_class.default_integration('JiraService', project)).to eq(instance_service)
context 'Hipchat serivce' do end
let(:type) { 'HipchatService' }
it { is_expected.to eq(nil) } it 'returns nil for nonexistent service type' do
expect(described_class.default_integration('HipchatService', project)).to eq(nil)
end end
context 'Jira serivce' do context 'with a group service' do
let(:type) { 'JiraService' } let_it_be(:group_service) { create(:jira_service, group_id: group.id, project_id: nil) }
it { is_expected.to eq(jira_service) } it 'returns the group service for a project' do
end expect(described_class.default_integration('JiraService', project)).to eq(group_service)
end
it 'returns the instance service for a group' do
expect(described_class.default_integration('JiraService', group)).to eq(instance_service)
end
context 'Slack serivce' do context 'with a subgroup' do
let(:type) { 'SlackService' } let_it_be(:subgroup) { create(:group, parent: group) }
let!(:project) { create(:project, group: subgroup) }
it { is_expected.to eq(slack_service) } it 'returns the closest group service for a project' do
expect(described_class.default_integration('JiraService', project)).to eq(group_service)
end
it 'returns the closest group service for a subgroup' do
expect(described_class.default_integration('JiraService', subgroup)).to eq(group_service)
end
context 'having a service' do
let!(:subgroup_service) { create(:jira_service, group_id: subgroup.id, project_id: nil) }
it 'returns the closest group service for a project' do
expect(described_class.default_integration('JiraService', project)).to eq(subgroup_service)
end
end
end
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