Override values from JSON with import data
This overrides values defined in the project JSON with the values provided in project.import_data.data['override_params']. These could be passed from the API.
This commit is contained in:
		
							parent
							
								
									e40c0085ef
								
							
						
					
					
						commit
						e3acc982a8
					
				|  | @ -0,0 +1,5 @@ | ||||||
|  | --- | ||||||
|  | title: Allow overriding params on project import through API | ||||||
|  | merge_request: 18086 | ||||||
|  | author: | ||||||
|  | type: added | ||||||
|  | @ -111,6 +111,9 @@ POST /projects/import | ||||||
| | `namespace` | integer/string | no | The ID or path of the namespace that the project will be imported to. Defaults to the current user's namespace | | | `namespace` | integer/string | no | The ID or path of the namespace that the project will be imported to. Defaults to the current user's namespace | | ||||||
| | `file` | string | yes | The file to be uploaded | | | `file` | string | yes | The file to be uploaded | | ||||||
| | `path` | string | yes | Name and path for new project | | | `path` | string | yes | Name and path for new project | | ||||||
|  | | `override_params` | Hash | no | Supports all fields defined in the [Project API](projects.md)] | | ||||||
|  | 
 | ||||||
|  | The override params passed will take precendence over all values defined inside the export file. | ||||||
| 
 | 
 | ||||||
| To upload a file from your filesystem, use the `--form` argument. This causes | To upload a file from your filesystem, use the `--form` argument. This causes | ||||||
| cURL to post data using the header `Content-Type: multipart/form-data`. | cURL to post data using the header `Content-Type: multipart/form-data`. | ||||||
|  |  | ||||||
|  | @ -77,13 +77,13 @@ module Gitlab | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       def default_relation_list |       def default_relation_list | ||||||
|         Gitlab::ImportExport::Reader.new(shared: @shared).tree.reject do |model| |         reader.tree.reject do |model| | ||||||
|           model.is_a?(Hash) && model[:project_members] |           model.is_a?(Hash) && model[:project_members] | ||||||
|         end |         end | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       def restore_project |       def restore_project | ||||||
|         params = project_params |         params = project_params.symbolize_keys | ||||||
| 
 | 
 | ||||||
|         if params[:description].present? |         if params[:description].present? | ||||||
|           params[:description_html] = nil |           params[:description_html] = nil | ||||||
|  | @ -94,7 +94,20 @@ module Gitlab | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       def project_params |       def project_params | ||||||
|         @tree_hash.reject do |key, value| |         @project_params ||= json_params.merge(override_params) | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       def override_params | ||||||
|  |         return {} unless params = @project.import_data&.data&.fetch('override_params') | ||||||
|  | 
 | ||||||
|  |         @override_params ||= params.select do |key, _value| | ||||||
|  |           Project.column_names.include?(key.to_s) && | ||||||
|  |             !reader.project_tree[:except].include?(key.to_sym) | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       def json_params | ||||||
|  |         @json_params ||= @tree_hash.reject do |key, value| | ||||||
|           # return params that are not 1 to many or 1 to 1 relations |           # return params that are not 1 to many or 1 to 1 relations | ||||||
|           value.respond_to?(:each) && !Project.column_names.include?(key) |           value.respond_to?(:each) && !Project.column_names.include?(key) | ||||||
|         end |         end | ||||||
|  | @ -181,6 +194,10 @@ module Gitlab | ||||||
| 
 | 
 | ||||||
|         relation_hash.merge(params) |         relation_hash.merge(params) | ||||||
|       end |       end | ||||||
|  | 
 | ||||||
