diff options
21 files changed, 500 insertions, 17 deletions
diff --git a/app/assets/javascripts/logs/components/environment_logs.vue b/app/assets/javascripts/logs/components/environment_logs.vue index 487b4f30b5b..0d84798d690 100644 --- a/app/assets/javascripts/logs/components/environment_logs.vue +++ b/app/assets/javascripts/logs/components/environment_logs.vue @@ -70,9 +70,10 @@ export default { return this.logs.isLoading; }, shouldShowElasticStackCallout() { - return ( - !this.isElasticStackCalloutDismissed && - (this.environments.isLoading || !this.showAdvancedFilters) + return !( + this.environments.isLoading || + this.isElasticStackCalloutDismissed || + this.showAdvancedFilters ); }, }, @@ -120,7 +121,8 @@ export default { <div class="environment-logs-viewer d-flex flex-column py-3"> <gl-alert v-if="shouldShowElasticStackCallout" - class="mb-3 js-elasticsearch-alert" + ref="elasticsearchNotice" + class="mb-3" @dismiss="isElasticStackCalloutDismissed = true" > {{ diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_terraform_plan.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_terraform_plan.vue new file mode 100644 index 00000000000..edf90085a5b --- /dev/null +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_terraform_plan.vue @@ -0,0 +1,152 @@ +<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> diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue index 084deee042b..1bc28b15f74 100644 --- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue +++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue @@ -36,6 +36,7 @@ import CheckingState from './components/states/mr_widget_checking.vue'; import eventHub from './event_hub'; import notify from '~/lib/utils/notify'; 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 { setFaviconOverlay } from '../lib/utils/common_utils'; @@ -74,6 +75,7 @@ export default { 'mr-widget-rebase': RebaseState, SourceBranchRemovalStatus, GroupedTestReportsApp, + TerraformPlan, }, props: { mrData: { @@ -379,6 +381,8 @@ export default { :endpoint="mr.testResultsPath" /> + <terraform-plan v-if="mr.terraformReportsPath" :endpoint="mr.terraformReportsPath" /> + <div class="mr-widget-section"> <component :is="componentName" :mr="mr" :service="service" /> diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js index 321b9270dde..9f001dda540 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js @@ -101,6 +101,7 @@ export default class MergeRequestStore { this.isPipelineActive = data.pipeline ? data.pipeline.active : false; this.isPipelineBlocked = pipelineStatus ? pipelineStatus.group === 'manual' : false; this.ciStatusFaviconPath = pipelineStatus ? pipelineStatus.favicon : null; + this.terraformReportsPath = data.terraform_reports_path; this.testResultsPath = data.test_reports_path; this.exposedArtifactsPath = data.exposed_artifacts_path; this.cancelAutoMergePath = data.cancel_auto_merge_path; diff --git a/app/controllers/projects/static_site_editor_controller.rb b/app/controllers/projects/static_site_editor_controller.rb index 597bfccf422..98ec2335899 100644 --- a/app/controllers/projects/static_site_editor_controller.rb +++ b/app/controllers/projects/static_site_editor_controller.rb @@ -1,10 +1,21 @@ # frozen_string_literal: true class Projects::StaticSiteEditorController < Projects::ApplicationController + include ExtractsPath layout 'fullscreen' prepend_before_action :authenticate_user!, only: [:show] + before_action :assign_ref_and_path, only: [: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 diff --git a/app/services/metrics/dashboard/base_service.rb b/app/services/metrics/dashboard/base_service.rb index 219b26defb1..c112d75a9b5 100644 --- a/app/services/metrics/dashboard/base_service.rb +++ b/app/services/metrics/dashboard/base_service.rb @@ -12,7 +12,8 @@ module Metrics STAGES::CommonMetricsInserter, STAGES::EndpointInserter, STAGES::PanelIdsInserter, - STAGES::Sorter + STAGES::Sorter, + STAGES::AlertsInserter ].freeze def get_dashboard @@ -117,5 +118,3 @@ module Metrics end end end - -Metrics::Dashboard::BaseService.prepend_if_ee('EE::Metrics::Dashboard::BaseService') diff --git a/app/services/metrics/dashboard/system_dashboard_service.rb b/app/services/metrics/dashboard/system_dashboard_service.rb index c28b7b875df..ed4b78ba159 100644 --- a/app/services/metrics/dashboard/system_dashboard_service.rb +++ b/app/services/metrics/dashboard/system_dashboard_service.rb @@ -14,7 +14,8 @@ module Metrics STAGES::CustomMetricsDetailsInserter, STAGES::EndpointInserter, STAGES::PanelIdsInserter, - STAGES::Sorter + STAGES::Sorter, + STAGES::AlertsInserter ].freeze class << self @@ -30,5 +31,3 @@ module Metrics end end end - -Metrics::Dashboard::SystemDashboardService.prepend_if_ee('EE::Metrics::Dashboard::SystemDashboardService') diff --git a/app/views/projects/static_site_editor/show.html.haml b/app/views/projects/static_site_editor/show.html.haml index 9ccc54e6d51..8d2649be588 100644 --- a/app/views/projects/static_site_editor/show.html.haml +++ b/app/views/projects/static_site_editor/show.html.haml @@ -1 +1 @@ -#static-site-editor{ data: { project_id: '8', path: 'README.md' } } +#static-site-editor{ data: @config.payload } diff --git a/app/workers/concerns/project_import_options.rb b/app/workers/concerns/project_import_options.rb index 2baf768bfd1..c8ee5539441 100644 --- a/app/workers/concerns/project_import_options.rb +++ b/app/workers/concerns/project_import_options.rb @@ -18,7 +18,12 @@ module ProjectImportOptions "import" 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']}" end end diff --git a/changelogs/unreleased/207528-tf-plan-in-mr.yml b/changelogs/unreleased/207528-tf-plan-in-mr.yml new file mode 100644 index 00000000000..6535e17d48c --- /dev/null +++ b/changelogs/unreleased/207528-tf-plan-in-mr.yml @@ -0,0 +1,5 @@ +--- +title: Add terraform report to merge request widget +merge_request: 27700 +author: +type: added diff --git a/changelogs/unreleased/212560_initialize_sse_frontend.yml b/changelogs/unreleased/212560_initialize_sse_frontend.yml new file mode 100644 index 00000000000..0ee5d7669ba --- /dev/null +++ b/changelogs/unreleased/212560_initialize_sse_frontend.yml @@ -0,0 +1,5 @@ +--- +title: Provide configuration options for Static Site Editor +merge_request: 29058 +author: +type: added diff --git a/changelogs/unreleased/213325-elastic-recommendation-alert-appears-when-the-screen-is-loaded.yml b/changelogs/unreleased/213325-elastic-recommendation-alert-appears-when-the-screen-is-loaded.yml new file mode 100644 index 00000000000..43583268c84 --- /dev/null +++ b/changelogs/unreleased/213325-elastic-recommendation-alert-appears-when-the-screen-is-loaded.yml @@ -0,0 +1,5 @@ +--- +title: Elasticsearch recommendation alert does not appears while screen is loaded +merge_request: 29097 +author: +type: fixed diff --git a/lib/gitlab/metrics/dashboard/stages/alerts_inserter.rb b/lib/gitlab/metrics/dashboard/stages/alerts_inserter.rb new file mode 100644 index 00000000000..38736158c3b --- /dev/null +++ b/lib/gitlab/metrics/dashboard/stages/alerts_inserter.rb @@ -0,0 +1,41 @@ +# 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 diff --git a/lib/gitlab/static_site_editor/config.rb b/lib/gitlab/static_site_editor/config.rb new file mode 100644 index 00000000000..4bc0fc95abd --- /dev/null +++ b/lib/gitlab/static_site_editor/config.rb @@ -0,0 +1,36 @@ +# 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 diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 0c35c77f8cf..9b39c97cb38 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -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." msgstr "" +msgid "A terraform report was generated in your pipelines." +msgstr "" + msgid "A user with write access to the source branch selected this option" msgstr "" @@ -2008,6 +2011,9 @@ msgstr "" msgid "An error occurred while loading merge requests." msgstr "" +msgid "An error occurred while loading terraform report" +msgstr "" + msgid "An error occurred while loading the data. Please try again." 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." msgstr "" +msgid "Changes are unknown" +msgstr "" + msgid "Changes suppressed. Click to show." msgstr "" @@ -15632,6 +15641,12 @@ msgstr "" msgid "Project name" 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." msgstr "" @@ -17019,6 +17034,9 @@ msgstr "" msgid "Reported %{timeAgo} by %{reportedBy}" msgstr "" +msgid "Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete" +msgstr "" + msgid "Reporter" msgstr "" @@ -22694,6 +22712,9 @@ msgstr "" msgid "View full dashboard" msgstr "" +msgid "View full log" +msgstr "" + msgid "View group labels" msgstr "" diff --git a/spec/controllers/projects/static_site_editor_controller_spec.rb b/spec/controllers/projects/static_site_editor_controller_spec.rb index 7f1b67fc734..d1224bb75c0 100644 --- a/spec/controllers/projects/static_site_editor_controller_spec.rb +++ b/spec/controllers/projects/static_site_editor_controller_spec.rb @@ -10,7 +10,8 @@ describe Projects::StaticSiteEditorController do { namespace_id: project.namespace, project_id: project, - id: 'master/README.md' + id: 'master/README.md', + return_url: 'http://example.com' } end @@ -38,6 +39,18 @@ describe Projects::StaticSiteEditorController do it 'renders the edit page' do expect(response).to render_template(:show) 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 diff --git a/spec/frontend/logs/components/environment_logs_spec.js b/spec/frontend/logs/components/environment_logs_spec.js index befcd462828..d097610cb0a 100644 --- a/spec/frontend/logs/components/environment_logs_spec.js +++ b/spec/frontend/logs/components/environment_logs_spec.js @@ -43,7 +43,7 @@ describe('EnvironmentLogs', () => { const findSimpleFilters = () => wrapper.find({ ref: 'log-simple-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 findInfiniteScroll = () => wrapper.find({ ref: 'infiniteScroll' }); @@ -160,6 +160,10 @@ describe('EnvironmentLogs', () => { initWrapper(); }); + it('does not display an alert to upgrade to ES', () => { + expect(findElasticsearchNotice().exists()).toBe(false); + }); + it('displays a disabled environments dropdown', () => { expect(findEnvironmentsDropdown().attributes('disabled')).toBe('true'); expect(findEnvironmentsDropdown().findAll(GlDropdownItem).length).toBe(0); @@ -204,7 +208,7 @@ describe('EnvironmentLogs', () => { }); 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', () => { @@ -235,7 +239,7 @@ describe('EnvironmentLogs', () => { }); it('does not display an alert to upgrade to ES', () => { - expect(findInfoAlert().exists()).toBe(false); + expect(findElasticsearchNotice().exists()).toBe(false); }); it('populates environments dropdown', () => { diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_terraform_plan_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_terraform_plan_spec.js new file mode 100644 index 00000000000..1951b56587a --- /dev/null +++ b/spec/frontend/vue_mr_widget/components/mr_widget_terraform_plan_spec.js @@ -0,0 +1,89 @@ +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'); + }); + }); +}); diff --git a/spec/lib/gitlab/metrics/dashboard/processor_spec.rb b/spec/lib/gitlab/metrics/dashboard/processor_spec.rb index d957b1c992f..3cb02a8bcb3 100644 --- a/spec/lib/gitlab/metrics/dashboard/processor_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/processor_spec.rb @@ -14,9 +14,11 @@ describe Gitlab::Metrics::Dashboard::Processor do Gitlab::Metrics::Dashboard::Stages::CustomMetricsInserter, Gitlab::Metrics::Dashboard::Stages::CustomMetricsDetailsInserter, Gitlab::Metrics::Dashboard::Stages::EndpointInserter, - Gitlab::Metrics::Dashboard::Stages::Sorter + Gitlab::Metrics::Dashboard::Stages::Sorter, + Gitlab::Metrics::Dashboard::Stages::AlertsInserter ] end + let(:process_params) { [project, dashboard_yml, sequence, { environment: environment }] } let(:dashboard) { described_class.new(*process_params).process } @@ -113,6 +115,54 @@ describe Gitlab::Metrics::Dashboard::Processor do 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| it 'raises a DashboardLayoutError' do error_class = Gitlab::Metrics::Dashboard::Errors::DashboardProcessingError diff --git a/spec/lib/gitlab/static_site_editor/config_spec.rb b/spec/lib/gitlab/static_site_editor/config_spec.rb new file mode 100644 index 00000000000..dea79fb0e92 --- /dev/null +++ b/spec/lib/gitlab/static_site_editor/config_spec.rb @@ -0,0 +1,30 @@ +# 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 diff --git a/spec/workers/concerns/project_import_options_spec.rb b/spec/workers/concerns/project_import_options_spec.rb index c5fbcfb5fb0..3ccfb21b653 100644 --- a/spec/workers/concerns/project_import_options_spec.rb +++ b/spec/workers/concerns/project_import_options_spec.rb @@ -39,6 +39,17 @@ describe ProjectImportOptions do expect(project.import_state.reload.last_error).to include("import") 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 let(:project) { create(:project) } |