Commit ee4b5402 authored by James Lopez's avatar James Lopez

Merge branch 'xanf-migrate-manifest-importer' into 'master'

Migrate manifest importer to new importer UI

See merge request gitlab-org/gitlab!38268
parents 49a39c70 5fc7730c
......@@ -86,15 +86,18 @@ export default {
</a>
</td>
<td class="d-flex flex-wrap flex-lg-nowrap">
<select2-select v-model="targetNamespaceSelect" :options="select2Options" />
<span class="px-2 import-slash-divider d-flex justify-content-center align-items-center"
>/</span
>
<input
v-model="newNameInput"
type="text"
class="form-control import-project-name-input qa-project-path-field"
/>
<template v-if="repo.target">{{ repo.target }}</template>
<template v-else>
<select2-select v-model="targetNamespaceSelect" :options="select2Options" />
<span class="px-2 import-slash-divider d-flex justify-content-center align-items-center"
>/</span
>
<input
v-model="newNameInput"
type="text"
class="form-control import-project-name-input qa-project-path-field"
/>
</template>
</td>
<td>
<import-status :status="repo.importStatus" />
......
import mountImportProjectsTable from '~/import_projects';
document.addEventListener('DOMContentLoaded', () => {
const mountElement = document.getElementById('import-projects-mount-element');
mountImportProjectsTable(mountElement);
});
......@@ -41,6 +41,10 @@ class Import::BaseController < ApplicationController
raise NotImplementedError
end
def extra_representation_opts
{}
end
private
def filter_attribute
......@@ -58,11 +62,11 @@ class Import::BaseController < ApplicationController
end
def serialized_provider_repos
Import::ProviderRepoSerializer.new(current_user: current_user).represent(importable_repos, provider: provider_name, provider_url: provider_url)
Import::ProviderRepoSerializer.new(current_user: current_user).represent(importable_repos, provider: provider_name, provider_url: provider_url, **extra_representation_opts)
end
def serialized_incompatible_repos
Import::ProviderRepoSerializer.new(current_user: current_user).represent(incompatible_repos, provider: provider_name, provider_url: provider_url)
Import::ProviderRepoSerializer.new(current_user: current_user).represent(incompatible_repos, provider: provider_name, provider_url: provider_url, **extra_representation_opts)
end
def serialized_imported_projects
......
# frozen_string_literal: true
class Import::ManifestController < Import::BaseController
extend ::Gitlab::Utils::Override
before_action :whitelist_query_limiting, only: [:create]
before_action :verify_import_enabled
before_action :ensure_import_vars, only: [:create, :status]
......@@ -8,16 +10,9 @@ class Import::ManifestController < Import::BaseController
def new
end
# rubocop: disable CodeReuse/ActiveRecord
def status
@already_added_projects = find_already_added_projects
already_added_import_urls = @already_added_projects.pluck(:import_url)
@pending_repositories = repositories.to_a.reject do |repository|
already_added_import_urls.include?(repository[:url])
end
super
end
# rubocop: enable CodeReuse/ActiveRecord
def upload
group = Group.find(params[:group_id])
......@@ -42,8 +37,8 @@ class Import::ManifestController < Import::BaseController
end
end
def jobs
render json: find_jobs
def realtime_changes
super
end
def create
......@@ -54,12 +49,43 @@ class Import::ManifestController < Import::BaseController
project = Gitlab::ManifestImport::ProjectCreator.new(repository, group, current_user).execute
if project.persisted?
render json: ProjectSerializer.new.represent(project)
render json: ProjectSerializer.new.represent(project, serializer: :import)
else
render json: { errors: project_save_error(project) }, status: :unprocessable_entity
end
end
protected
# rubocop: disable CodeReuse/ActiveRecord
override :importable_repos
def importable_repos
already_added_projects_names = already_added_projects.pluck(:import_url)
repositories.reject { |repo| already_added_projects_names.include?(repo[:url]) }
end
# rubocop: enable CodeReuse/ActiveRecord
override :incompatible_repos
def incompatible_repos
[]
end
override :provider_name
def provider_name
:manifest
end
override :provider_url
def provider_url
nil
end
override :extra_representation_opts
def extra_representation_opts
{ group_full_path: group.full_path }
end
private
def ensure_import_vars
......@@ -82,15 +108,6 @@ class Import::ManifestController < Import::BaseController
find_already_added_projects.to_json(only: [:id], methods: [:import_status])
end
# rubocop: disable CodeReuse/ActiveRecord
def find_already_added_projects
group.all_projects
.where(import_type: 'manifest')
.where(creator_id: current_user)
.with_import_state
end
# rubocop: enable CodeReuse/ActiveRecord
def verify_import_enabled
render_404 unless manifest_import_enabled?
end
......
# frozen_string_literal: true
class Import::ManifestProviderRepoEntity < Import::BaseProviderRepoEntity
expose :id
expose :full_name, override: true do |repo|
repo[:url]
end
expose :provider_link, override: true do |repo|
repo[:url]
end
expose :target do |repo, options|
import_project_target(options[:group_full_path], repo[:path], options[:request].current_user)
end
private
def import_project_target(owner, name, user)
namespace = user.can_create_group? ? owner : user.namespace_path
"#{namespace}/#{name}"
end
end
......@@ -14,6 +14,8 @@ class Import::ProviderRepoSerializer < BaseSerializer
Import::BitbucketServerProviderRepoEntity
when :gitlab
Import::GitlabProviderRepoEntity
when :manifest
Import::ManifestProviderRepoEntity
else
raise NotImplementedError
end
......
- page_title _("Manifest import")
- header_title _("Projects"), root_path
- provider = 'manifest'
%h3.page-title
= _('Manifest file import')
%p
= button_tag class: "btn btn-import btn-success js-import-all" do
= _('Import all repositories')
= icon("spinner spin", class: "loading-icon")
.table-responsive
%table.table.import-jobs
%thead
%tr
%th= _('Repository URL')
%th= _('To GitLab')
%th= _('Status')
%tbody
- @already_added_projects.each do |project|
%tr{ id: "project_#{project.id}", class: project_status_css_class(project.import_status) }
%td
= project.import_url
%td
= link_to_project project
%td.job-status
= render 'import/project_status', project: project
- @pending_repositories.each do |repository|
%tr{ id: "repo_#{repository[:id]}" }
%td
= repository[:url]
%td.import-target
= import_project_target(@group.full_path, repository[:path])
%td.import-actions.job-status
= button_tag class: "btn btn-import js-add-to-import" do
= _('Import')
= icon("spinner spin", class: "loading-icon")
.js-importer-status{ data: { jobs_import_path: url_for([:jobs, :import, provider]),
import_path: url_for([:import, provider]) } }
= render 'import/githubish_status', provider: 'manifest'
---
title: Switch manifest importer to new UI
merge_request: 38268
author:
type: changed
......@@ -71,7 +71,7 @@ namespace :import do
resource :manifest, only: [:create, :new], controller: :manifest do
get :status
get :jobs
get :realtime_changes
post :upload
end
......
......@@ -62,4 +62,4 @@ You can start the import with:
to the import status page with projects list based on the manifest file.
1. Check the list and click **Import all repositories** to start the import.
![Manifest status](img/manifest_status.png)
![Manifest status](img/manifest_status_v13_3.png)
......@@ -18,6 +18,7 @@ module Gitlab
params = {
import_url: repository[:url],
import_source: repository[:url],
import_type: 'manifest',
namespace_id: group.id,
path: project_path,
......
......@@ -20680,9 +20680,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
msgid "Repository URL"
msgstr ""
msgid "Repository check"
msgstr ""
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Import::ManifestController do
include ImportSpecHelper
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group)}
before(:all) do
group.add_maintainer(user)
end
before do
sign_in(user)
end
def assign_session_group
session[:manifest_import_repositories] = []
session[:manifest_import_group_id] = group.id
end
describe 'GET status' do
let(:repo1) { OpenStruct.new(id: 'test1', url: 'http://demo.host/test1') }
let(:repo2) { OpenStruct.new(id: 'test2', url: 'http://demo.host/test2') }
let(:repos) { [repo1, repo2] }
before do
assign_session_group
session[:manifest_import_repositories] = repos
end
it "returns variables for json request" do
project = create(:project, import_type: 'manifest', creator_id: user.id)
get :status, format: :json
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.dig("imported_projects", 0, "id")).to eq(project.id)
expect(json_response.dig("provider_repos", 0, "id")).to eq(repo1.id)
expect(json_response.dig("provider_repos", 1, "id")).to eq(repo2.id)
expect(json_response.dig("namespaces", 0, "id")).to eq(group.id)
end
it "does not show already added project" do
project = create(:project, import_type: 'manifest', namespace: user.namespace, import_status: :finished, import_url: repo1.url)
get :status, format: :json
expect(json_response.dig("imported_projects", 0, "id")).to eq(project.id)
expect(json_response.dig("provider_repos").length).to eq(1)
expect(json_response.dig("provider_repos", 0, "id")).not_to eq(repo1.id)
end
end
end
......@@ -24,7 +24,7 @@ RSpec.describe 'Import multiple repositories by uploading a manifest file', :js
expect(page).to have_content('https://android-review.googlesource.com/platform/build/blueprint')
end
it 'imports successfully imports a project', :sidekiq_inline do
it 'imports a project successfully', :sidekiq_inline, :js do
visit new_import_manifest_path
attach_file('manifest', Rails.root.join('spec/fixtures/aosp_manifest.xml'))
......@@ -32,7 +32,11 @@ RSpec.describe 'Import multiple repositories by uploading a manifest file', :js
page.within(second_row) do
click_on 'Import'
end
wait_for_requests
page.within(second_row) do
expect(page).to have_content 'Done'
expect(page).to have_content("#{group.full_path}/build/blueprint")
end
......@@ -48,6 +52,6 @@ RSpec.describe 'Import multiple repositories by uploading a manifest file', :js
end
def second_row
page.all('table.import-jobs tbody tr')[1]
page.all('table.import-table tbody tr')[1]
end
end
......@@ -23,13 +23,14 @@ RSpec.describe Gitlab::ManifestImport::ProjectCreator do
it { expect { subject.execute }.to change { Project.count }.by(1) }
it { expect { subject.execute }.to change { Group.count }.by(1) }
it 'creates project with valid full path and import url' do
it 'creates project with valid full path, import url and import source' do
subject.execute
project = Project.last
expect(project.full_path).to eq(File.join(group.path, 'device/common'))
expect(project.import_url).to eq('https://android-review.googlesource.com/device/common')
expect(project.import_source).to eq('https://android-review.googlesource.com/device/common')
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Import::ManifestProviderRepoEntity do
let(:current_user) { create(:user) }
let(:request) { double(:request, current_user: current_user) }
let(:repo_data) do
{
id: 1,
url: 'http://demo.repo/url',
path: '/demo/path'
}
end
subject { described_class.represent(repo_data, { group_full_path: 'group', request: request }).as_json }
it_behaves_like 'exposes required fields for import entity' do
let(:expected_values) do
{
id: repo_data[:id],
full_name: repo_data[:url],
sanitized_name: nil,
provider_link: repo_data[:url]
}
end
end
end
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