Commit 75ee59f7 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent e79918ce
...@@ -70,9 +70,10 @@ export default { ...@@ -70,9 +70,10 @@ export default {
return this.logs.isLoading; return this.logs.isLoading;
}, },
shouldShowElasticStackCallout() { shouldShowElasticStackCallout() {
return ( return !(
!this.isElasticStackCalloutDismissed && this.environments.isLoading ||
(this.environments.isLoading || !this.showAdvancedFilters) this.isElasticStackCalloutDismissed ||
this.showAdvancedFilters
); );
}, },
}, },
...@@ -120,7 +121,8 @@ export default { ...@@ -120,7 +121,8 @@ export default {
<div class="environment-logs-viewer d-flex flex-column py-3"> <div class="environment-logs-viewer d-flex flex-column py-3">
<gl-alert <gl-alert
v-if="shouldShowElasticStackCallout" v-if="shouldShowElasticStackCallout"
class="mb-3 js-elasticsearch-alert" ref="elasticsearchNotice"
class="mb-3"
@dismiss="isElasticStackCalloutDismissed = true" @dismiss="isElasticStackCalloutDismissed = true"
> >
{{ {{
......
<script>
import { __ } from '~/locale';
import { GlIcon, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import CiIcon from '../../vue_shared/components/ci_icon.vue';
import flash from '~/flash';
import Poll from '~/lib/utils/poll';
import Visibility from 'visibilityjs';
export default {
name: 'MRWidgetTerraformPlan',
components: {
CiIcon,
GlIcon,
GlLoadingIcon,
GlSprintf,
},
props: {
endpoint: {
type: String,
required: true,
},
},
data() {
return {
loading: true,
plans: {},
};
},
computed: {
addNum() {
return Number(this.plan.create);
},
changeNum() {
return Number(this.plan.update);
},
deleteNum() {
return Number(this.plan.delete);
},
iconStatusObj() {
return {
group: 'warning',
icon: 'status_warning',
};
},
logUrl() {
return this.plan.job_path;
},
plan() {
return this.plans['tfplan.json'] || {};
},
validPlanValues() {
return this.addNum + this.changeNum + this.deleteNum >= 0;
},
},
created() {
this.fetchPlans();
},
methods: {
fetchPlans() {
this.loading = true;
const poll = new Poll({
resource: {
fetchPlans: () => axios.get(this.endpoint),
},
data: this.endpoint,
method: 'fetchPlans',
successCallback: ({ data }) => {
this.plans = data;
this.loading = false;
},
errorCallback: () => {
this.plans = {};
this.loading = false;
flash(__('An error occurred while loading terraform report'));
},
});
if (!Visibility.hidden()) {
poll.makeRequest();
}
Visibility.change(() => {
if (!Visibility.hidden()) {
poll.restart();
} else {
poll.stop();
}
});
},
},
};
</script>
<template>
<section class="mr-widget-section">
<div class="mr-widget-body media d-flex flex-row">
<span class="append-right-default align-self-start align-self-lg-center">
<ci-icon :status="iconStatusObj" :size="24" />
</span>
<div class="d-flex flex-fill flex-column flex-md-row">
<div class="terraform-mr-plan-text normal d-flex flex-column flex-lg-row">
<p class="m-0 pr-1">{{ __('A terraform report was generated in your pipelines.') }}</p>
<gl-loading-icon v-if="loading" size="md" />
<p v-else-if="validPlanValues" class="m-0">
<gl-sprintf
:message="
__(
'Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete',
)
"
>
<template #addNum>
<strong>{{ addNum }}</strong>
</template>
<template #changeNum>
<strong>{{ changeNum }}</strong>
</template>
<template #deleteNum>
<strong>{{ deleteNum }}</strong>
</template>
</gl-sprintf>
</p>
<p v-else class="m-0">{{ __('Changes are unknown') }}</p>
</div>
<div class="terraform-mr-plan-actions">
<a
v-if="logUrl"
:href="logUrl"
target="_blank"
data-track-event="click_terraform_mr_plan_button"
data-track-label="mr_widget_terraform_mr_plan_button"
data-track-property="terraform_mr_plan_button"
class="btn btn-sm js-terraform-report-link"
rel="noopener"
>
{{ __('View full log') }}
<gl-icon name="external-link" />
</a>
</div>
</div>
</div>
</section>
</template>
...@@ -36,6 +36,7 @@ import CheckingState from './components/states/mr_widget_checking.vue'; ...@@ -36,6 +36,7 @@ import CheckingState from './components/states/mr_widget_checking.vue';
import eventHub from './event_hub'; import eventHub from './event_hub';
import notify from '~/lib/utils/notify'; import notify from '~/lib/utils/notify';
import SourceBranchRemovalStatus from './components/source_branch_removal_status.vue'; import SourceBranchRemovalStatus from './components/source_branch_removal_status.vue';
import TerraformPlan from './components/mr_widget_terraform_plan.vue';
import GroupedTestReportsApp from '../reports/components/grouped_test_reports_app.vue'; import GroupedTestReportsApp from '../reports/components/grouped_test_reports_app.vue';
import { setFaviconOverlay } from '../lib/utils/common_utils'; import { setFaviconOverlay } from '../lib/utils/common_utils';
...@@ -74,6 +75,7 @@ export default { ...@@ -74,6 +75,7 @@ export default {
'mr-widget-rebase': RebaseState, 'mr-widget-rebase': RebaseState,
SourceBranchRemovalStatus, SourceBranchRemovalStatus,
GroupedTestReportsApp, GroupedTestReportsApp,
TerraformPlan,
}, },
props: { props: {
mrData: { mrData: {
...@@ -379,6 +381,8 @@ export default { ...@@ -379,6 +381,8 @@ export default {
:endpoint="mr.testResultsPath" :endpoint="mr.testResultsPath"
/> />
<terraform-plan v-if="mr.terraformReportsPath" :endpoint="mr.terraformReportsPath" />
<div class="mr-widget-section"> <div class="mr-widget-section">
<component :is="componentName" :mr="mr" :service="service" /> <component :is="componentName" :mr="mr" :service="service" />
......
...@@ -101,6 +101,7 @@ export default class MergeRequestStore { ...@@ -101,6 +101,7 @@ export default class MergeRequestStore {
this.isPipelineActive = data.pipeline ? data.pipeline.active : false; this.isPipelineActive = data.pipeline ? data.pipeline.active : false;
this.isPipelineBlocked = pipelineStatus ? pipelineStatus.group === 'manual' : false; this.isPipelineBlocked = pipelineStatus ? pipelineStatus.group === 'manual' : false;
this.ciStatusFaviconPath = pipelineStatus ? pipelineStatus.favicon : null; this.ciStatusFaviconPath = pipelineStatus ? pipelineStatus.favicon : null;
this.terraformReportsPath = data.terraform_reports_path;
this.testResultsPath = data.test_reports_path; this.testResultsPath = data.test_reports_path;
this.exposedArtifactsPath = data.exposed_artifacts_path; this.exposedArtifactsPath = data.exposed_artifacts_path;
this.cancelAutoMergePath = data.cancel_auto_merge_path; this.cancelAutoMergePath = data.cancel_auto_merge_path;
......
# frozen_string_literal: true # frozen_string_literal: true
class Projects::StaticSiteEditorController < Projects::ApplicationController class Projects::StaticSiteEditorController < Projects::ApplicationController
include ExtractsPath
layout 'fullscreen' layout 'fullscreen'
prepend_before_action :authenticate_user!, only: [:show] prepend_before_action :authenticate_user!, only: [:show]
before_action :assign_ref_and_path, only: [:show]
def show def show
@config = Gitlab::StaticSiteEditor::Config.new(@repository, @ref, @path, params[:return_url])
end
private
def assign_ref_and_path
@ref, @path = extract_ref(params[:id])
render_404 if @ref.blank? || @path.blank?
end end
end end
...@@ -12,7 +12,8 @@ module Metrics ...@@ -12,7 +12,8 @@ module Metrics
STAGES::CommonMetricsInserter, STAGES::CommonMetricsInserter,
STAGES::EndpointInserter, STAGES::EndpointInserter,
STAGES::PanelIdsInserter, STAGES::PanelIdsInserter,
STAGES::Sorter STAGES::Sorter,
STAGES::AlertsInserter
].freeze ].freeze
def get_dashboard def get_dashboard
...@@ -117,5 +118,3 @@ module Metrics ...@@ -117,5 +118,3 @@ module Metrics
end end
end end
end end
Metrics::Dashboard::BaseService.prepend_if_ee('EE::Metrics::Dashboard::BaseService')
...@@ -14,7 +14,8 @@ module Metrics ...@@ -14,7 +14,8 @@ module Metrics
STAGES::CustomMetricsDetailsInserter, STAGES::CustomMetricsDetailsInserter,
STAGES::EndpointInserter, STAGES::EndpointInserter,
STAGES::PanelIdsInserter, STAGES::PanelIdsInserter,
STAGES::Sorter STAGES::Sorter,
STAGES::AlertsInserter
].freeze ].freeze
class << self class << self
...@@ -30,5 +31,3 @@ module Metrics ...@@ -30,5 +31,3 @@ module Metrics
end end
end end
end end
Metrics::Dashboard::SystemDashboardService.prepend_if_ee('EE::Metrics::Dashboard::SystemDashboardService')
#static-site-editor{ data: { project_id: '8', path: 'README.md' } } #static-site-editor{ data: @config.payload }
...@@ -18,7 +18,12 @@ module ProjectImportOptions ...@@ -18,7 +18,12 @@ module ProjectImportOptions
"import" "import"
end end
project.import_state.mark_as_failed(_("Every %{action} attempt has failed: %{job_error_message}. Please try again.") % { action: action, job_error_message: job['error_message'] }) if project.jira_import?
project.latest_jira_import.do_fail!
else
project.import_state.mark_as_failed(_("Every %{action} attempt has failed: %{job_error_message}. Please try again.") % { action: action, job_error_message: job['error_message'] })
end
Sidekiq.logger.warn "Failed #{job['class']} with #{job['args']}: #{job['error_message']}" Sidekiq.logger.warn "Failed #{job['class']} with #{job['args']}: #{job['error_message']}"
end end
end end
......
---
title: Add terraform report to merge request widget
merge_request: 27700
author:
type: added
---
title: Provide configuration options for Static Site Editor
merge_request: 29058
author:
type: added
---
title: Elasticsearch recommendation alert does not appears while screen is loaded
merge_request: 29097
author:
type: fixed
# frozen_string_literal: true
require 'set'
module Gitlab
module Metrics
module Dashboard
module Stages
class AlertsInserter < BaseStage
include ::Gitlab::Utils::StrongMemoize
def transform!
return if metrics_with_alerts.empty?
for_metrics do |metric|
next unless metrics_with_alerts.include?(metric[:metric_id])
metric[:alert_path] = alert_path(metric[:metric_id], project, params[:environment])
end
end
private
def metrics_with_alerts
strong_memoize(:metrics_with_alerts) do
alerts = ::Projects::Prometheus::AlertsFinder
.new(project: project, environment: params[:environment])
.execute
Set.new(alerts.map(&:prometheus_metric_id))
end
end
def alert_path(metric_id, project, environment)
::Gitlab::Routing.url_helpers.project_prometheus_alert_path(project, metric_id, environment_id: environment.id, format: :json)
end
end
end
end
end
end
# frozen_string_literal: true
module Gitlab
module StaticSiteEditor
class Config
def initialize(repository, ref, file_path, return_url)
@repository = repository
@ref = ref
@file_path = file_path
@return_url = return_url
end
def payload
{
branch: ref,
path: file_path,
commit: commit.id,
project_id: project.id,
project: project.path,
namespace: project.namespace.path,
return_url: return_url
}
end
private
attr_reader :repository, :ref, :file_path, :return_url
delegate :project, to: :repository
def commit
repository.commit(ref)
end
end
end
end
...@@ -888,6 +888,9 @@ msgstr "" ...@@ -888,6 +888,9 @@ msgstr ""
msgid "A subscription will trigger a new pipeline on the default branch of this project when a pipeline successfully completes for a new tag on the %{default_branch_docs} of the subscribed project." msgid "A subscription will trigger a new pipeline on the default branch of this project when a pipeline successfully completes for a new tag on the %{default_branch_docs} of the subscribed project."
msgstr "" msgstr ""
msgid "A terraform report was generated in your pipelines."
msgstr ""
msgid "A user with write access to the source branch selected this option" msgid "A user with write access to the source branch selected this option"
msgstr "" msgstr ""
...@@ -2008,6 +2011,9 @@ msgstr "" ...@@ -2008,6 +2011,9 @@ msgstr ""
msgid "An error occurred while loading merge requests." msgid "An error occurred while loading merge requests."
msgstr "" msgstr ""
msgid "An error occurred while loading terraform report"
msgstr ""
msgid "An error occurred while loading the data. Please try again." msgid "An error occurred while loading the data. Please try again."
msgstr "" msgstr ""
...@@ -3526,6 +3532,9 @@ msgstr "" ...@@ -3526,6 +3532,9 @@ msgstr ""
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision." msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr "" msgstr ""
msgid "Changes are unknown"
msgstr ""
msgid "Changes suppressed. Click to show." msgid "Changes suppressed. Click to show."
msgstr "" msgstr ""
...@@ -15632,6 +15641,12 @@ msgstr "" ...@@ -15632,6 +15641,12 @@ msgstr ""
msgid "Project name" msgid "Project name"
msgstr "" msgstr ""
msgid "Project name suffix"
msgstr ""
msgid "Project name suffix is a user-defined string which will be appended to the project path, and will form the Service Desk email address."
msgstr ""
msgid "Project order will not be saved as local storage is not available." msgid "Project order will not be saved as local storage is not available."
msgstr "" msgstr ""
...@@ -17019,6 +17034,9 @@ msgstr "" ...@@ -17019,6 +17034,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}" msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr "" msgstr ""
msgid "Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete"
msgstr ""
msgid "Reporter" msgid "Reporter"
msgstr "" msgstr ""
...@@ -22694,6 +22712,9 @@ msgstr "" ...@@ -22694,6 +22712,9 @@ msgstr ""
msgid "View full dashboard" msgid "View full dashboard"
msgstr "" msgstr ""
msgid "View full log"
msgstr ""
msgid "View group labels" msgid "View group labels"
msgstr "" msgstr ""
......
...@@ -10,7 +10,8 @@ describe Projects::StaticSiteEditorController do ...@@ -10,7 +10,8 @@ describe Projects::StaticSiteEditorController do
{ {
namespace_id: project.namespace, namespace_id: project.namespace,
project_id: project, project_id: project,
id: 'master/README.md' id: 'master/README.md',
return_url: 'http://example.com'
} }
end end
...@@ -38,6 +39,18 @@ describe Projects::StaticSiteEditorController do ...@@ -38,6 +39,18 @@ describe Projects::StaticSiteEditorController do
it 'renders the edit page' do it 'renders the edit page' do
expect(response).to render_template(:show) expect(response).to render_template(:show)
end end
it 'assigns a config variable' do
expect(assigns(:config)).to be_a(Gitlab::StaticSiteEditor::Config)
end
context 'when combination of ref and file path is incorrect' do
let(:default_params) { super().merge(id: 'unknown') }
it 'responds with 404 page' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
end end
end end
end end
......
...@@ -43,7 +43,7 @@ describe('EnvironmentLogs', () => { ...@@ -43,7 +43,7 @@ describe('EnvironmentLogs', () => {
const findSimpleFilters = () => wrapper.find({ ref: 'log-simple-filters' }); const findSimpleFilters = () => wrapper.find({ ref: 'log-simple-filters' });
const findAdvancedFilters = () => wrapper.find({ ref: 'log-advanced-filters' }); const findAdvancedFilters = () => wrapper.find({ ref: 'log-advanced-filters' });
const findInfoAlert = () => wrapper.find('.js-elasticsearch-alert'); const findElasticsearchNotice = () => wrapper.find({ ref: 'elasticsearchNotice' });
const findLogControlButtons = () => wrapper.find({ name: 'log-control-buttons-stub' }); const findLogControlButtons = () => wrapper.find({ name: 'log-control-buttons-stub' });
const findInfiniteScroll = () => wrapper.find({ ref: 'infiniteScroll' }); const findInfiniteScroll = () => wrapper.find({ ref: 'infiniteScroll' });
...@@ -160,6 +160,10 @@ describe('EnvironmentLogs', () => { ...@@ -160,6 +160,10 @@ describe('EnvironmentLogs', () => {
initWrapper(); initWrapper();
}); });
it('does not display an alert to upgrade to ES', () => {
expect(findElasticsearchNotice().exists()).toBe(false);
});
it('displays a disabled environments dropdown', () => { it('displays a disabled environments dropdown', () => {
expect(findEnvironmentsDropdown().attributes('disabled')).toBe('true'); expect(findEnvironmentsDropdown().attributes('disabled')).toBe('true');
expect(findEnvironmentsDropdown().findAll(GlDropdownItem).length).toBe(0); expect(findEnvironmentsDropdown().findAll(GlDropdownItem).length).toBe(0);
...@@ -204,7 +208,7 @@ describe('EnvironmentLogs', () => { ...@@ -204,7 +208,7 @@ describe('EnvironmentLogs', () => {
}); });
it('displays an alert to upgrade to ES', () => { it('displays an alert to upgrade to ES', () => {
expect(findInfoAlert().exists()).toBe(true); expect(findElasticsearchNotice().exists()).toBe(true);
}); });
it('displays simple filters for kubernetes logs API', () => { it('displays simple filters for kubernetes logs API', () => {
...@@ -235,7 +239,7 @@ describe('EnvironmentLogs', () => { ...@@ -235,7 +239,7 @@ describe('EnvironmentLogs', () => {
}); });
it('does not display an alert to upgrade to ES', () => { it('does not display an alert to upgrade to ES', () => {
expect(findInfoAlert().exists()).toBe(false); expect(findElasticsearchNotice().exists()).toBe(false);
}); });
it('populates environments dropdown', () => { it('populates environments dropdown', () => {
......
import { GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import axios from '~/lib/utils/axios_utils';
import MockAdapter from 'axios-mock-adapter';
import MrWidgetTerraformPlan from '~/vue_merge_request_widget/components/mr_widget_terraform_plan.vue';
const plan = {
create: 10,
update: 20,
delete: 30,
job_path: '/path/to/ci/logs',
};
describe('MrWidgetTerraformPlan', () => {
let mock;
let wrapper;
const propsData = { endpoint: '/path/to/terraform/report.json' };
const mockPollingApi = (response, body, header) => {
mock.onGet(propsData.endpoint).reply(response, body, header);
};
const mountWrapper = () => {
wrapper = shallowMount(MrWidgetTerraformPlan, { propsData });
return axios.waitForAll();
};
beforeEach(() => {
mock = new MockAdapter(axios);
});
afterEach(() => {
wrapper.destroy();
mock.restore();
});
describe('loading poll', () => {
beforeEach(() => {
mockPollingApi(200, { 'tfplan.json': plan }, {});
return mountWrapper().then(() => {
wrapper.setData({ loading: true });
return wrapper.vm.$nextTick();
});
});
it('Diplays loading icon when loading is true', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
expect(wrapper.find(GlSprintf).exists()).toBe(false);
expect(wrapper.text()).not.toContain(
'A terraform report was generated in your pipelines. Changes are unknown',
);
});
});
describe('successful poll', () => {
beforeEach(() => {
mockPollingApi(200, { 'tfplan.json': plan }, {});
return mountWrapper();
});
it('content change text', () => {
expect(wrapper.find(GlSprintf).exists()).toBe(true);
});
it('renders button when url is found', () => {
expect(wrapper.find('a').text()).toContain('View full log');
});
});
describe('polling fails', () => {
beforeEach(() => {
mockPollingApi(500, null, {});
return mountWrapper();
});
it('does not display changes text when api fails', () => {
expect(wrapper.text()).toContain(
'A terraform report was generated in your pipelines. Changes are unknown',
);
expect(wrapper.find('.js-terraform-report-link').exists()).toBe(false);
expect(wrapper.text()).not.toContain('View full log');
});
});
});
...@@ -14,9 +14,11 @@ describe Gitlab::Metrics::Dashboard::Processor do ...@@ -14,9 +14,11 @@ describe Gitlab::Metrics::Dashboard::Processor do
Gitlab::Metrics::Dashboard::Stages::CustomMetricsInserter, Gitlab::Metrics::Dashboard::Stages::CustomMetricsInserter,
Gitlab::Metrics::Dashboard::Stages::CustomMetricsDetailsInserter, Gitlab::Metrics::Dashboard::Stages::CustomMetricsDetailsInserter,
Gitlab::Metrics::Dashboard::Stages::EndpointInserter, Gitlab::Metrics::Dashboard::Stages::EndpointInserter,
Gitlab::Metrics::Dashboard::Stages::Sorter Gitlab::Metrics::Dashboard::Stages::Sorter,
Gitlab::Metrics::Dashboard::Stages::AlertsInserter
] ]
end end
let(:process_params) { [project, dashboard_yml, sequence, { environment: environment }] } let(:process_params) { [project, dashboard_yml, sequence, { environment: environment }] }
let(:dashboard) { described_class.new(*process_params).process } let(:dashboard) { described_class.new(*process_params).process }
...@@ -113,6 +115,54 @@ describe Gitlab::Metrics::Dashboard::Processor do ...@@ -113,6 +115,54 @@ describe Gitlab::Metrics::Dashboard::Processor do
end end
end end
context 'when the dashboard references persisted metrics with alerts' do
let!(:alert) do
create(
:prometheus_alert,
environment: environment,
project: project,
prometheus_metric: persisted_metric
)
end
shared_examples_for 'has saved alerts' do
it 'includes an alert path' do
target_metric = all_metrics.find { |metric| metric[:metric_id] == persisted_metric.id }
expect(target_metric).to be_a Hash
expect(target_metric).to include(:alert_path)
expect(target_metric[:alert_path]).to include(
project.path,
persisted_metric.id.to_s,
environment.id.to_s
)
end
end
context 'that are shared across projects' do
let!(:persisted_metric) { create(:prometheus_metric, :common, identifier: 'metric_a1') }
it_behaves_like 'has saved alerts'
end
context 'when the project has associated metrics' do
let!(:persisted_metric) { create(:prometheus_metric, project: project, group: :business) }
it_behaves_like 'has saved alerts'
end
end
context 'when there are no alerts' do
let!(:persisted_metric) { create(:prometheus_metric, :common, identifier: 'metric_a1') }
it 'does not insert an alert_path' do
target_metric = all_metrics.find { |metric| metric[:metric_id] == persisted_metric.id }
expect(target_metric).to be_a Hash
expect(target_metric).not_to include(:alert_path)
end
end
shared_examples_for 'errors with message' do |expected_message| shared_examples_for 'errors with message' do |expected_message|
it 'raises a DashboardLayoutError' do it 'raises a DashboardLayoutError' do
error_class = Gitlab::Metrics::Dashboard::Errors::DashboardProcessingError error_class = Gitlab::Metrics::Dashboard::Errors::DashboardProcessingError
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::StaticSiteEditor::Config do
subject(:config) { described_class.new(repository, ref, file_path, return_url) }
let(:project) { create(:project, :public, :repository, name: 'project', namespace: namespace) }
let(:namespace) { create(:namespace, name: 'namespace') }
let(:repository) { project.repository }
let(:ref) { 'master' }
let(:file_path) { 'README.md' }
let(:return_url) { 'http://example.com' }
describe '#payload' do
subject { config.payload }
it 'returns data for the frontend component' do
is_expected.to eq(
branch: 'master',
commit: repository.commit.id,
namespace: 'namespace',
path: 'README.md',
project: 'project',
project_id: project.id,
return_url: 'http://example.com'
)
end
end
end
...@@ -39,6 +39,17 @@ describe ProjectImportOptions do ...@@ -39,6 +39,17 @@ describe ProjectImportOptions do
expect(project.import_state.reload.last_error).to include("import") expect(project.import_state.reload.last_error).to include("import")
end end
context 'when project is jira import' do
let(:project) { create(:project, import_type: 'jira') }
let!(:jira_import) { create(:jira_import_state, project: project) }
it 'logs the appropriate error message for forked projects' do
worker_class.sidekiq_retries_exhausted_block.call(job)
expect(project.latest_jira_import.reload.status).to eq('failed')
end
end
context 'when project does not have import_state' do context 'when project does not have import_state' do
let(:project) { create(:project) } let(:project) { create(:project) }
......
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