Commit c3d0947e authored by George Koltsov's avatar George Koltsov

Fix Wiki Pipeline network error if wiki does not exist

  - Add a preliminary check on source to see if there are
    any wiki pages available before doing wiki repository import
  - Update `BulkImports::Clients::HTTP` to have a more detailed
    error message when a non-successful http response is returned

Changelog: fixed
parent 1d835b16
......@@ -20,8 +20,6 @@
class BulkImports::Entity < ApplicationRecord
self.table_name = 'bulk_import_entities'
EXPORT_RELATIONS_URL = '/%{resource}/%{full_path}/export_relations'
belongs_to :bulk_import, optional: false
belongs_to :parent, class_name: 'BulkImports::Entity', optional: true
......@@ -112,14 +110,22 @@ class BulkImports::Entity < ApplicationRecord
entity_type.pluralize
end
def base_resource_url_path
"/#{pluralized_name}/#{encoded_source_full_path}"
end
def export_relations_url_path
@export_relations_url_path ||= EXPORT_RELATIONS_URL % { resource: pluralized_name, full_path: encoded_source_full_path }
"#{base_resource_url_path}/export_relations"
end
def relation_download_url_path(relation)
"#{export_relations_url_path}/download?relation=#{relation}"
end
def wikis_url_path
"#{base_resource_url_path}/wikis"
end
def project?
source_type == 'project_entity'
end
......
......@@ -123,7 +123,7 @@ module BulkImports
def with_error_handling
response = yield
raise ::BulkImports::NetworkError.new(response: response) unless response.success?
raise ::BulkImports::NetworkError.new("Unsuccessful response #{response.code} from #{response.request.path.path}", response: response) unless response.success?
response
rescue *Gitlab::HTTP::HTTP_ERRORS => e
......
......@@ -7,7 +7,9 @@ module BulkImports
include Pipeline
def extract(*)
BulkImports::Pipeline::ExtractedData.new(data: { url: url_from_parent_path(context.entity.source_full_path) })
url = url_from_parent_path(context.entity.source_full_path) if source_wiki_exists?
BulkImports::Pipeline::ExtractedData.new(data: { url: url })
end
def transform(_, data)
......@@ -15,14 +17,15 @@ module BulkImports
end
def load(context, data)
return unless context.portable.wiki
return unless data&.dig(:url)
wiki = context.portable.wiki
url = data[:url].sub("://", "://oauth2:#{context.configuration.access_token}@")
Gitlab::UrlBlocker.validate!(url, allow_local_network: allow_local_requests?, allow_localhost: allow_local_requests?)
context.portable.wiki.ensure_repository
context.portable.wiki.repository.fetch_as_mirror(url)
wiki.ensure_repository
wiki.repository.fetch_as_mirror(url)
end
private
......@@ -36,6 +39,16 @@ module BulkImports
def allow_local_requests?
Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services?
end
def source_wiki_exists?
wikis = client.get(context.entity.wikis_url_path).parsed_response
wikis.any?
end
def client
BulkImports::Clients::HTTP.new(url: context.configuration.url, token: context.configuration.access_token)
end
end
end
end
......
......@@ -38,11 +38,11 @@ RSpec.describe BulkImports::Clients::HTTP do
context 'when response is not success' do
it 'raises BulkImports::Error' do
response_double = double(code: 503, success?: false)
response_double = double(code: 503, success?: false, request: double(path: double(path: '/test')))
allow(Gitlab::HTTP).to receive(method).and_return(response_double)
expect { subject.public_send(method, resource) }.to raise_exception(BulkImports::NetworkError)
expect { subject.public_send(method, resource) }.to raise_exception(BulkImports::NetworkError, 'Unsuccessful response 503 from /test')
end
end
end
......
......@@ -282,4 +282,20 @@ RSpec.describe BulkImports::Entity, type: :model do
expect(project_entity.group?).to eq(false)
end
end
describe '#base_resource_url_path' do
it 'returns base entity url path' do
entity = build(:bulk_import_entity)
expect(entity.base_resource_url_path).to eq("/groups/#{entity.encoded_source_full_path}")
end
end
describe '#wiki_url_path' do
it 'returns entity wiki url path' do
entity = build(:bulk_import_entity)
expect(entity.wikis_url_path).to eq("/groups/#{entity.encoded_source_full_path}/wikis")
end
end
end
......@@ -9,16 +9,18 @@ RSpec.shared_examples 'wiki pipeline imports a wiki for an entity' do
let(:extracted_data) { BulkImports::Pipeline::ExtractedData.new(data: {}) }
context 'successfully imports wiki for an entity' do
subject { described_class.new(context) }
subject { described_class.new(context) }
before do
allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
allow(extractor).to receive(:extract).and_return(extracted_data)
end
before do
allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
allow(extractor).to receive(:extract).and_return(extracted_data)
end
end
context 'when wiki exists' do
it 'imports new wiki into destination project' do
expect(subject).to receive(:source_wiki_exists?).and_return(true)
expect_next_instance_of(Gitlab::GitalyClient::RepositoryService) do |repository_service|
url = "https://oauth2:token@gitlab.example/#{entity.source_full_path}.wiki.git"
expect(repository_service).to receive(:fetch_remote).with(url, any_args).and_return 0
......@@ -27,5 +29,16 @@ RSpec.shared_examples 'wiki pipeline imports a wiki for an entity' do
subject.run
end
end
context 'when wiki does not exist' do
it 'does not import wiki' do
expect(subject).to receive(:source_wiki_exists?).and_return(false)
expect(parent.wiki).not_to receive(:ensure_repository)
expect(parent.wiki.repository).not_to receive(:ensure_repository)
expect { subject.run }.not_to raise_error
end
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