2021-08-13 15:11:15 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require 'spec_helper'
|
|
|
|
|
2021-10-06 21:12:16 +00:00
|
|
|
RSpec.describe Gitlab::Import::ImportFailureService, :aggregate_failures do
|
2021-08-13 15:11:15 +00:00
|
|
|
let_it_be(:import_type) { 'import_type' }
|
2021-10-06 21:12:16 +00:00
|
|
|
let_it_be(:project) { create(:project, :import_started, import_type: import_type) }
|
2021-08-13 15:11:15 +00:00
|
|
|
|
|
|
|
let(:exception) { StandardError.new('some error') }
|
2021-12-01 21:13:44 +00:00
|
|
|
let(:import_state) { nil }
|
|
|
|
let(:fail_import) { false }
|
|
|
|
let(:metrics) { false }
|
|
|
|
|
|
|
|
let(:arguments) do
|
|
|
|
{
|
|
|
|
project_id: project.id,
|
|
|
|
error_source: 'SomeImporter',
|
|
|
|
exception: exception,
|
|
|
|
fail_import: fail_import,
|
|
|
|
metrics: metrics,
|
|
|
|
import_state: import_state
|
|
|
|
}
|
|
|
|
end
|
2021-10-06 21:12:16 +00:00
|
|
|
|
|
|
|
describe '.track' do
|
2021-12-01 21:13:44 +00:00
|
|
|
let(:instance) { double(:failure_service) }
|
|
|
|
|
2021-10-06 21:12:16 +00:00
|
|
|
context 'with all arguments provided' do
|
2021-12-01 21:13:44 +00:00
|
|
|
let(:arguments) do
|
2021-10-06 21:12:16 +00:00
|
|
|
{
|
|
|
|
exception: exception,
|
|
|
|
import_state: '_import_state_',
|
|
|
|
project_id: '_project_id_',
|
2021-12-01 21:13:44 +00:00
|
|
|
error_source: '_error_source_',
|
2021-10-06 21:12:16 +00:00
|
|
|
fail_import: '_fail_import_',
|
|
|
|
metrics: '_metrics_'
|
|
|
|
}
|
|
|
|
end
|
2021-08-13 15:11:15 +00:00
|
|
|
|
2021-10-06 21:12:16 +00:00
|
|
|
it 'invokes a new instance and executes' do
|
2021-12-01 21:13:44 +00:00
|
|
|
expect(described_class).to receive(:new).with(**arguments).and_return(instance)
|
|
|
|
expect(instance).to receive(:execute)
|
2021-10-06 21:12:16 +00:00
|
|
|
|
2021-12-01 21:13:44 +00:00
|
|
|
described_class.track(**arguments)
|
2021-10-06 21:12:16 +00:00
|
|
|
end
|
2021-08-13 15:11:15 +00:00
|
|
|
end
|
|
|
|
|
2021-10-06 21:12:16 +00:00
|
|
|
context 'with only necessary arguments utilizing defaults' do
|
|
|
|
it 'invokes a new instance and executes' do
|
2021-12-01 21:13:44 +00:00
|
|
|
expect(described_class).to receive(:new).with(a_hash_including(exception: exception)).and_return(instance)
|
|
|
|
expect(instance).to receive(:execute)
|
2021-10-06 21:12:16 +00:00
|
|
|
|
|
|
|
described_class.track(exception: exception)
|
|
|
|
end
|
2021-08-13 15:11:15 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-10-06 21:12:16 +00:00
|
|
|
describe '#execute' do
|
2021-12-01 21:13:44 +00:00
|
|
|
subject(:service) { described_class.new(**arguments) }
|
2021-10-06 21:12:16 +00:00
|
|
|
|
|
|
|
shared_examples 'logs the exception and fails the import' do
|
|
|
|
it 'when the failure does not abort the import' do
|
|
|
|
expect(Gitlab::ErrorTracking)
|
|
|
|
.to receive(:track_exception)
|
|
|
|
.with(
|
|
|
|
exception,
|
2022-05-02 15:10:10 +00:00
|
|
|
{
|
|
|
|
project_id: project.id,
|
|
|
|
import_type: import_type,
|
|
|
|
source: 'SomeImporter'
|
|
|
|
}
|
2021-10-06 21:12:16 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
expect(Gitlab::Import::Logger)
|
|
|
|
.to receive(:error)
|
|
|
|
.with(
|
2022-05-02 15:10:10 +00:00
|
|
|
{
|
|
|
|
message: 'importer failed',
|
|
|
|
'error.message': 'some error',
|
|
|
|
project_id: project.id,
|
|
|
|
import_type: import_type,
|
|
|
|
source: 'SomeImporter'
|
|
|
|
}
|
2021-10-06 21:12:16 +00:00
|
|
|
)
|
|
|
|
|
2021-12-01 21:13:44 +00:00
|
|
|
service.execute
|
2021-10-06 21:12:16 +00:00
|
|
|
|
|
|
|
expect(project.import_state.reload.status).to eq('failed')
|
|
|
|
|
|
|
|
expect(project.import_failures).not_to be_empty
|
|
|
|
expect(project.import_failures.last.exception_class).to eq('StandardError')
|
|
|
|
expect(project.import_failures.last.exception_message).to eq('some error')
|
2021-12-01 21:13:44 +00:00
|
|
|
expect(project.import_failures.last.retry_count).to eq(0)
|
2021-08-13 15:11:15 +00:00
|
|
|
end
|
2021-10-06 21:12:16 +00:00
|
|
|
end
|
2021-08-13 15:11:15 +00:00
|
|
|
|
2021-10-06 21:12:16 +00:00
|
|
|
shared_examples 'logs the exception and does not fail the import' do
|
|
|
|
it 'when the failure does not abort the import' do
|
|
|
|
expect(Gitlab::ErrorTracking)
|
|
|
|
.to receive(:track_exception)
|
|
|
|
.with(
|
|
|
|
exception,
|
2022-05-02 15:10:10 +00:00
|
|
|
{
|
|
|
|
project_id: project.id,
|
|
|
|
import_type: import_type,
|
|
|
|
source: 'SomeImporter'
|
|
|
|
}
|
2021-10-06 21:12:16 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
expect(Gitlab::Import::Logger)
|
|
|
|
.to receive(:error)
|
|
|
|
.with(
|
2022-05-02 15:10:10 +00:00
|
|
|
{
|
|
|
|
message: 'importer failed',
|
|
|
|
'error.message': 'some error',
|
|
|
|
project_id: project.id,
|
|
|
|
import_type: import_type,
|
|
|
|
source: 'SomeImporter'
|
|
|
|
}
|
2021-10-06 21:12:16 +00:00
|
|
|
)
|
|
|
|
|
2021-12-01 21:13:44 +00:00
|
|
|
service.execute
|
2021-10-06 21:12:16 +00:00
|
|
|
|
|
|
|
expect(project.import_state.reload.status).to eq('started')
|
|
|
|
|
|
|
|
expect(project.import_failures).not_to be_empty
|
|
|
|
expect(project.import_failures.last.exception_class).to eq('StandardError')
|
|
|
|
expect(project.import_failures.last.exception_message).to eq('some error')
|
2021-12-01 21:13:44 +00:00
|
|
|
expect(project.import_failures.last.retry_count).to eq(nil)
|
2021-10-06 21:12:16 +00:00
|
|
|
end
|
2021-08-13 15:11:15 +00:00
|
|
|
end
|
|
|
|
|
2021-10-06 21:12:16 +00:00
|
|
|
context 'when tracking metrics' do
|
2021-12-01 21:13:44 +00:00
|
|
|
let(:metrics) { true }
|
2021-10-06 21:12:16 +00:00
|
|
|
|
|
|
|
it 'tracks the failed import' do
|
2021-12-01 21:13:44 +00:00
|
|
|
metrics_double = double(:metrics)
|
2021-10-06 21:12:16 +00:00
|
|
|
|
2021-12-01 21:13:44 +00:00
|
|
|
expect(Gitlab::Import::Metrics)
|
|
|
|
.to receive(:new)
|
|
|
|
.with("#{project.import_type}_importer", project)
|
|
|
|
.and_return(metrics_double)
|
|
|
|
expect(metrics_double).to receive(:track_failed_import)
|
2021-10-06 21:12:16 +00:00
|
|
|
|
2021-12-01 21:13:44 +00:00
|
|
|
service.execute
|
2021-08-13 15:11:15 +00:00
|
|
|
end
|
2021-10-06 21:12:16 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when using the project as reference' do
|
|
|
|
context 'when it fails the import' do
|
2021-12-01 21:13:44 +00:00
|
|
|
let(:fail_import) { true }
|
2021-08-13 15:11:15 +00:00
|
|
|
|
2021-10-06 21:12:16 +00:00
|
|
|
it_behaves_like 'logs the exception and fails the import'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when it does not fail the import' do
|
|
|
|
it_behaves_like 'logs the exception and does not fail the import'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when using the import_state as reference' do
|
2021-12-01 21:13:44 +00:00
|
|
|
let(:import_state) { project.import_state }
|
2021-10-06 21:12:16 +00:00
|
|
|
|
|
|
|
context 'when it fails the import' do
|
2021-12-01 21:13:44 +00:00
|
|
|
let(:fail_import) { true }
|
2021-10-06 21:12:16 +00:00
|
|
|
|
|
|
|
it_behaves_like 'logs the exception and fails the import'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when it does not fail the import' do
|
|
|
|
it_behaves_like 'logs the exception and does not fail the import'
|
|
|
|
end
|
2021-08-13 15:11:15 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|