|  |       def reader | ||||||
|  |         @reader ||= Gitlab::ImportExport::Reader.new(shared: @shared) | ||||||
|  |       end | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
|   "description": "Nisi et repellendus ut enim quo accusamus vel magnam.", |   "description": "Nisi et repellendus ut enim quo accusamus vel magnam.", | ||||||
|   "visibility_level": 10, |   "visibility_level": 10, | ||||||
|   "archived": false, |   "archived": false, | ||||||
|   "description_html": "description", |   "description_html": "<p dir=\"auto\">Nisi et repellendus ut enim quo accusamus vel magnam.</p>", | ||||||
|   "labels": [ |   "labels": [ | ||||||
|     { |     { | ||||||
|       "id": 2, |       "id": 2, | ||||||
|  |  | ||||||
|  | @ -47,7 +47,8 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it 'has the project html description' do |       it 'has the project html description' do | ||||||
|         expect(Project.find_by_path('project').description_html).to eq('description') |         expected_description_html = "<p dir=\"auto\">Nisi et repellendus ut enim quo accusamus vel magnam.</p>" | ||||||
|  |         expect(Project.find_by_path('project').description_html).to eq(expected_description_html) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it 'has the same label associated to two issues' do |       it 'has the same label associated to two issues' do | ||||||
|  | @ -317,6 +318,24 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  |     context 'when the project has overriden params in import data' do | ||||||
|  |       it 'overwrites the params stored in the JSON' do | ||||||
|  |         project.create_import_data(data: { override_params: { description: "Overridden" } }) | ||||||
|  | 
 | ||||||
|  |         restored_project_json | ||||||
|  | 
 | ||||||
|  |         expect(project.description).to eq("Overridden") | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       it 'does not allow setting params that are excluded from import_export settings' do | ||||||
|  |         project.create_import_data(data: { override_params: { lfs_enabled: true } }) | ||||||
|  | 
 | ||||||
|  |         restored_project_json | ||||||
|  | 
 | ||||||
|  |         expect(project.lfs_enabled).to be_nil | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|     context 'with a project that has a group' do |     context 'with a project that has a group' do | ||||||
|       let!(:project) do |       let!(:project) do | ||||||
|         create(:project, |         create(:project, | ||||||
|  |  | ||||||
|  | @ -71,7 +71,7 @@ describe API::ProjectImport do | ||||||
|       expect(json_response['error']).to eq('file is invalid') |       expect(json_response['error']).to eq('file is invalid') | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     it 'allows overriding project params' do |     it 'stores params that can be overridden' do | ||||||
|       stub_import(namespace) |       stub_import(namespace) | ||||||
|       override_params = { 'description' => 'Hello world' } |       override_params = { 'description' => 'Hello world' } | ||||||
| 
 | 
 | ||||||
|  | @ -85,7 +85,7 @@ describe API::ProjectImport do | ||||||
|       expect(import_project.import_data.data['override_params']).to eq(override_params) |       expect(import_project.import_data.data['override_params']).to eq(override_params) | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     it 'does store params that are not allowed' do |     it 'does not store params that are not allowed' do | ||||||
|       stub_import(namespace) |       stub_import(namespace) | ||||||
|       override_params = { 'not_allowed' => 'Hello world' } |       override_params = { 'not_allowed' => 'Hello world' } | ||||||
| 
 | 
 | ||||||
|  | @ -99,6 +99,21 @@ describe API::ProjectImport do | ||||||
|       expect(import_project.import_data.data['override_params']).to be_empty |       expect(import_project.import_data.data['override_params']).to be_empty | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  |     it 'correctly overrides params during the import' do | ||||||
|  |       override_params = { 'description' => 'Hello world' } | ||||||
|  | 
 | ||||||
|  |       Sidekiq::Testing.inline! do | ||||||
|  |         post api('/projects/import', user), | ||||||
|  |              path: 'test-import', | ||||||
|  |              file: fixture_file_upload(file), | ||||||
|  |              namespace: namespace.id, | ||||||
|  |              override_params: override_params | ||||||
|  |       end | ||||||
|  |       import_project = Project.find(json_response['id']) | ||||||
|  | 
 | ||||||
|  |       expect(import_project.description).to eq('Hello world') | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|     def stub_import(namespace) |     def stub_import(namespace) | ||||||
|       expect_any_instance_of(Project).to receive(:import_schedule) |       expect_any_instance_of(Project).to receive(:import_schedule) | ||||||
|       expect(::Projects::CreateService).to receive(:new).with(user, hash_including(namespace_id: namespace.id)).and_call_original |       expect(::Projects::CreateService).to receive(:new).with(user, hash_including(namespace_id: namespace.id)).and_call_original | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue