Add missing group members to export for I/E
This commit is contained in:
parent
572fb0be9b
commit
8409340b3b
|
@ -26,7 +26,7 @@ module Projects
|
|||
end
|
||||
|
||||
def project_tree_saver
|
||||
Gitlab::ImportExport::ProjectTreeSaver.new(project: project, shared: @shared)
|
||||
Gitlab::ImportExport::ProjectTreeSaver.new(project: project, current_user: @current_user, shared: @shared)
|
||||
end
|
||||
|
||||
def uploads_saver
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Add ability to export project inherited group members to Import/Export
|
||||
merge_request: 8923
|
||||
author:
|
|
@ -14,6 +14,11 @@
|
|||
> raketask.
|
||||
> - The exports are stored in a temporary [shared directory][tmp] and are deleted
|
||||
> every 24 hours by a specific worker.
|
||||
> - Group members will get exported as project members, as long as the user has
|
||||
> master or admin access to the group where the exported project lives. An admin
|
||||
> in the import side is required to map the users, based on email or username.
|
||||
> Otherwise, a supplementary comment is left to mention the original author and
|
||||
> the MRs, notes or issues will be owned by the importer.
|
||||
|
||||
Existing projects running on any GitLab instance or GitLab.com can be exported
|
||||
with all their related data and be moved into a new GitLab instance.
|
||||
|
@ -22,7 +27,7 @@ with all their related data and be moved into a new GitLab instance.
|
|||
|
||||
| GitLab version | Import/Export version |
|
||||
| -------- | -------- |
|
||||
| 8.16.2 to current | 0.1.6 |
|
||||
| 8.17.0 to current | 0.1.6 |
|
||||
| 8.13.0 | 0.1.5 |
|
||||
| 8.12.0 | 0.1.4 |
|
||||
| 8.10.3 | 0.1.3 |
|
||||
|
|
|
@ -32,6 +32,10 @@ module Gitlab
|
|||
@user.id
|
||||
end
|
||||
|
||||
def include?(old_author_id)
|
||||
map.keys.include?(old_author_id) && map[old_author_id] != default_user_id
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def missing_keys_tracking_hash
|
||||
|
|
|
@ -5,8 +5,9 @@ module Gitlab
|
|||
|
||||
attr_reader :full_path
|
||||
|
||||
def initialize(project:, shared:)
|
||||
def initialize(project:, current_user:, shared:)
|
||||
@project = project
|
||||
@current_user = current_user
|
||||
@shared = shared
|
||||
@full_path = File.join(@shared.export_path, ImportExport.project_filename)
|
||||
end
|
||||
|
@ -24,7 +25,29 @@ module Gitlab
|
|||
private
|
||||
|
||||
def project_json_tree
|
||||
@project.to_json(Gitlab::ImportExport::Reader.new(shared: @shared).project_tree)
|
||||
project_json['project_members'] += group_members_json
|
||||
|
||||
project_json.to_json
|
||||
end
|
||||
|
||||
def project_json
|
||||
@project_json ||= @project.as_json(reader.project_tree)
|
||||
end
|
||||
|
||||
def reader
|
||||
@reader ||= Gitlab::ImportExport::Reader.new(shared: @shared)
|
||||
end
|
||||
|
||||
def group_members_json
|
||||
group_members.as_json(reader.group_members_tree).each do |group_member|
|
||||
group_member['source_type'] = 'Project' # Make group members project members of the future import
|
||||
end
|
||||
end
|
||||
|
||||
def group_members
|
||||
return [] unless @current_user.can?(:admin_group, @project.group)
|
||||
|
||||
MembersFinder.new(@project.project_members, @project.group).execute(@current_user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,6 +21,10 @@ module Gitlab
|
|||
false
|
||||
end
|
||||
|
||||
def group_members_tree
|
||||
@attributes_finder.find_included(:project_members).merge(include: @attributes_finder.find(:user))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Builds a hash in the format described here: http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html
|
||||
|
|
|
@ -89,7 +89,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def has_author?(old_author_id)
|
||||
admin_user? && @members_mapper.map.keys.include?(old_author_id)
|
||||
admin_user? && @members_mapper.include?(old_author_id)
|
||||
end
|
||||
|
||||
def missing_author_note(updated_at, author_name)
|
||||
|
|
|
@ -116,5 +116,27 @@ describe Gitlab::ImportExport::MembersMapper, services: true do
|
|||
expect(members_mapper.map[exported_user_id]).to eq(user2.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'importing group members' do
|
||||
let(:group) { create(:group) }
|
||||
let(:project) { create(:empty_project, namespace: group) }
|
||||
let(:members_mapper) do
|
||||
described_class.new(
|
||||
exported_members: exported_members, user: user, project: project)
|
||||
end
|
||||
|
||||
before do
|
||||
group.add_users([user, user2], GroupMember::DEVELOPER)
|
||||
user.update(email: 'invite@test.com')
|
||||
end
|
||||
|
||||
it 'maps the importer' do
|
||||
expect(members_mapper.map[-1]).to eq(user.id)
|
||||
end
|
||||
|
||||
it 'maps the group member' do
|
||||
expect(members_mapper.map[exported_user_id]).to eq(user2.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ require 'spec_helper'
|
|||
describe Gitlab::ImportExport::ProjectTreeSaver, services: true do
|
||||
describe 'saves the project tree into a json object' do
|
||||
let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) }
|
||||
let(:project_tree_saver) { described_class.new(project: project, shared: shared) }
|
||||
let(:project_tree_saver) { described_class.new(project: project, current_user: user, shared: shared) }
|
||||
let(:export_path) { "#{Dir::tmpdir}/project_tree_saver_spec" }
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { setup_project }
|
||||
|
@ -92,7 +92,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do
|
|||
end
|
||||
|
||||
it 'has pipeline builds' do
|
||||
expect(saved_project_json['pipelines'].first['statuses'].count { |hash| hash['type'] == 'Ci::Build'}).to eq(1)
|
||||
expect(saved_project_json['pipelines'].first['statuses'].count { |hash| hash['type'] == 'Ci::Build' }).to eq(1)
|
||||
end
|
||||
|
||||
it 'has pipeline commits' do
|
||||
|
@ -112,13 +112,13 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do
|
|||
end
|
||||
|
||||
it 'has project and group labels' do
|
||||
label_types = saved_project_json['issues'].first['label_links'].map { |link| link['label']['type']}
|
||||
label_types = saved_project_json['issues'].first['label_links'].map { |link| link['label']['type'] }
|
||||
|
||||
expect(label_types).to match_array(['ProjectLabel', 'GroupLabel'])
|
||||
end
|
||||
|
||||
it 'has priorities associated to labels' do
|
||||
priorities = saved_project_json['issues'].first['label_links'].map { |link| link['label']['priorities']}
|
||||
priorities = saved_project_json['issues'].first['label_links'].map { |link| link['label']['priorities'] }
|
||||
|
||||
expect(priorities.flatten).not_to be_empty
|
||||
end
|
||||
|
@ -140,6 +140,51 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do
|
|||
|
||||
expect(project_tree_saver.save).to be true
|
||||
end
|
||||
|
||||
context 'group members' do
|
||||
let(:user2) { create(:user, email: 'group@member.com') }
|
||||
let(:member_emails) do
|
||||
saved_project_json['project_members'].map do |pm|
|
||||
pm['user']['email']
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
Group.first.add_developer(user2)
|
||||
end
|
||||
|
||||
it 'does not export group members if it has no permission' do
|
||||
Group.first.add_developer(user)
|
||||
|
||||
expect(member_emails).not_to include('group@member.com')
|
||||
end
|
||||
|
||||
it 'does not export group members as master' do
|
||||
Group.first.add_master(user)
|
||||
|
||||
expect(member_emails).not_to include('group@member.com')
|
||||
end
|
||||
|
||||
it 'exports group members as group owner' do
|
||||
Group.first.add_owner(user)
|
||||
|
||||
expect(member_emails).to include('group@member.com')
|
||||
end
|
||||
|
||||
context 'as admin' do
|
||||
let(:user) { create(:admin) }
|
||||
|
||||
it 'exports group members as admin' do
|
||||
expect(member_emails).to include('group@member.com')
|
||||
end
|
||||
|
||||
it 'exports group members as project members' do
|
||||
member_types = saved_project_json['project_members'].map { |pm| pm['source_type'] }
|
||||
|
||||
expect(member_types).to all(eq('Project'))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -167,10 +212,10 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do
|
|||
commit_status = create(:commit_status, project: project)
|
||||
|
||||
ci_pipeline = create(:ci_pipeline,
|
||||
project: project,
|
||||
sha: merge_request.diff_head_sha,
|
||||
ref: merge_request.source_branch,
|
||||
statuses: [commit_status])
|
||||
project: project,
|
||||
sha: merge_request.diff_head_sha,
|
||||
ref: merge_request.source_branch,
|
||||
statuses: [commit_status])
|
||||
|
||||
create(:ci_build, pipeline: ci_pipeline, project: project)
|
||||
create(:milestone, project: project)
|
||||
|
|
|
@ -86,6 +86,10 @@ describe Gitlab::ImportExport::Reader, lib: true do
|
|||
expect(described_class.new(shared: shared).project_tree).to match(include: [{ issues: { methods: [:name] } }])
|
||||
end
|
||||
|
||||
it 'generates the correct hash for group members' do
|
||||
expect(described_class.new(shared: shared).group_members_tree).to match({ include: { user: { only: [:email] } } })
|
||||
end
|
||||
|
||||
def setup_yaml(hash)
|
||||
allow(YAML).to receive(:load_file).with(test_config).and_return(hash)
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue