From 798ba98818bfaeea1d0982a6e21fd9b2ac077fc8 Mon Sep 17 00:00:00 2001 From: Luke Duncalfe <lduncalfe@eml.cc> Date: Fri, 10 May 2024 15:30:53 +1200 Subject: [PATCH] Set imported_from for Direct Transfer objects Sets the `imported_from` for objects imported in Direct Transfer. The objects that need this to be set are listed in https://gitlab.com/gitlab-org/gitlab/-/issues/424454. Changelog: added --- .../concerns/import/has_import_source.rb | 4 +++- lib/bulk_imports/ndjson_pipeline.rb | 3 ++- .../import_export/base/relation_factory.rb | 9 ++++++- spec/lib/bulk_imports/ndjson_pipeline_spec.rb | 3 ++- .../base/relation_factory_spec.rb | 24 +++++++++++++++++-- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/app/models/concerns/import/has_import_source.rb b/app/models/concerns/import/has_import_source.rb index f617c7accc386..cdede6ddc7740 100644 --- a/app/models/concerns/import/has_import_source.rb +++ b/app/models/concerns/import/has_import_source.rb @@ -1,12 +1,14 @@ # frozen_string_literal: true module Import + SOURCE_DIRECT_TRANSFER = :gitlab_migration # aka BulkImports + module HasImportSource extend ActiveSupport::Concern IMPORT_SOURCES = { none: 0, # not imported - gitlab_migration: 1, # aka direct transfer & bulk_import + SOURCE_DIRECT_TRANSFER => 1, gitlab_project: 2, # aka gitlab import/export github: 3, bitbucket: 4, # aka bitbucket cloud diff --git a/lib/bulk_imports/ndjson_pipeline.rb b/lib/bulk_imports/ndjson_pipeline.rb index d7976389c80ee..a038d445f0ba9 100644 --- a/lib/bulk_imports/ndjson_pipeline.rb +++ b/lib/bulk_imports/ndjson_pipeline.rb @@ -26,7 +26,8 @@ def transform(context, data) members_mapper: members_mapper, object_builder: object_builder, user: context.current_user, - excluded_keys: import_export_config.relation_excluded_keys(key) + excluded_keys: import_export_config.relation_excluded_keys(key), + import_source: Import::SOURCE_DIRECT_TRANSFER ) end diff --git a/lib/gitlab/import_export/base/relation_factory.rb b/lib/gitlab/import_export/base/relation_factory.rb index c3021f034cd57..966fd15270e9b 100644 --- a/lib/gitlab/import_export/base/relation_factory.rb +++ b/lib/gitlab/import_export/base/relation_factory.rb @@ -46,7 +46,8 @@ def self.relation_class(relation_name) relation_name.to_s.constantize end - def initialize(relation_sym:, relation_index:, relation_hash:, members_mapper:, object_builder:, user:, importable:, excluded_keys: []) + # rubocop:disable Metrics/ParameterLists -- Keyword arguments are not adding complexity to initializer + def initialize(relation_sym:, relation_index:, relation_hash:, members_mapper:, object_builder:, user:, importable:, excluded_keys: [], import_source: nil) @relation_sym = relation_sym @relation_name = self.class.overrides[relation_sym]&.to_sym || relation_sym @relation_index = relation_index @@ -55,6 +56,7 @@ def initialize(relation_sym:, relation_index:, relation_hash:, members_mapper:, @object_builder = object_builder @user = user @importable = importable + @import_source = import_source @imported_object_retries = 0 @relation_hash[importable_column_name] = @importable.id @original_user = {} @@ -67,6 +69,7 @@ def initialize(relation_sym:, relation_index:, relation_hash:, members_mapper:, # from the object attributes and the export will fail. @relation_hash.except!(*excluded_keys) end + # rubocop:enable Metrics/ParameterLists # Creates an object from an actual model with name "relation_sym" with params from # the relation_hash, updating references with new object IDs, mapping users using @@ -182,6 +185,10 @@ def imported_object existing_or_new_object.importing = true end + if @import_source && existing_or_new_object.respond_to?(:imported_from) + existing_or_new_object.imported_from = @import_source + end + existing_or_new_object rescue ActiveRecord::RecordNotUnique # as the operation is not atomic, retry in the unlikely scenario an INSERT is diff --git a/spec/lib/bulk_imports/ndjson_pipeline_spec.rb b/spec/lib/bulk_imports/ndjson_pipeline_spec.rb index 55a9292e48d03..56ebb885f5e02 100644 --- a/spec/lib/bulk_imports/ndjson_pipeline_spec.rb +++ b/spec/lib/bulk_imports/ndjson_pipeline_spec.rb @@ -143,7 +143,8 @@ def initialize(portable, user, context) members_mapper: instance_of(BulkImports::UsersMapper), object_builder: Gitlab::ImportExport::Group::ObjectBuilder, user: user, - excluded_keys: nil + excluded_keys: nil, + import_source: Import::SOURCE_DIRECT_TRANSFER ) .and_return(relation_object) expect(relation_object).to receive(:assign_attributes).with(group: group) diff --git a/spec/lib/gitlab/import_export/base/relation_factory_spec.rb b/spec/lib/gitlab/import_export/base/relation_factory_spec.rb index 5e63804c51c28..86238e8d6e35d 100644 --- a/spec/lib/gitlab/import_export/base/relation_factory_spec.rb +++ b/spec/lib/gitlab/import_export/base/relation_factory_spec.rb @@ -2,13 +2,14 @@ require 'spec_helper' -RSpec.describe Gitlab::ImportExport::Base::RelationFactory do +RSpec.describe Gitlab::ImportExport::Base::RelationFactory, feature_category: :importers do let(:user) { create(:admin) } let(:project) { create(:project) } let(:members_mapper) { double('members_mapper').as_null_object } let(:relation_sym) { :project_snippets } let(:relation_hash) { {} } let(:excluded_keys) { [] } + let(:import_source) { nil } subject do described_class.create( # rubocop:disable Rails/SaveBang @@ -19,7 +20,8 @@ members_mapper: members_mapper, user: user, importable: project, - excluded_keys: excluded_keys + excluded_keys: excluded_keys, + import_source: import_source ) end @@ -90,6 +92,24 @@ expect(subject).to be_instance_of(Note) end + context 'when import_source is given' do + let(:import_source) { Import::SOURCE_DIRECT_TRANSFER } + + it 'sets the imported_from' do + expect(subject.imported_from).to eq(import_source.to_s) + end + + context 'when object does not have an imported_from attribute' do + let(:relation_sym) { :user } + let(:relation_hash) { attributes_for(:user) } + + it 'works without an error' do + expect(subject).not_to respond_to(:imported_from) # Sanity check: This must be true for test subject + expect(subject).to be_instance_of(User) + end + end + end + context 'when relation contains user references' do let(:new_user) { create(:user) } let(:exported_member) do -- GitLab