Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
e06142fc
Commit
e06142fc
authored
Oct 27, 2021
by
Doug Stull
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Split RelationTreeRestorer into group and project
- remove branching logic on if project or group
parent
43ad1fba
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
565 additions
and
310 deletions
+565
-310
.rubocop_manual_todo.yml
.rubocop_manual_todo.yml
+1
-1
lib/gitlab/import_export/group/relation_tree_restorer.rb
lib/gitlab/import_export/group/relation_tree_restorer.rb
+274
-0
lib/gitlab/import_export/project/relation_tree_restorer.rb
lib/gitlab/import_export/project/relation_tree_restorer.rb
+27
-0
lib/gitlab/import_export/project/sample/relation_tree_restorer.rb
...ab/import_export/project/sample/relation_tree_restorer.rb
+3
-3
lib/gitlab/import_export/relation_tree_restorer.rb
lib/gitlab/import_export/relation_tree_restorer.rb
+0
-280
spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb
...gitlab/import_export/group/relation_tree_restorer_spec.rb
+88
-0
spec/lib/gitlab/import_export/project/relation_tree_restorer_spec.rb
...tlab/import_export/project/relation_tree_restorer_spec.rb
+150
-0
spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
...port_export/project/sample/relation_tree_restorer_spec.rb
+22
-26
No files found.
.rubocop_manual_todo.yml
View file @
e06142fc
...
@@ -2459,7 +2459,7 @@ Database/MultipleDatabases:
...
@@ -2459,7 +2459,7 @@ Database/MultipleDatabases:
-
'
lib/gitlab/gitlab_import/importer.rb'
-
'
lib/gitlab/gitlab_import/importer.rb'
-
'
lib/gitlab/health_checks/db_check.rb'
-
'
lib/gitlab/health_checks/db_check.rb'
-
'
lib/gitlab/import_export/base/relation_factory.rb'
-
'
lib/gitlab/import_export/base/relation_factory.rb'
-
'
lib/gitlab/import_export/relation_tree_restorer.rb'
-
'
lib/gitlab/import_export/
group/
relation_tree_restorer.rb'
-
'
lib/gitlab/legacy_github_import/importer.rb'
-
'
lib/gitlab/legacy_github_import/importer.rb'
-
'
lib/gitlab/metrics/samplers/database_sampler.rb'
-
'
lib/gitlab/metrics/samplers/database_sampler.rb'
-
'
lib/gitlab/seeder.rb'
-
'
lib/gitlab/seeder.rb'
...
...
lib/gitlab/import_export/group/relation_tree_restorer.rb
0 → 100644
View file @
e06142fc
# frozen_string_literal: true
module
Gitlab
module
ImportExport
module
Group
class
RelationTreeRestorer
def
initialize
(
# rubocop:disable Metrics/ParameterLists
user
:,
shared
:,
relation_reader
:,
members_mapper
:,
object_builder
:,
relation_factory
:,
reader
:,
importable
:,
importable_attributes
:,
importable_path:
)
@user
=
user
@shared
=
shared
@importable
=
importable
@relation_reader
=
relation_reader
@members_mapper
=
members_mapper
@object_builder
=
object_builder
@relation_factory
=
relation_factory
@reader
=
reader
@importable_attributes
=
importable_attributes
@importable_path
=
importable_path
end
def
restore
ActiveRecord
::
Base
.
uncached
do
ActiveRecord
::
Base
.
no_touching
do
update_params!
BulkInsertableAssociations
.
with_bulk_insert
(
enabled:
bulk_insert_enabled
)
do
fix_ci_pipelines_not_sorted_on_legacy_project_json!
create_relations!
end
end
end
# ensure that we have latest version of the restore
@importable
.
reload
# rubocop:disable Cop/ActiveRecordAssociationReload
true
rescue
StandardError
=>
e
@shared
.
error
(
e
)
false
end
private
def
bulk_insert_enabled
false
end
# Loops through the tree of models defined in import_export.yml and
# finds them in the imported JSON so they can be instantiated and saved
# in the DB. The structure and relationships between models are guessed from
# the configuration yaml file too.
# Finally, it updates each attribute in the newly imported project/group.
def
create_relations!
relations
.
each
do
|
relation_key
,
relation_definition
|
process_relation!
(
relation_key
,
relation_definition
)
end
end
def
process_relation!
(
relation_key
,
relation_definition
)
@relation_reader
.
consume_relation
(
@importable_path
,
relation_key
).
each
do
|
data_hash
,
relation_index
|
process_relation_item!
(
relation_key
,
relation_definition
,
relation_index
,
data_hash
)
end
end
def
process_relation_item!
(
relation_key
,
relation_definition
,
relation_index
,
data_hash
)
relation_object
=
build_relation
(
relation_key
,
relation_definition
,
relation_index
,
data_hash
)
return
unless
relation_object
return
if
relation_invalid_for_importable?
(
relation_object
)
relation_object
.
assign_attributes
(
importable_class_sym
=>
@importable
)
import_failure_service
.
with_retry
(
action:
'relation_object.save!'
,
relation_key:
relation_key
,
relation_index:
relation_index
)
do
relation_object
.
save!
log_relation_creation
(
@importable
,
relation_key
,
relation_object
)
end
rescue
StandardError
=>
e
import_failure_service
.
log_import_failure
(
source:
'process_relation_item!'
,
relation_key:
relation_key
,
relation_index:
relation_index
,
exception:
e
)
end
def
import_failure_service
@import_failure_service
||=
ImportFailureService
.
new
(
@importable
)
end
def
relations
@relations
||=
@reader
.
attributes_finder
.
find_relations_tree
(
importable_class_sym
)
.
deep_stringify_keys
end
def
update_params!
params
=
@importable_attributes
.
except
(
*
relations
.
keys
.
map
(
&
:to_s
))
params
=
params
.
merge
(
present_override_params
)
# Cleaning all imported and overridden params
params
=
Gitlab
::
ImportExport
::
AttributeCleaner
.
clean
(
relation_hash:
params
,
relation_class:
importable_class
,
excluded_keys:
excluded_keys_for_relation
(
importable_class_sym
))
@importable
.
assign_attributes
(
params
)
modify_attributes
Gitlab
::
Timeless
.
timeless
(
@importable
)
do
@importable
.
save!
end
end
def
present_override_params
# we filter out the empty strings from the overrides
# keeping the default values configured
override_params
&
.
transform_values
do
|
value
|
value
.
is_a?
(
String
)
?
value
.
presence
:
value
end
&
.
compact
end
def
override_params
@importable_override_params
||=
importable_override_params
end
def
importable_override_params
if
@importable
.
respond_to?
(
:import_data
)
@importable
.
import_data
&
.
data
&
.
fetch
(
'override_params'
,
nil
)
||
{}
else
{}
end
end
def
modify_attributes
# no-op to be overridden on inheritance
end
def
build_relations
(
relation_key
,
relation_definition
,
relation_index
,
data_hashes
)
data_hashes
.
map
{
|
data_hash
|
build_relation
(
relation_key
,
relation_definition
,
relation_index
,
data_hash
)
}
.
tap
{
|
entries
|
entries
.
compact!
}
end
def
build_relation
(
relation_key
,
relation_definition
,
relation_index
,
data_hash
)
# TODO: This is hack to not create relation for the author
# Rather make `RelationFactory#set_note_author` to take care of that
return
data_hash
if
relation_key
==
'author'
||
already_restored?
(
data_hash
)
# create relation objects recursively for all sub-objects
relation_definition
.
each
do
|
sub_relation_key
,
sub_relation_definition
|
transform_sub_relations!
(
data_hash
,
sub_relation_key
,
sub_relation_definition
,
relation_index
)
end
relation
=
@relation_factory
.
create
(
**
relation_factory_params
(
relation_key
,
relation_index
,
data_hash
))
if
relation
&&
!
relation
.
valid?
@shared
.
logger
.
warn
(
message:
"[Project/Group Import] Invalid object relation built"
,
relation_key:
relation_key
,
relation_index:
relation_index
,
relation_class:
relation
.
class
.
name
,
error_messages:
relation
.
errors
.
full_messages
.
join
(
". "
)
)
end
relation
end
# Since we update the data hash in place as we restore relation items,
# and since we also de-duplicate items, we might encounter items that
# have already been restored in a previous iteration.
def
already_restored?
(
relation_item
)
!
relation_item
.
is_a?
(
Hash
)
end
def
transform_sub_relations!
(
data_hash
,
sub_relation_key
,
sub_relation_definition
,
relation_index
)
sub_data_hash
=
data_hash
[
sub_relation_key
]
return
unless
sub_data_hash
# if object is a hash we can create simple object
# as it means that this is 1-to-1 vs 1-to-many
current_item
=
if
sub_data_hash
.
is_a?
(
Array
)
build_relations
(
sub_relation_key
,
sub_relation_definition
,
relation_index
,
sub_data_hash
).
presence
else
build_relation
(
sub_relation_key
,
sub_relation_definition
,
relation_index
,
sub_data_hash
)
end
if
current_item
data_hash
[
sub_relation_key
]
=
current_item
else
data_hash
.
delete
(
sub_relation_key
)
end
end
def
relation_invalid_for_importable?
(
_relation_object
)
false
end
def
excluded_keys_for_relation
(
relation
)
@reader
.
attributes_finder
.
find_excluded_keys
(
relation
)
end
def
importable_class
@importable
.
class
end
def
importable_class_sym
importable_class
.
to_s
.
downcase
.
to_sym
end
def
relation_factory_params
(
relation_key
,
relation_index
,
data_hash
)
{
relation_index:
relation_index
,
relation_sym:
relation_key
.
to_sym
,
relation_hash:
data_hash
,
importable:
@importable
,
members_mapper:
@members_mapper
,
object_builder:
@object_builder
,
user:
@user
,
excluded_keys:
excluded_keys_for_relation
(
relation_key
)
}
end
# Temporary fix for https://gitlab.com/gitlab-org/gitlab/-/issues/27883 when import from legacy project.json
# This should be removed once legacy JSON format is deprecated.
# Ndjson export file will fix the order during project export.
def
fix_ci_pipelines_not_sorted_on_legacy_project_json!
return
unless
@relation_reader
.
legacy?
@relation_reader
.
sort_ci_pipelines_by_id
end
# Enable logging of each top-level relation creation when Importing
# into a Group if feature flag is enabled
def
log_relation_creation
(
importable
,
relation_key
,
relation_object
)
root_ancestor_group
=
importable
.
try
(
:root_ancestor
)
return
unless
root_ancestor_group
return
unless
root_ancestor_group
.
instance_of?
(
::
Group
)
return
unless
Feature
.
enabled?
(
:log_import_export_relation_creation
,
root_ancestor_group
)
@shared
.
logger
.
info
(
importable_type:
importable
.
class
.
to_s
,
importable_id:
importable
.
id
,
relation_key:
relation_key
,
relation_id:
relation_object
.
id
,
author_id:
relation_object
.
try
(
:author_id
),
message:
'[Project/Group Import] Created new object relation'
)
end
end
end
end
end
lib/gitlab/import_export/project/relation_tree_restorer.rb
0 → 100644
View file @
e06142fc
# frozen_string_literal: true
module
Gitlab
module
ImportExport
module
Project
class
RelationTreeRestorer
<
ImportExport
::
Group
::
RelationTreeRestorer
# Relations which cannot be saved at project level (and have a group assigned)
GROUP_MODELS
=
[
GroupLabel
,
Milestone
,
Epic
].
freeze
private
def
bulk_insert_enabled
true
end
def
modify_attributes
@importable
.
reconcile_shared_runners_setting!
@importable
.
drop_visibility_level!
end
def
relation_invalid_for_importable?
(
relation_object
)
GROUP_MODELS
.
include?
(
relation_object
.
class
)
&&
relation_object
.
group_id
end
end
end
end
end
lib/gitlab/import_export/project/sample/relation_tree_restorer.rb
View file @
e06142fc
...
@@ -4,7 +4,7 @@ module Gitlab
...
@@ -4,7 +4,7 @@ module Gitlab
module
ImportExport
module
ImportExport
module
Project
module
Project
module
Sample
module
Sample
class
RelationTreeRestorer
<
ImportExport
::
RelationTreeRestorer
class
RelationTreeRestorer
<
ImportExport
::
Project
::
RelationTreeRestorer
def
initialize
(
...
)
def
initialize
(
...
)
super
(
...
)
super
(
...
)
...
@@ -18,10 +18,10 @@ module Gitlab
...
@@ -18,10 +18,10 @@ module Gitlab
end
end
def
dates
def
dates
return
[]
if
relation_reader
.
legacy?
return
[]
if
@
relation_reader
.
legacy?
RelationFactory
::
DATE_MODELS
.
flat_map
do
|
tag
|
RelationFactory
::
DATE_MODELS
.
flat_map
do
|
tag
|
relation_reader
.
consume_relation
(
@importable_path
,
tag
,
mark_as_consumed:
false
).
map
do
|
model
|
@
relation_reader
.
consume_relation
(
@importable_path
,
tag
,
mark_as_consumed:
false
).
map
do
|
model
|
model
.
first
[
'due_date'
]
model
.
first
[
'due_date'
]
end
end
end
end
...
...
lib/gitlab/import_export/relation_tree_restorer.rb
deleted
100644 → 0
View file @
43ad1fba
# frozen_string_literal: true
module
Gitlab
module
ImportExport
class
RelationTreeRestorer
# Relations which cannot be saved at project level (and have a group assigned)
GROUP_MODELS
=
[
GroupLabel
,
Milestone
,
Epic
].
freeze
attr_reader
:user
attr_reader
:shared
attr_reader
:importable
attr_reader
:relation_reader
def
initialize
(
# rubocop:disable Metrics/ParameterLists
user
:,
shared
:,
relation_reader
:,
members_mapper
:,
object_builder
:,
relation_factory
:,
reader
:,
importable
:,
importable_attributes
:,
importable_path:
)
@user
=
user
@shared
=
shared
@importable
=
importable
@relation_reader
=
relation_reader
@members_mapper
=
members_mapper
@object_builder
=
object_builder
@relation_factory
=
relation_factory
@reader
=
reader
@importable_attributes
=
importable_attributes
@importable_path
=
importable_path
end
def
restore
ActiveRecord
::
Base
.
uncached
do
ActiveRecord
::
Base
.
no_touching
do
update_params!
BulkInsertableAssociations
.
with_bulk_insert
(
enabled:
project?
)
do
fix_ci_pipelines_not_sorted_on_legacy_project_json!
create_relations!
end
end
end
# ensure that we have latest version of the restore
@importable
.
reload
# rubocop:disable Cop/ActiveRecordAssociationReload
true
rescue
StandardError
=>
e
@shared
.
error
(
e
)
false
end
private
def
project?
@importable
.
instance_of?
(
::
Project
)
end
# Loops through the tree of models defined in import_export.yml and
# finds them in the imported JSON so they can be instantiated and saved
# in the DB. The structure and relationships between models are guessed from
# the configuration yaml file too.
# Finally, it updates each attribute in the newly imported project/group.
def
create_relations!
relations
.
each
do
|
relation_key
,
relation_definition
|
process_relation!
(
relation_key
,
relation_definition
)
end
end
def
process_relation!
(
relation_key
,
relation_definition
)
@relation_reader
.
consume_relation
(
@importable_path
,
relation_key
).
each
do
|
data_hash
,
relation_index
|
process_relation_item!
(
relation_key
,
relation_definition
,
relation_index
,
data_hash
)
end
end
def
process_relation_item!
(
relation_key
,
relation_definition
,
relation_index
,
data_hash
)
relation_object
=
build_relation
(
relation_key
,
relation_definition
,
relation_index
,
data_hash
)
return
unless
relation_object
return
if
project?
&&
group_model?
(
relation_object
)
relation_object
.
assign_attributes
(
importable_class_sym
=>
@importable
)
import_failure_service
.
with_retry
(
action:
'relation_object.save!'
,
relation_key:
relation_key
,
relation_index:
relation_index
)
do
relation_object
.
save!
log_relation_creation
(
@importable
,
relation_key
,
relation_object
)
end
rescue
StandardError
=>
e
import_failure_service
.
log_import_failure
(
source:
'process_relation_item!'
,
relation_key:
relation_key
,
relation_index:
relation_index
,
exception:
e
)
end
def
import_failure_service
@import_failure_service
||=
ImportFailureService
.
new
(
@importable
)
end
def
relations
@relations
||=
@reader
.
attributes_finder
.
find_relations_tree
(
importable_class_sym
)
.
deep_stringify_keys
end
def
update_params!
params
=
@importable_attributes
.
except
(
*
relations
.
keys
.
map
(
&
:to_s
))
params
=
params
.
merge
(
present_override_params
)
# Cleaning all imported and overridden params
params
=
Gitlab
::
ImportExport
::
AttributeCleaner
.
clean
(
relation_hash:
params
,
relation_class:
importable_class
,
excluded_keys:
excluded_keys_for_relation
(
importable_class_sym
))
@importable
.
assign_attributes
(
params
)
modify_attributes
Gitlab
::
Timeless
.
timeless
(
@importable
)
do
@importable
.
save!
end
end
def
present_override_params
# we filter out the empty strings from the overrides
# keeping the default values configured
override_params
&
.
transform_values
do
|
value
|
value
.
is_a?
(
String
)
?
value
.
presence
:
value
end
&
.
compact
end
def
override_params
@importable_override_params
||=
importable_override_params
end
def
importable_override_params
if
@importable
.
respond_to?
(
:import_data
)
@importable
.
import_data
&
.
data
&
.
fetch
(
'override_params'
,
nil
)
||
{}
else
{}
end
end
def
modify_attributes
return
unless
project?
@importable
.
reconcile_shared_runners_setting!
@importable
.
drop_visibility_level!
end
def
build_relations
(
relation_key
,
relation_definition
,
relation_index
,
data_hashes
)
data_hashes
.
map
{
|
data_hash
|
build_relation
(
relation_key
,
relation_definition
,
relation_index
,
data_hash
)
}
.
tap
{
|
entries
|
entries
.
compact!
}
end
def
build_relation
(
relation_key
,
relation_definition
,
relation_index
,
data_hash
)
# TODO: This is hack to not create relation for the author
# Rather make `RelationFactory#set_note_author` to take care of that
return
data_hash
if
relation_key
==
'author'
||
already_restored?
(
data_hash
)
# create relation objects recursively for all sub-objects
relation_definition
.
each
do
|
sub_relation_key
,
sub_relation_definition
|
transform_sub_relations!
(
data_hash
,
sub_relation_key
,
sub_relation_definition
,
relation_index
)
end
relation
=
@relation_factory
.
create
(
**
relation_factory_params
(
relation_key
,
relation_index
,
data_hash
))
if
relation
&&
!
relation
.
valid?
@shared
.
logger
.
warn
(
message:
"[Project/Group Import] Invalid object relation built"
,
relation_key:
relation_key
,
relation_index:
relation_index
,
relation_class:
relation
.
class
.
name
,
error_messages:
relation
.
errors
.
full_messages
.
join
(
". "
)
)
end
relation
end
# Since we update the data hash in place as we restore relation items,
# and since we also de-duplicate items, we might encounter items that
# have already been restored in a previous iteration.
def
already_restored?
(
relation_item
)
!
relation_item
.
is_a?
(
Hash
)
end
def
transform_sub_relations!
(
data_hash
,
sub_relation_key
,
sub_relation_definition
,
relation_index
)
sub_data_hash
=
data_hash
[
sub_relation_key
]
return
unless
sub_data_hash
# if object is a hash we can create simple object
# as it means that this is 1-to-1 vs 1-to-many
current_item
=
if
sub_data_hash
.
is_a?
(
Array
)
build_relations
(
sub_relation_key
,
sub_relation_definition
,
relation_index
,
sub_data_hash
).
presence
else
build_relation
(
sub_relation_key
,
sub_relation_definition
,
relation_index
,
sub_data_hash
)
end
if
current_item
data_hash
[
sub_relation_key
]
=
current_item
else
data_hash
.
delete
(
sub_relation_key
)
end
end
def
group_model?
(
relation_object
)
GROUP_MODELS
.
include?
(
relation_object
.
class
)
&&
relation_object
.
group_id
end
def
excluded_keys_for_relation
(
relation
)
@reader
.
attributes_finder
.
find_excluded_keys
(
relation
)
end
def
importable_class
@importable
.
class
end
def
importable_class_sym
importable_class
.
to_s
.
downcase
.
to_sym
end
def
relation_factory_params
(
relation_key
,
relation_index
,
data_hash
)
{
relation_index:
relation_index
,
relation_sym:
relation_key
.
to_sym
,
relation_hash:
data_hash
,
importable:
@importable
,
members_mapper:
@members_mapper
,
object_builder:
@object_builder
,
user:
@user
,
excluded_keys:
excluded_keys_for_relation
(
relation_key
)
}
end
# Temporary fix for https://gitlab.com/gitlab-org/gitlab/-/issues/27883 when import from legacy project.json
# This should be removed once legacy JSON format is deprecated.
# Ndjson export file will fix the order during project export.
def
fix_ci_pipelines_not_sorted_on_legacy_project_json!
return
unless
relation_reader
.
legacy?
relation_reader
.
sort_ci_pipelines_by_id
end
# Enable logging of each top-level relation creation when Importing
# into a Group if feature flag is enabled
def
log_relation_creation
(
importable
,
relation_key
,
relation_object
)
root_ancestor_group
=
importable
.
try
(
:root_ancestor
)
return
unless
root_ancestor_group
return
unless
root_ancestor_group
.
instance_of?
(
::
Group
)
return
unless
Feature
.
enabled?
(
:log_import_export_relation_creation
,
root_ancestor_group
)
@shared
.
logger
.
info
(
importable_type:
importable
.
class
.
to_s
,
importable_id:
importable
.
id
,
relation_key:
relation_key
,
relation_id:
relation_object
.
id
,
author_id:
relation_object
.
try
(
:author_id
),
message:
'[Project/Group Import] Created new object relation'
)
end
end
end
end
spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb
0 → 100644
View file @
e06142fc
# frozen_string_literal: true
# This spec is a lightweight version of:
# * project/tree_restorer_spec.rb
#
# In depth testing is being done in the above specs.
# This spec tests that restore project works
# but does not have 100% relation coverage.
require
'spec_helper'
RSpec
.
describe
Gitlab
::
ImportExport
::
Group
::
RelationTreeRestorer
do
let_it_be
(
:group
)
{
create
(
:group
)
}
let_it_be
(
:importable
)
{
create
(
:group
,
parent:
group
)
}
include_context
'relation tree restorer shared context'
do
let
(
:importable_name
)
{
nil
}
end
let
(
:path
)
{
'spec/fixtures/lib/gitlab/import_export/group_exports/no_children/group.json'
}
let
(
:relation_reader
)
do
Gitlab
::
ImportExport
::
Json
::
LegacyReader
::
File
.
new
(
path
,
relation_names:
reader
.
group_relation_names
)
end
let
(
:reader
)
do
Gitlab
::
ImportExport
::
Reader
.
new
(
shared:
shared
,
config:
Gitlab
::
ImportExport
::
Config
.
new
(
config:
Gitlab
::
ImportExport
.
legacy_group_config_file
).
to_h
)
end
let
(
:relation_tree_restorer
)
do
described_class
.
new
(
user:
user
,
shared:
shared
,
relation_reader:
relation_reader
,
object_builder:
Gitlab
::
ImportExport
::
Group
::
ObjectBuilder
,
members_mapper:
members_mapper
,
relation_factory:
Gitlab
::
ImportExport
::
Group
::
RelationFactory
,
reader:
reader
,
importable:
importable
,
importable_path:
nil
,
importable_attributes:
attributes
)
end
subject
{
relation_tree_restorer
.
restore
}
shared_examples
'logging of relations creation'
do
context
'when log_import_export_relation_creation feature flag is enabled'
do
before
do
stub_feature_flags
(
log_import_export_relation_creation:
group
)
end
it
'logs top-level relation creation'
do
expect
(
shared
.
logger
)
.
to
receive
(
:info
)
.
with
(
hash_including
(
message:
'[Project/Group Import] Created new object relation'
))
.
at_least
(
:once
)
subject
end
end
context
'when log_import_export_relation_creation feature flag is disabled'
do
before
do
stub_feature_flags
(
log_import_export_relation_creation:
false
)
end
it
'does not log top-level relation creation'
do
expect
(
shared
.
logger
)
.
to
receive
(
:info
)
.
with
(
hash_including
(
message:
'[Project/Group Import] Created new object relation'
))
.
never
subject
end
end
end
it
'restores group tree'
do
expect
(
subject
).
to
eq
(
true
)
end
include_examples
'logging of relations creation'
end
spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
→
spec/lib/gitlab/import_export/
project/
relation_tree_restorer_spec.rb
View file @
e06142fc
...
@@ -9,20 +9,27 @@
...
@@ -9,20 +9,27 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Gitlab
::
ImportExport
::
RelationTreeRestorer
do
RSpec
.
describe
Gitlab
::
ImportExport
::
Project
::
RelationTreeRestorer
do
include_context
'relation tree restorer shared context'
let_it_be
(
:importable
,
reload:
true
)
do
create
(
:project
,
:builds_enabled
,
:issues_disabled
,
name:
'project'
,
path:
'project'
)
end
include_context
'relation tree restorer shared context'
do
let
(
:importable_name
)
{
'project'
}
end
let
(
:reader
)
{
Gitlab
::
ImportExport
::
Reader
.
new
(
shared:
shared
)
}
let
(
:relation_tree_restorer
)
do
let
(
:relation_tree_restorer
)
do
described_class
.
new
(
described_class
.
new
(
user:
user
,
user:
user
,
shared:
shared
,
shared:
shared
,
relation_reader:
relation_reader
,
relation_reader:
relation_reader
,
object_builder:
object_b
uilder
,
object_builder:
Gitlab
::
ImportExport
::
Project
::
ObjectB
uilder
,
members_mapper:
members_mapper
,
members_mapper:
members_mapper
,
relation_factory:
relation_f
actory
,
relation_factory:
Gitlab
::
ImportExport
::
Project
::
RelationF
actory
,
reader:
reader
,
reader:
reader
,
importable:
importable
,
importable:
importable
,
importable_path:
importable_path
,
importable_path:
'project'
,
importable_attributes:
attributes
importable_attributes:
attributes
)
)
end
end
...
@@ -54,7 +61,7 @@ RSpec.describe Gitlab::ImportExport::RelationTreeRestorer do
...
@@ -54,7 +61,7 @@ RSpec.describe Gitlab::ImportExport::RelationTreeRestorer do
end
end
it
'logs top-level relation creation'
do
it
'logs top-level relation creation'
do
expect
(
relation_tree_restorer
.
shared
.
logger
)
expect
(
shared
.
logger
)
.
to
receive
(
:info
)
.
to
receive
(
:info
)
.
with
(
hash_including
(
message:
'[Project/Group Import] Created new object relation'
))
.
with
(
hash_including
(
message:
'[Project/Group Import] Created new object relation'
))
.
at_least
(
:once
)
.
at_least
(
:once
)
...
@@ -69,7 +76,7 @@ RSpec.describe Gitlab::ImportExport::RelationTreeRestorer do
...
@@ -69,7 +76,7 @@ RSpec.describe Gitlab::ImportExport::RelationTreeRestorer do
end
end
it
'does not log top-level relation creation'
do
it
'does not log top-level relation creation'
do
expect
(
relation_tree_restorer
.
shared
.
logger
)
expect
(
shared
.
logger
)
.
to
receive
(
:info
)
.
to
receive
(
:info
)
.
with
(
hash_including
(
message:
'[Project/Group Import] Created new object relation'
))
.
with
(
hash_including
(
message:
'[Project/Group Import] Created new object relation'
))
.
never
.
never
...
@@ -79,106 +86,65 @@ RSpec.describe Gitlab::ImportExport::RelationTreeRestorer do
...
@@ -79,106 +86,65 @@ RSpec.describe Gitlab::ImportExport::RelationTreeRestorer do
end
end
end
end
context
'when restoring a project'
do
context
'with legacy reader'
do
let_it_be
(
:importable
,
reload:
true
)
do
let
(
:path
)
{
'spec/fixtures/lib/gitlab/import_export/complex/project.json'
}
create
(
:project
,
:builds_enabled
,
:issues_disabled
,
name:
'project'
,
path:
'project'
)
let
(
:relation_reader
)
do
Gitlab
::
ImportExport
::
Json
::
LegacyReader
::
File
.
new
(
path
,
relation_names:
reader
.
project_relation_names
,
allowed_path:
'project'
)
end
end
let
(
:importable_name
)
{
'project'
}
let
(
:attributes
)
{
relation_reader
.
consume_attributes
(
'project'
)
}
let
(
:importable_path
)
{
'project'
}
let
(
:object_builder
)
{
Gitlab
::
ImportExport
::
Project
::
ObjectBuilder
}
let
(
:relation_factory
)
{
Gitlab
::
ImportExport
::
Project
::
RelationFactory
}
let
(
:reader
)
{
Gitlab
::
ImportExport
::
Reader
.
new
(
shared:
shared
)
}
context
'using legacy reader'
do
let
(
:path
)
{
'spec/fixtures/lib/gitlab/import_export/complex/project.json'
}
let
(
:relation_reader
)
do
Gitlab
::
ImportExport
::
Json
::
LegacyReader
::
File
.
new
(
path
,
relation_names:
reader
.
project_relation_names
,
allowed_path:
'project'
)
end
let
(
:attributes
)
{
relation_reader
.
consume_attributes
(
'project'
)
}
it_behaves_like
'import project successfully'
context
'logging of relations creation'
do
it_behaves_like
'import project successfully'
let_it_be
(
:group
)
{
create
(
:group
)
}
let_it_be
(
:importable
)
do
create
(
:project
,
:builds_enabled
,
:issues_disabled
,
name:
'project'
,
path:
'project'
,
group:
group
)
end
include_examples
'logging of relations creation'
context
'with logging of relations creation'
do
let_it_be
(
:group
)
{
create
(
:group
)
}
let_it_be
(
:importable
)
do
create
(
:project
,
:builds_enabled
,
:issues_disabled
,
name:
'project'
,
path:
'project'
,
group:
group
)
end
end
end
context
'using ndjson reader'
do
include_examples
'logging of relations creation'
let
(
:path
)
{
'spec/fixtures/lib/gitlab/import_export/complex/tree'
}
end
let
(
:relation_reader
)
{
Gitlab
::
ImportExport
::
Json
::
NdjsonReader
.
new
(
path
)
}
end
it_behaves_like
'import project successfully'
context
'when inside a group'
do
context
'with ndjson reader'
do
let_it_be
(
:group
)
do
let
(
:path
)
{
'spec/fixtures/lib/gitlab/import_export/complex/tree'
}
create
(
:group
,
:disabled_and_unoverridable
)
let
(
:relation_reader
)
{
Gitlab
::
ImportExport
::
Json
::
NdjsonReader
.
new
(
path
)
}
end
before
do
it_behaves_like
'import project successfully'
importable
.
update!
(
shared_runners_enabled:
false
,
group:
group
)
end
it_behaves_like
'import project successfully'
context
'when inside a group'
do
let_it_be
(
:group
)
do
create
(
:group
,
:disabled_and_unoverridable
)
end
end
end
context
'with invalid relations'
do
before
do
let
(
:path
)
{
'spec/fixtures/lib/gitlab/import_export/project_with_invalid_relations/tree'
}
importable
.
update!
(
shared_runners_enabled:
false
,
group:
group
)
let
(
:relation_reader
)
{
Gitlab
::
ImportExport
::
Json
::
NdjsonReader
.
new
(
path
)
}
it
'logs the invalid relation and its errors'
do
expect
(
relation_tree_restorer
.
shared
.
logger
)
.
to
receive
(
:warn
)
.
with
(
error_messages:
"Title can't be blank. Title is invalid"
,
message:
'[Project/Group Import] Invalid object relation built'
,
relation_class:
'ProjectLabel'
,
relation_index:
0
,
relation_key:
'labels'
).
once
relation_tree_restorer
.
restore
end
end
end
end
context
'when restoring a group'
do
let_it_be
(
:group
)
{
create
(
:group
)
}
let_it_be
(
:importable
)
{
create
(
:group
,
parent:
group
)
}
let
(
:path
)
{
'spec/fixtures/lib/gitlab/import_export/group_exports/no_children/group.json'
}
let
(
:importable_name
)
{
nil
}
let
(
:importable_path
)
{
nil
}
let
(
:object_builder
)
{
Gitlab
::
ImportExport
::
Group
::
ObjectBuilder
}
let
(
:relation_factory
)
{
Gitlab
::
ImportExport
::
Group
::
RelationFactory
}
let
(
:relation_reader
)
do
Gitlab
::
ImportExport
::
Json
::
LegacyReader
::
File
.
new
(
path
,
relation_names:
reader
.
group_relation_names
)
end
let
(
:reader
)
do
it_behaves_like
'import project successfully'
Gitlab
::
ImportExport
::
Reader
.
new
(
shared:
shared
,
config:
Gitlab
::
ImportExport
::
Config
.
new
(
config:
Gitlab
::
ImportExport
.
legacy_group_config_file
).
to_h
)
end
end
end
it
'restores group tree'
do
context
'with invalid relations'
do
expect
(
subject
).
to
eq
(
true
)
let
(
:path
)
{
'spec/fixtures/lib/gitlab/import_export/project_with_invalid_relations/tree'
}
let
(
:relation_reader
)
{
Gitlab
::
ImportExport
::
Json
::
NdjsonReader
.
new
(
path
)
}
it
'logs the invalid relation and its errors'
do
expect
(
shared
.
logger
)
.
to
receive
(
:warn
)
.
with
(
error_messages:
"Title can't be blank. Title is invalid"
,
message:
'[Project/Group Import] Invalid object relation built'
,
relation_class:
'ProjectLabel'
,
relation_index:
0
,
relation_key:
'labels'
).
once
relation_tree_restorer
.
restore
end
end
include_examples
'logging of relations creation'
end
end
end
end
spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
View file @
e06142fc
...
@@ -10,19 +10,26 @@
...
@@ -10,19 +10,26 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Gitlab
::
ImportExport
::
Project
::
Sample
::
RelationTreeRestorer
do
RSpec
.
describe
Gitlab
::
ImportExport
::
Project
::
Sample
::
RelationTreeRestorer
do
include_context
'relation tree restorer shared context'
let_it_be
(
:importable
)
{
create
(
:project
,
:builds_enabled
,
:issues_disabled
,
name:
'project'
,
path:
'project'
)
}
include_context
'relation tree restorer shared context'
do
let
(
:importable_name
)
{
'project'
}
end
let
(
:reader
)
{
Gitlab
::
ImportExport
::
Reader
.
new
(
shared:
shared
)
}
let
(
:path
)
{
'spec/fixtures/lib/gitlab/import_export/sample_data/tree'
}
let
(
:relation_reader
)
{
Gitlab
::
ImportExport
::
Json
::
NdjsonReader
.
new
(
path
)
}
let
(
:sample_data_relation_tree_restorer
)
do
let
(
:sample_data_relation_tree_restorer
)
do
described_class
.
new
(
described_class
.
new
(
user:
user
,
user:
user
,
shared:
shared
,
shared:
shared
,
relation_reader:
relation_reader
,
relation_reader:
relation_reader
,
object_builder:
object_b
uilder
,
object_builder:
Gitlab
::
ImportExport
::
Project
::
ObjectB
uilder
,
members_mapper:
members_mapper
,
members_mapper:
members_mapper
,
relation_factory:
relation_f
actory
,
relation_factory:
Gitlab
::
ImportExport
::
Project
::
Sample
::
RelationF
actory
,
reader:
reader
,
reader:
reader
,
importable:
importable
,
importable:
importable
,
importable_path:
importable_path
,
importable_path:
'project'
,
importable_attributes:
attributes
importable_attributes:
attributes
)
)
end
end
...
@@ -69,32 +76,21 @@ RSpec.describe Gitlab::ImportExport::Project::Sample::RelationTreeRestorer do
...
@@ -69,32 +76,21 @@ RSpec.describe Gitlab::ImportExport::Project::Sample::RelationTreeRestorer do
end
end
end
end
context
'when restoring a project'
do
it
'initializes relation_factory with date_calculator as parameter'
do
let
(
:importable
)
{
create
(
:project
,
:builds_enabled
,
:issues_disabled
,
name:
'project'
,
path:
'project'
)
}
expect
(
Gitlab
::
ImportExport
::
Project
::
Sample
::
RelationFactory
).
to
receive
(
:create
).
with
(
hash_including
(
:date_calculator
)).
at_least
(
:once
).
times
let
(
:importable_name
)
{
'project'
}
let
(
:importable_path
)
{
'project'
}
let
(
:object_builder
)
{
Gitlab
::
ImportExport
::
Project
::
ObjectBuilder
}
let
(
:relation_factory
)
{
Gitlab
::
ImportExport
::
Project
::
Sample
::
RelationFactory
}
let
(
:reader
)
{
Gitlab
::
ImportExport
::
Reader
.
new
(
shared:
shared
)
}
let
(
:path
)
{
'spec/fixtures/lib/gitlab/import_export/sample_data/tree'
}
let
(
:relation_reader
)
{
Gitlab
::
ImportExport
::
Json
::
NdjsonReader
.
new
(
path
)
}
it
'initializes relation_factory with date_calculator as parameter'
do
expect
(
Gitlab
::
ImportExport
::
Project
::
Sample
::
RelationFactory
).
to
receive
(
:create
).
with
(
hash_including
(
:date_calculator
)).
at_least
(
:once
).
times
subject
subject
end
end
context
'when relation tree restorer is initialized'
do
context
'when relation tree restorer is initialized'
do
it
'initializes date calculator with due dates'
do
it
'initializes date calculator with due dates'
do
expect
(
Gitlab
::
ImportExport
::
Project
::
Sample
::
DateCalculator
).
to
receive
(
:new
).
with
(
Array
)
expect
(
Gitlab
::
ImportExport
::
Project
::
Sample
::
DateCalculator
).
to
receive
(
:new
).
with
(
Array
)
sample_data_relation_tree_restorer
sample_data_relation_tree_restorer
end
end
end
end
context
'using ndjson reader'
do
context
'using ndjson reader'
do
it_behaves_like
'import project successfully'
it_behaves_like
'import project successfully'
end
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment