Commit 9d2c7938 authored by George Koltsov's avatar George Koltsov

Add Board Lists to Group Export

- Add missing board lists to group export
  which were not previously exported
- Exports label lists for CE and
  assignee/milestone lists for EE
parent 6b95c3f9
---
title: Add Board Lists to Group Export
merge_request: 24863
author:
type: changed
{
"name": "ymg09t5704clnxnqfgaj2h098gz4r7gyx4wc3fzmlqj1en24zf",
"path": "ymg09t5704clnxnqfgaj2h098gz4r7gyx4wc3fzmlqj1en24zf",
"owner_id": null,
"created_at": "2019-11-20 17:01:53 UTC",
"updated_at": "2019-11-20 17:05:44 UTC",
"description": "Group Description",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 0,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": null,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"saml_discovery_token": "rBKx3ioz",
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"milestones": [
{
"id": 7642,
"title": "v4.0",
"project_id": null,
"description": "Et laudantium enim omnis ea reprehenderit iure.",
"due_date": null,
"created_at": "2019-11-20T17:02:14.336Z",
"updated_at": "2019-11-20T17:02:14.336Z",
"state": "closed",
"iid": 5,
"start_date": null,
"group_id": 4351
}
],
"badges": [
{
"id": 10,
"link_url": "https://localhost:3443/%{default_branch}",
"image_url": "https://badge_image.png",
"project_id": null,
"group_id": 4351,
"created_at": "2019-11-20T17:27:02.047Z",
"updated_at": "2019-11-20T17:27:02.047Z",
"type": "GroupBadge"
}
],
"labels": [
{
"id": 23452,
"title": "Bruffefunc",
"color": "#1d2da4",
"project_id": null,
"created_at": "2019-11-20T17:02:20.546Z",
"updated_at": "2019-11-20T17:02:20.546Z",
"template": false,
"description": null,
"group_id": 4351,
"type": "GroupLabel",
"priorities": [],
"textColor": "#FFFFFF"
}
],
"boards": [
{
"id": 57,
"project_id": null,
"created_at": "2019-11-20T17:27:41.118Z",
"updated_at": "2019-11-20T17:27:41.118Z",
"name": "first board",
"milestone_id": 7638,
"group_id": 4351,
"weight": null,
"labels": [],
"lists": [
{
"id": 231,
"board_id": 173,
"label_id": null,
"list_type": "assignee",
"position": 3,
"created_at": "2020-02-11T17:02:14.073Z",
"updated_at": "2020-02-11T17:02:14.073Z",
"user_id": 70,
"milestone_id": null,
"max_issue_count": 0,
"max_issue_weight": 0,
"board": {
"id": 173,
"project_id": null,
"created_at": "2020-02-11T14:35:51.561Z",
"updated_at": "2020-02-11T14:35:51.561Z",
"name": "hi",
"milestone_id": null,
"group_id": 4351,
"weight": null
}
},
{
"id": 33,
"board_id": 173,
"label_id": null,
"list_type": "milestone",
"position": 1,
"created_at": "2020-02-10T16:16:01.896Z",
"updated_at": "2020-02-10T16:16:01.896Z",
"user_id": null,
"milestone_id": 264,
"max_issue_count": 0,
"max_issue_weight": 0,
"milestone": {
"id": 264,
"title": "v2.2",
"project_id": null,
"description": "Voluptatum itaque natus laboriosam dolor omnis eaque quos cupiditate.",
"due_date": null,
"created_at": "2020-02-06T15:44:52.126Z",
"updated_at": "2020-02-06T15:44:52.126Z",
"state": "active",
"iid": 1,
"start_date": null,
"group_id": 4351,
"events": []
},
"board": {
"id": 173,
"project_id": null,
"created_at": "2020-02-11T14:35:51.561Z",
"updated_at": "2020-02-11T14:35:51.561Z",
"name": "hi",
"milestone_id": null,
"group_id": 4351,
"weight": null
}
}
]
}
],
"members": [
{
"id": 13766,
"access_level": 30,
"source_id": 4351,
"source_type": "Namespace",
"user_id": 42,
"notification_level": 3,
"created_at": "2019-11-20T17:04:36.184Z",
"updated_at": "2019-11-20T17:04:36.184Z",
"created_by_id": null,
"invite_email": null,
"invite_token": null,
"invite_accepted_at": null,
"requested_at": null,
"expires_at": null,
"ldap": false,
"override": false,
"user": {
"id": 42,
"email": "moriah@collinsmurphy.com",
"username": "reported_user_15"
}
}
],
"epics": [
{
"id": 13622,
"milestone_id": null,
"group_id": 4351,
"author_id": 1,
"assignee_id": null,
"iid": 1,
"updated_by_id": null,
"last_edited_by_id": null,
"lock_version": 0,
"start_date": null,
"end_date": null,
"last_edited_at": null,
"created_at": "2019-11-20T17:02:09.754Z",
"updated_at": "2019-11-20T18:38:40.054Z",
"title": "Provident neque consequatur numquam ad laboriosam voluptatem magnam.",
"description": "Fugit nisi est ut numquam quia rerum vitae qui. Et in est aliquid voluptas et ut vitae. In distinctio voluptates ut deleniti iste.\n\nReiciendis eum sunt vero blanditiis at quia. Voluptate eum facilis illum ea distinctio maiores. Doloribus aut nemo ea distinctio.\n\nNihil cum distinctio voluptates quam. Laboriosam distinctio ea accusantium soluta perspiciatis nesciunt impedit. Id qui natus quis minima voluptatum velit ut reprehenderit. Molestiae quia est harum sapiente rem error architecto id. Et minus ipsa et ut ut.",
"start_date_sourcing_milestone_id": null,
"due_date_sourcing_milestone_id": null,
"start_date_fixed": null,
"due_date_fixed": null,
"start_date_is_fixed": null,
"due_date_is_fixed": null,
"closed_by_id": null,
"closed_at": null,
"parent_id": null,
"relative_position": null,
"state_id": "opened",
"start_date_sourcing_epic_id": null,
"due_date_sourcing_epic_id": null,
"notes": [
{
"id": 44164,
"note": "added epic \u00262 as child epic",
"noteable_type": "Epic",
"author_id": 1,
"created_at": "2019-11-20T18:38:26.689Z",
"updated_at": "2019-11-20T18:38:26.724Z",
"project_id": null,
"attachment": {
"url": null
},
"line_code": null,
"commit_id": null,
"noteable_id": 13622,
"system": true,
"st_diff": null,
"updated_by_id": null,
"position": null,
"original_position": null,
"resolved_at": null,
"resolved_by_id": null,
"discussion_id": "133f0c3001860fa8d2031e398a65db74477378c4",
"change_position": null,
"resolved_by_push": null,
"review_id": null,
"type": null,
"author": {
"name": "Administrator"
},
"award_emoji": [
{
"id": 12,
"name": "drum",
"user_id": 1,
"awardable_type": "Note",
"awardable_id": 44170,
"created_at": "2019-11-05T15:32:21.287Z",
"updated_at": "2019-11-05T15:32:21.287Z"
}
]
}
],
"award_emoji": [
{
"id": 12,
"name": "thumbsup",
"user_id": 1,
"awardable_type": "Epic",
"awardable_id": 13622,
"created_at": "2019-11-05T15:37:21.287Z",
"updated_at": "2019-11-05T15:37:21.287Z"
}
]
}
]
}
......@@ -11,7 +11,9 @@ describe Gitlab::ImportExport::GroupTreeRestorer do
let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group, group_hash: nil) }
before do
setup_import_export_config('group_exports/complex')
stub_licensed_features(board_assignee_lists: true, board_milestone_lists: true)
setup_import_export_config('group_exports/light', 'ee')
group.add_owner(user)
group_tree_restorer.restore
end
......@@ -19,7 +21,7 @@ describe Gitlab::ImportExport::GroupTreeRestorer do
describe 'restore group tree' do
context 'epics' do
it 'has group epics' do
expect(group.epics.count).to eq(5)
expect(group.epics.count).to eq(1)
end
it 'has award emoji' do
......@@ -29,12 +31,20 @@ describe Gitlab::ImportExport::GroupTreeRestorer do
context 'epic notes' do
it 'has epic notes' do
expect(group.epics.first.notes.count).to eq(4)
expect(group.epics.first.notes.count).to eq(1)
end
it 'has award emoji on epic notes' do
expect(group.epics.first.notes.first.award_emoji.first.name).to eq('drum')
end
end
context 'board lists' do
it 'has milestone & assignee lists' do
lists = group.boards.find_by(name: 'first board').lists
expect(lists.map(&:list_type)).to contain_exactly('assignee', 'milestone')
end
end
end
end
......@@ -11,6 +11,7 @@ describe Gitlab::ImportExport::GroupTreeSaver do
let_it_be(:epic) { create(:epic, group: group, parent: parent_epic) }
let_it_be(:epic_event) { create(:event, :created, target: epic, group: group, author: user) }
let_it_be(:epic_push_event) { create(:event, :pushed, target: epic, group: group, author: user) }
let_it_be(:milestone) { create(:milestone, group: group) }
let_it_be(:board) { create(:board, group: group, assignee: user, labels: [label]) }
let_it_be(:note) { create(:note, noteable: epic) }
let_it_be(:note_event) { create(:event, :created, target: note, author: user) }
......@@ -101,24 +102,41 @@ describe Gitlab::ImportExport::GroupTreeSaver do
end
context 'boards relation' do
it 'saves top level boards' do
before do
stub_licensed_features(board_assignee_lists: true, board_milestone_lists: true)
create(:list, board: board, user: user, list_type: List.list_types[:assignee], position: 0)
create(:list, board: board, milestone: milestone, list_type: List.list_types[:milestone], position: 1)
expect_successful_save(group_tree_saver)
end
it 'saves top level boards' do
expect(saved_group_json['boards'].size).to eq(1)
end
it 'saves board assignee' do
expect_successful_save(group_tree_saver)
expect(saved_group_json['boards'].first['board_assignee']['assignee_id']).to eq(user.id)
end
it 'saves board labels' do
expect_successful_save(group_tree_saver)
labels = saved_group_json['boards'].first['labels']
expect(labels).not_to be_empty
expect(labels.first['title']).to eq(label.title)
end
it 'saves board lists' do
lists = saved_group_json['boards'].first['lists']
expect(lists).not_to be_empty
milestone_list = lists.find { |list| list['list_type'] == 'milestone' }
assignee_list = lists.find { |list| list['list_type'] == 'assignee' }
expect(milestone_list['milestone_id']).to eq(milestone.id)
expect(assignee_list['user_id']).to eq(user.id)
end
end
end
......
......@@ -8,10 +8,14 @@ tree:
- :milestones
- :badges
- labels:
- :priorities
- :boards
- :priorities
- boards:
- lists:
- label:
- :priorities
- :board
- members:
- :user
- :user
included_attributes:
user:
......@@ -30,12 +34,16 @@ excluded_attributes:
methods:
labels:
- :type
label:
- :type
badges:
- :type
notes:
- :type
events:
- :action
lists:
- :list_type
preloads:
......@@ -45,16 +53,20 @@ ee:
tree:
group:
- epics:
- :parent
- :parent
- :award_emoji
- events:
- :push_event_payload
- notes:
- :author
- :award_emoji
- events:
- :push_event_payload
- notes:
- :author
- :award_emoji
- events:
- :push_event_payload
- :push_event_payload
- boards:
- :board_assignee
- labels:
- :priorities
- :board_assignee
- labels:
- :priorities
- lists:
- milestone:
- events:
- :push_event_payload
......@@ -260,25 +260,101 @@
],
"boards": [
{
"id": 56,
"id": 173,
"project_id": null,
"created_at": "2019-11-20T17:27:16.808Z",
"updated_at": "2019-11-20T17:27:16.808Z",
"name": "Development",
"created_at": "2020-02-11T14:35:51.561Z",
"updated_at": "2020-02-11T14:35:51.561Z",
"name": "first board",
"milestone_id": null,
"group_id": 4351,
"weight": null,
"labels": []
},
{
"id": 57,
"project_id": null,
"created_at": "2019-11-20T17:27:41.118Z",
"updated_at": "2019-11-20T17:27:41.118Z",
"name": "Board!",
"milestone_id": 7638,
"group_id": 4351,
"weight": null,
"lists": [
{
"id": 189,
"board_id": 173,
"label_id": 271,
"list_type": "label",
"position": 0,
"created_at": "2020-02-11T14:35:57.131Z",
"updated_at": "2020-02-11T14:35:57.131Z",
"user_id": null,
"milestone_id": null,
"max_issue_count": 0,
"max_issue_weight": 0,
"label": {
"id": 271,
"title": "TSL",
"color": "#58796f",
"project_id": null,
"created_at": "2019-11-20T17:02:20.541Z",
"updated_at": "2020-02-06T15:44:52.048Z",
"template": false,
"description": null,
"group_id": 4351,
"type": "GroupLabel",
"priorities": []
},
"board": {
"id": 173,
"project_id": null,
"created_at": "2020-02-11T14:35:51.561Z",
"updated_at": "2020-02-11T14:35:51.561Z",
"name": "hi",
"milestone_id": null,
"group_id": 4351,
"weight": null
}
},
{
"id": 190,
"board_id": 173,
"label_id": 272,
"list_type": "label",
"position": 1,
"created_at": "2020-02-11T14:35:57.868Z",
"updated_at": "2020-02-11T14:35:57.868Z",
"user_id": null,
"milestone_id": null,
"max_issue_count": 0,
"max_issue_weight": 0,
"label": {
"id": 272,
"title": "Sosync",
"color": "#110320",
"project_id": null,
"created_at": "2019-11-20T17:02:20.532Z",
"updated_at": "2020-02-06T15:44:52.057Z",
"template": false,
"description": null,
"group_id": 4351,
"type": "GroupLabel",
"priorities": []
},
"board": {
"id": 173,
"project_id": null,
"created_at": "2020-02-11T14:35:51.561Z",
"updated_at": "2020-02-11T14:35:51.561Z",
"name": "hi",
"milestone_id": null,
"group_id": 4351,
"weight": null
}
},
{
"id": 188,
"board_id": 173,
"label_id": null,
"list_type": "closed",
"position": null,
"created_at": "2020-02-11T14:35:51.593Z",
"updated_at": "2020-02-11T14:35:51.593Z",
"user_id": null,
"milestone_id": null,
"max_issue_count": 0,
"max_issue_weight": 0
}
],
"labels": []
}
],
......
......@@ -39,8 +39,18 @@ describe Gitlab::ImportExport::GroupTreeRestorer do
expect(@group.labels.count).to eq(10)
end
it 'has issue boards' do
expect(@group.boards.count).to eq(2)
context 'issue boards' do
it 'has issue boards' do
expect(@group.boards.count).to eq(1)
end
it 'has board label lists' do
lists = @group.boards.find_by(name: 'first board').lists
expect(lists.count).to eq(3)
expect(lists.first.label.title).to eq('TSL')
expect(lists.second.label.title).to eq('Sosync')
end
end
it 'has badges' do
......
......@@ -95,6 +95,10 @@ describe Gitlab::ImportExport::GroupTreeSaver do
expect(saved_group_json['boards']).not_to be_empty
end
it 'has board label list' do
expect(saved_group_json['boards'].first['lists']).not_to be_empty
end
it 'has group members' do
expect(saved_group_json['members']).not_to be_empty
end
......@@ -168,7 +172,8 @@ describe Gitlab::ImportExport::GroupTreeSaver do
create(:group_badge, group: group)
group_label = create(:group_label, group: group)
create(:label_priority, label: group_label, priority: 1)
create(:board, group: group)
board = create(:board, group: group)
create(:list, board: board, label: group_label)
create(:group_badge, group: group)
group
......
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