Commit b0b1b3de authored by Ash McKenzie's avatar Ash McKenzie

Merge branch 'jhyson/export-board-milestone' into 'master'

Export Board Milestones

See merge request gitlab-org/gitlab!24606
parents 7e0abff5 40ed66df
......@@ -3,7 +3,13 @@
class Milestone < ApplicationRecord
# Represents a "No Milestone" state used for filtering Issues and Merge
# Requests that have no milestone assigned.
MilestoneStruct = Struct.new(:title, :name, :id)
MilestoneStruct = Struct.new(:title, :name, :id) do
# Ensure these models match the interface required for exporting
def serializable_hash(_opts = {})
{ title: title, name: name, id: id }
end
end
None = MilestoneStruct.new('No Milestone', 'No Milestone', 0)
Any = MilestoneStruct.new('Any Milestone', '', -1)
Upcoming = MilestoneStruct.new('Upcoming', '#upcoming', -2)
......@@ -128,11 +134,12 @@ class Milestone < ApplicationRecord
reorder(nil).group(:state).count
end
def predefined_id?(id)
[Any.id, None.id, Upcoming.id, Started.id].include?(id)
end
def predefined?(milestone)
milestone == Any ||
milestone == None ||
milestone == Upcoming ||
milestone == Started
predefined_id?(milestone&.id)
end
end
......
---
title: Export Board Milestones in Group Export
merge_request: 24606
author:
type: added
......@@ -87,7 +87,8 @@
"created_at": "2019-11-20T17:27:41.118Z",
"updated_at": "2019-11-20T17:27:41.118Z",
"name": "first board",
"milestone_id": 7638,
"milestone_id": -2,
"milestone": {"id": -2, "name": "#upcoming", "title": "Upcoming"},
"group_id": 4351,
"weight": null,
"labels": [],
......@@ -153,6 +154,31 @@
}
}
]
},
{
"id": 57,
"project_id": null,
"created_at": "2019-11-20T17:27:41.118Z",
"updated_at": "2019-11-20T17:27:41.118Z",
"name": "second board",
"milestone_id": 7642,
"milestone": {
"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
},
"group_id": 4351,
"weight": null,
"labels": [],
"lists": []
}
],
"members": [
......
......@@ -46,5 +46,17 @@ describe Gitlab::ImportExport::Group::TreeRestorer do
expect(lists.map(&:list_type)).to contain_exactly('assignee', 'milestone')
end
end
context 'boards' do
it 'has user generated milestones' do
board = group.boards.find_by(name: 'second board')
expect(board.milestone.title).to eq 'v4.0'
end
it 'does not have predefined milestones' do
board = group.boards.find_by(name: 'first board')
expect(board.milestone).to be_nil
end
end
end
end
......@@ -138,6 +138,51 @@ describe Gitlab::ImportExport::Group::TreeSaver do
expect(assignee_list['user_id']).to eq(user.id)
end
end
context 'when there are boards with predefined milestones' do
let(:milestone) { Milestone::Upcoming }
before do
create(:board, group: group, milestone_id: milestone.id)
end
it 'saves the milestone data' do
expect_successful_save(group_tree_saver)
board_data = saved_group_json['boards'].last
expect(board_data).to include(
'milestone_id' => milestone.id,
'milestone' => {
'id' => milestone.id,
'name' => milestone.name,
'title' => milestone.title
}
)
end
end
context 'when there are boards with persisted milestones' do
let(:milestone) { create(:milestone) }
before do
create(:board, group: group, milestone: milestone)
end
it 'saves the milestone data' do
expect_successful_save(group_tree_saver)
board_data = saved_group_json['boards'].last
expect(board_data).to include(
'milestone_id' => milestone.id,
'milestone' => a_hash_including(
'id' => milestone.id,
'title' => milestone.title
)
)
end
end
end
def expect_successful_save(group_tree_saver)
......
......@@ -67,7 +67,7 @@ module Gitlab
# the relation_hash, updating references with new object IDs, mapping users using
# the "members_mapper" object, also updating notes if required.
def create
return if invalid_relation?
return if invalid_relation? || predefined_relation?
setup_base_models
setup_models
......@@ -89,6 +89,10 @@ module Gitlab
false
end
def predefined_relation?
relation_class.try(:predefined_id?, @relation_hash['id'])
end
def setup_models
raise NotImplementedError
end
......
......@@ -70,6 +70,7 @@ ee:
- :push_event_payload
- boards:
- :board_assignee
- :milestone
- labels:
- :priorities
- lists:
......
......@@ -33,6 +33,15 @@ describe Gitlab::ImportExport::Base::RelationFactory do
end
end
context 'when the relation is predefined' do
let(:relation_sym) { :milestone }
let(:relation_hash) { { 'name' => '#upcoming', 'title' => 'Upcoming', 'id' => -2 } }
it 'returns without creating a new relation' do
expect(subject).to be_nil
end
end
context 'when #setup_models is not implemented' do
it 'raises NotImplementedError' do
expect { subject }.to raise_error(NotImplementedError)
......
......@@ -189,7 +189,7 @@ describe Gitlab::ImportExport::Group::TreeSaver do
create(:group_badge, group: group)
group_label = create(:group_label, group: group)
create(:label_priority, label: group_label, priority: 1)
board = create(:board, group: group)
board = create(:board, group: group, milestone_id: Milestone::Upcoming.id)
create(:list, board: board, label: group_label)
create(:group_badge, group: group)
......
......@@ -3,6 +3,18 @@
require 'spec_helper'
describe Milestone do
describe 'MilestoneStruct#serializable_hash' do
let(:predefined_milestone) { described_class::MilestoneStruct.new('Test Milestone', '#test', 1) }
it 'presents the predefined milestone as a hash' do
expect(predefined_milestone.serializable_hash).to eq(
title: predefined_milestone.title,
name: predefined_milestone.name,
id: predefined_milestone.id
)
end
end
describe 'modules' do
context 'with a project' do
it_behaves_like 'AtomicInternalId' do
......@@ -179,6 +191,16 @@ describe Milestone do
end
end
describe '.predefined_id?' do
it 'returns true for a predefined Milestone ID' do
expect(Milestone.predefined_id?(described_class::Upcoming.id)).to be true
end
it 'returns false for a Milestone ID that is not predefined' do
expect(Milestone.predefined_id?(milestone.id)).to be false
end
end
describe '.order_by_name_asc' do
it 'sorts by name ascending' do
milestone1 = create(:milestone, title: 'Foo')
......
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