Commit 3487761d authored by Mark Chao's avatar Mark Chao

Assign code owners in data migration

The sync_code_owners_with_approvers call uses
original implementation, as it requires full
MR implementation to compute code owners.
However the specs are copied over,
so in the future if its behavior changes,
spec failure would notify developer to copy
existing code over.
parent fc73f551
...@@ -83,11 +83,19 @@ module EE ...@@ -83,11 +83,19 @@ module EE
end end
def sync_code_owners_with_approvers def sync_code_owners_with_approvers
ActiveRecord::Base.transaction do return if merged?
rule = approval_rules.code_owner.first
rule ||= approval_rules.code_owner.create!(name: ApprovalMergeRequestRule::DEFAULT_NAME_FOR_CODE_OWNER)
rule.users = code_owners owners = code_owners
if owners.present?
ActiveRecord::Base.transaction do
rule = approval_rules.code_owner.first
rule ||= approval_rules.code_owner.create!(name: ApprovalMergeRequestRule::DEFAULT_NAME_FOR_CODE_OWNER)
rule.users = code_owners
end
else
approval_rules.code_owner.delete_all
end end
end end
end end
......
...@@ -102,6 +102,10 @@ module Gitlab ...@@ -102,6 +102,10 @@ module Gitlab
state == 'merged' state == 'merged'
end end
def sync_code_owners_with_approvers
::MergeRequest.find(id).sync_code_owners_with_approvers
end
def finalize_approvals def finalize_approvals
return unless merged? return unless merged?
...@@ -170,6 +174,8 @@ module Gitlab ...@@ -170,6 +174,8 @@ module Gitlab
rule.approval_project_rule = target.target_project.approval_rules.regular.first rule.approval_project_rule = target.target_project.approval_rules.regular.first
end end
target.sync_code_owners_with_approvers
target.finalize_approvals if target.merged? target.finalize_approvals if target.merged?
end end
end end
......
...@@ -120,6 +120,56 @@ describe Gitlab::BackgroundMigration::MigrateApproverToApprovalRules do ...@@ -120,6 +120,56 @@ describe Gitlab::BackgroundMigration::MigrateApproverToApprovalRules do
expect(target.approval_rules.exists?(approval_rule.id)).to eq(false) expect(target.approval_rules.exists?(approval_rule.id)).to eq(false)
end end
end end
context '#sync_code_owners_with_approvers' do
let(:owners) { create_list(:user, 2) }
before do
allow(::Gitlab::CodeOwners).to receive(:for_merge_request).and_return(owners)
end
context 'when merge request is merged' do
let(:target) { create(:merged_merge_request) }
it 'does nothing' do
expect do
described_class.new.perform(target_type, target.id)
end.not_to change { target.approval_rules.count }
end
end
context 'when code owner rule does not exist' do
it 'creates rule' do
expect do
described_class.new.perform(target_type, target.id)
end.to change { target.approval_rules.code_owner.count }.by(1)
expect(target.approval_rules.code_owner.first.users).to contain_exactly(*owners)
end
end
context 'when code owner rule exists' do
let!(:code_owner_rule) { create(:approval_merge_request_rule, merge_request: target, code_owner: true, users: [create(:user)]) }
it 'reuses and updates existing rule' do
expect do
described_class.new.perform(target_type, target.id)
end.not_to change { target.approval_rules.count }
expect(code_owner_rule.reload.users).to contain_exactly(*owners)
end
context 'when there is no code owner' do
let(:owners) { [] }
it 'removes rule' do
described_class.new.perform(target_type, target.id)
expect(target.approval_rules.exists?(code_owner_rule.id)).to eq(false)
end
end
end
end
end end
context 'project' do context 'project' do
......
...@@ -71,36 +71,49 @@ describe MergeRequest do ...@@ -71,36 +71,49 @@ describe MergeRequest do
end end
describe '#sync_code_owners_with_approvers' do describe '#sync_code_owners_with_approvers' do
let(:owners) { [create(:user), create(:user)] } let(:owners) { create_list(:user, 2) }
before do before do
allow(subject).to receive(:code_owners).and_return(owners) allow(subject).to receive(:code_owners).and_return(owners)
end end
it 'sync code owner to the code owner rule' do it 'does nothing when merge request is merged' do
allow(subject).to receive(:merged?).and_return(true)
expect do expect do
subject.sync_code_owners_with_approvers subject.sync_code_owners_with_approvers
end.to change { subject.approval_rules.count }.by(1) end.not_to change { subject.approval_rules.count }
expect(subject.approval_rules.code_owner.first.users).to contain_exactly(*owners)
end end
context 'when code owner rule already exists' do context 'when code owner rule does not exist' do
let!(:code_owner_rule) { subject.approval_rules.code_owner.create!(name: 'Code Owner') } it 'creates rule' do
expect do
subject.sync_code_owners_with_approvers
end.to change { subject.approval_rules.code_owner.count }.by(1)
before do expect(subject.approval_rules.code_owner.first.users).to contain_exactly(*owners)
code_owner_rule.users << create(:user)
end end
end
it 'reuses existing rule' do context 'when code owner rule exists' do
let!(:code_owner_rule) { subject.approval_rules.code_owner.create!(name: 'Code Owner', users: [create(:user)]) }
it 'reuses and updates existing rule' do
expect do expect do
subject.sync_code_owners_with_approvers subject.sync_code_owners_with_approvers
end.not_to change { subject.approval_rules.count } end.not_to change { subject.approval_rules.count }
rule = subject.approval_rules.code_owner.first expect(code_owner_rule.reload.users).to contain_exactly(*owners)
end
context 'when there is no code owner' do
let(:owners) { [] }
expect(rule).to eq(code_owner_rule) it 'removes rule' do
expect(rule.users).to contain_exactly(*owners) subject.sync_code_owners_with_approvers
expect(subject.approval_rules.exists?(code_owner_rule.id)).to eq(false)
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