Commit ca8f1ed9 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Import multiple issue assignees from GitLab export

When importing from a GitLab archive, an admin can carry over the
assignations. Other users can not.

When a regular user is importing an issue with multiple assignees, the
assignee is replaced with the current user, meaning we would try to
insert current user as an assignee multiple times.

By filtering the array before storing it, the import becomes more
robust.
parent 5ae91f32
---
title: Fix importing multiple assignees from GitLab export
merge_request: 17718
author:
type: fixed
...@@ -70,6 +70,7 @@ module Gitlab ...@@ -70,6 +70,7 @@ module Gitlab
update_user_references update_user_references
update_project_references update_project_references
remove_duplicate_assignees
reset_tokens! reset_tokens!
remove_encrypted_attributes! remove_encrypted_attributes!
...@@ -83,6 +84,14 @@ module Gitlab ...@@ -83,6 +84,14 @@ module Gitlab
end end
end end
def remove_duplicate_assignees
return unless @relation_hash['issue_assignees']
# When an assignee did not exist in the members mapper, the importer is
# assigned. We only need to assign each user once.
@relation_hash['issue_assignees'].uniq!(&:user_id)
end
def setup_note def setup_note
set_note_author set_note_author
# attachment is deprecated and note uploads are handled by Markdown uploader # attachment is deprecated and note uploads are handled by Markdown uploader
......
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
{ {
"id": 40, "id": 40,
"title": "Voluptatem", "title": "Voluptatem",
"assignee_id": 1,
"author_id": 22, "author_id": 22,
"project_id": 5, "project_id": 5,
"created_at": "2016-06-14T15:02:08.340Z", "created_at": "2016-06-14T15:02:08.340Z",
...@@ -61,7 +60,23 @@ ...@@ -61,7 +60,23 @@
"issue_assignees": [ "issue_assignees": [
{ {
"user_id": 1, "user_id": 1,
"issue_id": 1 "issue_id": 40
},
{
"user_id": 15,
"issue_id": 40
},
{
"user_id": 16,
"issue_id": 40
},
{
"user_id": 16,
"issue_id": 40
},
{
"user_id": 6,
"issue_id": 40
} }
], ],
"milestone": { "milestone": {
...@@ -319,8 +334,7 @@ ...@@ -319,8 +334,7 @@
}, },
{ {
"id": 39, "id": 39,
"title": "Delectus veniam ratione in eos culpa et natus molestiae earum aut.", "title": "Issue without assignees",
"assignee_id": 20,
"author_id": 22, "author_id": 22,
"project_id": 5, "project_id": 5,
"created_at": "2016-06-14T15:02:08.233Z", "created_at": "2016-06-14T15:02:08.233Z",
...@@ -334,6 +348,7 @@ ...@@ -334,6 +348,7 @@
"confidential": false, "confidential": false,
"due_date": null, "due_date": null,
"moved_to_id": null, "moved_to_id": null,
"issue_assignees": [],
"milestone": { "milestone": {
"id": 1, "id": 1,
"title": "test milestone", "title": "test milestone",
...@@ -539,7 +554,6 @@ ...@@ -539,7 +554,6 @@
{ {
"id": 38, "id": 38,
"title": "Quasi adipisci non cupiditate dolorem quo qui earum sed.", "title": "Quasi adipisci non cupiditate dolorem quo qui earum sed.",
"assignee_id": 1,
"author_id": 6, "author_id": 6,
"project_id": 5, "project_id": 5,
"created_at": "2016-06-14T15:02:08.154Z", "created_at": "2016-06-14T15:02:08.154Z",
...@@ -756,7 +770,6 @@ ...@@ -756,7 +770,6 @@
{ {
"id": 37, "id": 37,
"title": "Cupiditate quo aut ducimus minima molestiae vero numquam possimus.", "title": "Cupiditate quo aut ducimus minima molestiae vero numquam possimus.",
"assignee_id": 15,
"author_id": 20, "author_id": 20,
"project_id": 5, "project_id": 5,
"created_at": "2016-06-14T15:02:08.051Z", "created_at": "2016-06-14T15:02:08.051Z",
...@@ -952,7 +965,6 @@ ...@@ -952,7 +965,6 @@
{ {
"id": 36, "id": 36,
"title": "Necessitatibus dolor est enim quia rem suscipit quidem voluptas ullam.", "title": "Necessitatibus dolor est enim quia rem suscipit quidem voluptas ullam.",
"assignee_id": 20,
"author_id": 16, "author_id": 16,
"project_id": 5, "project_id": 5,
"created_at": "2016-06-14T15:02:07.958Z", "created_at": "2016-06-14T15:02:07.958Z",
...@@ -1148,7 +1160,6 @@ ...@@ -1148,7 +1160,6 @@
{ {
"id": 35, "id": 35,
"title": "Repellat praesentium deserunt maxime incidunt harum porro qui.", "title": "Repellat praesentium deserunt maxime incidunt harum porro qui.",
"assignee_id": 6,
"author_id": 20, "author_id": 20,
"project_id": 5, "project_id": 5,
"created_at": "2016-06-14T15:02:07.832Z", "created_at": "2016-06-14T15:02:07.832Z",
...@@ -1344,7 +1355,6 @@ ...@@ -1344,7 +1355,6 @@
{ {
"id": 34, "id": 34,
"title": "Ullam expedita deserunt libero consequatur quia dolor harum perferendis facere quidem.", "title": "Ullam expedita deserunt libero consequatur quia dolor harum perferendis facere quidem.",
"assignee_id": 20,
"author_id": 1, "author_id": 1,
"project_id": 5, "project_id": 5,
"created_at": "2016-06-14T15:02:07.717Z", "created_at": "2016-06-14T15:02:07.717Z",
...@@ -1540,7 +1550,6 @@ ...@@ -1540,7 +1550,6 @@
{ {
"id": 33, "id": 33,
"title": "Numquam accusamus eos iste exercitationem magni non inventore.", "title": "Numquam accusamus eos iste exercitationem magni non inventore.",
"assignee_id": 15,
"author_id": 26, "author_id": 26,
"project_id": 5, "project_id": 5,
"created_at": "2016-06-14T15:02:07.611Z", "created_at": "2016-06-14T15:02:07.611Z",
...@@ -1736,7 +1745,6 @@ ...@@ -1736,7 +1745,6 @@
{ {
"id": 32, "id": 32,
"title": "Necessitatibus magnam qui at velit consequatur perspiciatis.", "title": "Necessitatibus magnam qui at velit consequatur perspiciatis.",
"assignee_id": 22,
"author_id": 15, "author_id": 15,
"project_id": 5, "project_id": 5,
"created_at": "2016-06-14T15:02:07.431Z", "created_at": "2016-06-14T15:02:07.431Z",
...@@ -1932,7 +1940,6 @@ ...@@ -1932,7 +1940,6 @@
{ {
"id": 31, "id": 31,
"title": "Libero nam magnam incidunt eaque placeat error et.", "title": "Libero nam magnam incidunt eaque placeat error et.",
"assignee_id": 1,
"author_id": 16, "author_id": 16,
"project_id": 5, "project_id": 5,
"created_at": "2016-06-14T15:02:07.280Z", "created_at": "2016-06-14T15:02:07.280Z",
......
...@@ -4,7 +4,12 @@ include ImportExport::CommonUtil ...@@ -4,7 +4,12 @@ include ImportExport::CommonUtil
describe Gitlab::ImportExport::ProjectTreeRestorer do describe Gitlab::ImportExport::ProjectTreeRestorer do
describe 'restore project tree' do describe 'restore project tree' do
before(:context) do before(:context) do
@user = create(:user) # Using an admin for import, so we can check assignment of existing members
@user = create(:admin)
@existing_members = [
create(:user, username: 'bernard_willms'),
create(:user, username: 'saul_will')
]
RSpec::Mocks.with_temporary_scope do RSpec::Mocks.with_temporary_scope do
@project = create(:project, :builds_disabled, :issues_disabled, name: 'project', path: 'project') @project = create(:project, :builds_disabled, :issues_disabled, name: 'project', path: 'project')
...@@ -63,8 +68,9 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do ...@@ -63,8 +68,9 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
expect(issue.reload.updated_at.to_s).to eq('2016-06-14 15:02:47 UTC') expect(issue.reload.updated_at.to_s).to eq('2016-06-14 15:02:47 UTC')
end end
it 'has issue assignees' do it 'has multiple issue assignees' do
expect(Issue.where(title: 'Voluptatem').first.issue_assignees).not_to be_empty expect(Issue.find_by(title: 'Voluptatem').assignees).to contain_exactly(@user, *@existing_members)
expect(Issue.find_by(title: 'Issue without assignees').assignees).to be_empty
end end
it 'contains the merge access levels on a protected branch' do it 'contains the merge access levels on a protected branch' do
......
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