...@@ -17,7 +17,13 @@ GitLab monitors its own internal service metrics, and makes them available at th ...@@ -17,7 +17,13 @@ GitLab monitors its own internal service metrics, and makes them available at th
`/-/metrics` endpoint. Unlike other [Prometheus](https://prometheus.io) exporters, in order to access `/-/metrics` endpoint. Unlike other [Prometheus](https://prometheus.io) exporters, in order to access
it, the client IP needs to be [included in a whitelist](../ip_whitelist.md). it, the client IP needs to be [included in a whitelist](../ip_whitelist.md).
For Omnibus and Chart installations, these metrics are automatically enabled and collected as of [GitLab 9.4](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/1702). For source installations or earlier versions, these metrics will need to be enabled manually and collected by a Prometheus server. For Omnibus and Chart installations, these metrics are automatically enabled
and collected as of [GitLab
9.4](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/1702). For
source installations or earlier versions, these metrics will need to be enabled
manually and collected by a Prometheus server.
See also [Sidekiq metrics](#sidekiq-metrics) for how to enable and view metrics from Sidekiq nodes.
## Metrics available ## Metrics available
...@@ -105,10 +111,12 @@ The following metrics can be controlled by feature flags: ...@@ -105,10 +111,12 @@ The following metrics can be controlled by feature flags:
| `gitlab_method_call_duration_seconds` | `prometheus_metrics_method_instrumentation` | | `gitlab_method_call_duration_seconds` | `prometheus_metrics_method_instrumentation` |
| `gitlab_view_rendering_duration_seconds` | `prometheus_metrics_view_instrumentation` | | `gitlab_view_rendering_duration_seconds` | `prometheus_metrics_view_instrumentation` |
## Sidekiq Metrics available for Geo **(PREMIUM)** ## Sidekiq metrics
Sidekiq jobs may also gather metrics, and these metrics can be accessed if the Sidekiq exporter is enabled (e.g. via Sidekiq jobs may also gather metrics, and these metrics can be accessed if the
the `monitoring.sidekiq_exporter` configuration option in `gitlab.yml`. Sidekiq exporter is enabled (for example, using the `monitoring.sidekiq_exporter`
configuration option in `gitlab.yml`. These metrics are served from the
`/metrics` path on the configured port.
| Metric | Type | Since | Description | Labels | | Metric | Type | Since | Description | Labels |
|:---------------------------------------------- |:------- |:----- |:----------- |:------ | |:---------------------------------------------- |:------- |:----- |:----------- |:------ |
...@@ -145,6 +153,7 @@ the `monitoring.sidekiq_exporter` configuration option in `gitlab.yml`. ...@@ -145,6 +153,7 @@ the `monitoring.sidekiq_exporter` configuration option in `gitlab.yml`.
| `geo_repositories_checked_failed_count` | Gauge | 11.1 | Number of repositories that have a failure from `git fsck` | url | | `geo_repositories_checked_failed_count` | Gauge | 11.1 | Number of repositories that have a failure from `git fsck` | url |
| `geo_repositories_retrying_verification_count` | Gauge | 11.2 | Number of repositories verification failures that Geo is actively trying to correct on secondary | url | | `geo_repositories_retrying_verification_count` | Gauge | 11.2 | Number of repositories verification failures that Geo is actively trying to correct on secondary | url |
| `geo_wikis_retrying_verification_count` | Gauge | 11.2 | Number of wikis verification failures that Geo is actively trying to correct on secondary | url | | `geo_wikis_retrying_verification_count` | Gauge | 11.2 | Number of wikis verification failures that Geo is actively trying to correct on secondary | url |
| `global_search_bulk_cron_queue_size` | Gauge | 12.10 | Number of database records waiting to be synchronized to Elasticsearch | |
## Database load balancing metrics **(PREMIUM ONLY)** ## Database load balancing metrics **(PREMIUM ONLY)**
... ...
......
...@@ -51,8 +51,6 @@ module Gitlab ...@@ -51,8 +51,6 @@ module Gitlab
end end
def hash_of_the_latest_changes def hash_of_the_latest_changes
return unless Feature.enabled?(:ci_file_based_cache, @pipeline.project, default_enabled: true)
ids = files.map { |path| last_commit_id_for_path(path) } ids = files.map { |path| last_commit_id_for_path(path) }
ids = ids.compact.sort.uniq ids = ids.compact.sort.uniq
... ...
......
...@@ -37,7 +37,7 @@ module Gitlab ...@@ -37,7 +37,7 @@ module Gitlab
case resource case resource
when Hash when Hash
self.new(resource.symbolize_keys) self.new(resource.symbolize_keys)
when ::HasVariable when ::Ci::HasVariable
self.new(resource.to_runner_variable) self.new(resource.to_runner_variable)
when self when self
resource.dup resource.dup
... ...
......
...@@ -4,7 +4,10 @@ import { visitUrl } from '~/lib/utils/url_utility'; ...@@ -4,7 +4,10 @@ import { visitUrl } from '~/lib/utils/url_utility';
import TableRow from '~/repository/components/table/row.vue'; import TableRow from '~/repository/components/table/row.vue';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
jest.mock('~/lib/utils/url_utility'); jest.mock('~/lib/utils/url_utility', () => ({
...jest.requireActual('~/lib/utils/url_utility'),
visitUrl: jest.fn(),
}));
let vm; let vm;
let $router; let $router;
... ...
......
...@@ -204,7 +204,6 @@ describe BlobHelper do ...@@ -204,7 +204,6 @@ describe BlobHelper do
end end
describe '#show_suggest_pipeline_creation_celebration?' do describe '#show_suggest_pipeline_creation_celebration?' do
let(:blob) { fake_blob(path: Gitlab::FileDetector::PATTERNS[:gitlab_ci]) }
let(:current_user) { create(:user) } let(:current_user) { create(:user) }
before do before do
...@@ -212,10 +211,13 @@ describe BlobHelper do ...@@ -212,10 +211,13 @@ describe BlobHelper do
assign(:blob, blob) assign(:blob, blob)
assign(:commit, double('Commit', sha: 'whatever')) assign(:commit, double('Commit', sha: 'whatever'))
helper.request.cookies["suggest_gitlab_ci_yml_commit_#{project.id}"] = 'true' helper.request.cookies["suggest_gitlab_ci_yml_commit_#{project.id}"] = 'true'
allow(blob).to receive(:auxiliary_viewer).and_return(double('viewer', valid?: true))
allow(helper).to receive(:current_user).and_return(current_user) allow(helper).to receive(:current_user).and_return(current_user)
end end
context 'when file is a pipeline config file' do
let(:data) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
let(:blob) { fake_blob(path: Gitlab::FileDetector::PATTERNS[:gitlab_ci], data: data) }
context 'experiment enabled' do context 'experiment enabled' do
before do before do
allow(helper).to receive(:experiment_enabled?).and_return(true) allow(helper).to receive(:experiment_enabled?).and_return(true)
...@@ -226,18 +228,16 @@ describe BlobHelper do ...@@ -226,18 +228,16 @@ describe BlobHelper do
end end
context 'file is invalid format' do context 'file is invalid format' do
before do let(:data) { 'foo' }
allow(blob).to receive(:auxiliary_viewer).and_return(double('viewer', valid?: false))
end
it 'is false' do it 'is false' do
expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
end end
end end
context 'path is not a ci file' do context 'does not use the default ci config' do
before do before do
allow(blob).to receive(:path).and_return('something_bad') project.ci_config_path = 'something_bad'
end end
it 'is false' do it 'is false' do
...@@ -245,19 +245,20 @@ describe BlobHelper do ...@@ -245,19 +245,20 @@ describe BlobHelper do
end end
end end
context 'does not use the default ci config' do context 'does not have the needed cookie' do
before do before do
project.ci_config_path = 'something_bad' helper.request.cookies.delete "suggest_gitlab_ci_yml_commit_#{project.id}"
end end
it 'is false' do it 'is false' do
expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
end end
end end
end
context 'does not have the needed cookie' do context 'experiment disabled' do
before do before do
helper.request.cookies.delete "suggest_gitlab_ci_yml_commit_#{project.id}" allow(helper).to receive(:experiment_enabled?).and_return(false)
end end
it 'is false' do it 'is false' do
...@@ -266,9 +267,12 @@ describe BlobHelper do ...@@ -266,9 +267,12 @@ describe BlobHelper do
end end
end end
context 'experiment disabled' do context 'when file is not a pipeline config file' do
let(:blob) { fake_blob(path: 'LICENSE') }
context 'experiment enabled' do
before do before do
allow(helper).to receive(:experiment_enabled?).and_return(false) allow(helper).to receive(:experiment_enabled?).and_return(true)
end end
it 'is false' do it 'is false' do
...@@ -277,6 +281,7 @@ describe BlobHelper do ...@@ -277,6 +281,7 @@ describe BlobHelper do
end end
end end
end end
end
describe 'suggest_pipeline_commit_cookie_name' do describe 'suggest_pipeline_commit_cookie_name' do
let(:project) { create(:project) } let(:project) { create(:project) }
... ...
......
...@@ -83,16 +83,6 @@ describe Gitlab::Ci::Pipeline::Seed::Build::Cache do ...@@ -83,16 +83,6 @@ describe Gitlab::Ci::Pipeline::Seed::Build::Cache do
it_behaves_like 'version and gemfile files' it_behaves_like 'version and gemfile files'
end end
context 'with feature flag disabled' do
let(:files) { ['VERSION', 'Gemfile.zip'] }
before do
stub_feature_flags(ci_file_based_cache: false)
end
it_behaves_like 'default key'
end
context 'with files ending with /' do context 'with files ending with /' do
let(:files) { ['Gemfile.zip/'] } let(:files) { ['Gemfile.zip/'] }
... ...
......
...@@ -8,7 +8,7 @@ describe Ci::GroupVariable do ...@@ -8,7 +8,7 @@ describe Ci::GroupVariable do
it_behaves_like "CI variable" it_behaves_like "CI variable"
it { is_expected.to include_module(Presentable) } it { is_expected.to include_module(Presentable) }
it { is_expected.to include_module(Maskable) } it { is_expected.to include_module(Ci::Maskable) }
it { is_expected.to validate_uniqueness_of(:key).scoped_to(:group_id).with_message(/\(\w+\) has already been taken/) } it { is_expected.to validate_uniqueness_of(:key).scoped_to(:group_id).with_message(/\(\w+\) has already been taken/) }
describe '.unprotected' do describe '.unprotected' do
... ...
......
...@@ -9,7 +9,7 @@ describe Ci::Variable do ...@@ -9,7 +9,7 @@ describe Ci::Variable do
describe 'validations' do describe 'validations' do
it { is_expected.to include_module(Presentable) } it { is_expected.to include_module(Presentable) }
it { is_expected.to include_module(Maskable) } it { is_expected.to include_module(Ci::Maskable) }
it { is_expected.to include_module(HasEnvironmentScope) } it { is_expected.to include_module(HasEnvironmentScope) }
it { is_expected.to validate_uniqueness_of(:key).scoped_to(:project_id, :environment_scope).with_message(/\(\w+\) has already been taken/) } it { is_expected.to validate_uniqueness_of(:key).scoped_to(:project_id, :environment_scope).with_message(/\(\w+\) has already been taken/) }
end end
... ...
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
describe HasVariable do describe Ci::HasVariable do
subject { build(:ci_variable) } subject { build(:ci_variable) }
it { is_expected.to validate_presence_of(:key) } it { is_expected.to validate_presence_of(:key) }
... ...
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
describe Maskable do describe Ci::Maskable do
let(:variable) { build(:ci_variable) } let(:variable) { build(:ci_variable) }
describe 'masked value validations' do describe 'masked value validations' do
...@@ -34,7 +34,7 @@ describe Maskable do ...@@ -34,7 +34,7 @@ describe Maskable do
end end
describe 'REGEX' do describe 'REGEX' do
subject { Maskable::REGEX } subject { Ci::Maskable::REGEX }
it 'does not match strings shorter than 8 letters' do it 'does not match strings shorter than 8 letters' do
expect(subject.match?('hello')).to eq(false) expect(subject.match?('hello')).to eq(false)
... ...
......
# frozen_string_literal: true
require 'spec_helper'
describe JiraImportData do
let(:symbol_keys_project) do
{ key: 'AA', scheduled_at: 2.days.ago.strftime('%Y-%m-%d %H:%M:%S'), scheduled_by: { 'user_id' => 1, 'name' => 'tester1' } }
end
let(:string_keys_project) do
{ 'key': 'BB', 'scheduled_at': 1.hour.ago.strftime('%Y-%m-%d %H:%M:%S'), 'scheduled_by': { 'user_id': 2, 'name': 'tester2' } }
end
let(:jira_project_details) do
JiraImportData::JiraProjectDetails.new('CC', 1.day.ago.strftime('%Y-%m-%d %H:%M:%S'), { user_id: 3, name: 'tester3' })
end
describe '#projects' do
it 'returns empty array if no data' do
expect(described_class.new.projects).to eq([])
end
it 'returns empty array if no projects' do
import_data = described_class.new(data: { 'some-key' => 10 })
expect(import_data.projects).to eq([])
end
it 'returns JiraProjectDetails sorted by scheduled_at time' do
import_data = described_class.new(data: { jira: { projects: [symbol_keys_project, string_keys_project, jira_project_details] } })
expect(import_data.projects.size).to eq 3
expect(import_data.projects.map(&:key)).to eq(%w(AA CC BB))
expect(import_data.projects.map(&:scheduled_by).map {|e| e['name']}).to eq %w(tester1 tester3 tester2)
expect(import_data.projects.map(&:scheduled_by).map {|e| e['user_id']}).to eq [1, 3, 2]
end
end
describe 'add projects' do
it 'adds project when data is nil' do
import_data = described_class.new
expect(import_data.data).to be nil
import_data << string_keys_project
expect(import_data.data).to eq({ 'jira' => { 'projects' => [string_keys_project] } })
end
it 'adds project when data has some random info' do
import_data = described_class.new(data: { 'one-key': 10 })
expect(import_data.data).to eq({ 'one-key' => 10 })
import_data << string_keys_project
expect(import_data.data).to eq({ 'one-key' => 10, 'jira' => { 'projects' => [string_keys_project] } })
end
it 'adds project when data already has some jira projects' do
import_data = described_class.new(data: { jira: { projects: [symbol_keys_project] } })
expect(import_data.projects.map(&:to_h)).to eq [symbol_keys_project]
import_data << string_keys_project
expect(import_data.data['jira']['projects'].size).to eq 2
expect(import_data.projects.map(&:key)).to eq(%w(AA BB))
expect(import_data.projects.map(&:scheduled_by).map {|e| e['name']}).to eq %w(tester1 tester2)
expect(import_data.projects.map(&:scheduled_by).map {|e| e['user_id']}).to eq [1, 2]
end
end
describe '#force_import!' do
it 'sets force import when data is nil' do
import_data = described_class.new
import_data.force_import!
expect(import_data.data['jira'][JiraImportData::FORCE_IMPORT_KEY]).to be true
expect(import_data.force_import?).to be false
end
it 'sets force import when data is present but no jira key' do
import_data = described_class.new(data: { 'some-key': 'some-data' })
import_data.force_import!
expect(import_data.data['jira'][JiraImportData::FORCE_IMPORT_KEY]).to be true
expect(import_data.data).to eq({ 'some-key' => 'some-data', 'jira' => { JiraImportData::FORCE_IMPORT_KEY => true } })
expect(import_data.force_import?).to be false
end
it 'sets force import when data and jira keys exist' do
import_data = described_class.new(data: { 'some-key': 'some-data', 'jira': {} })
import_data.force_import!
expect(import_data.data['jira'][JiraImportData::FORCE_IMPORT_KEY]).to be true
expect(import_data.data).to eq({ 'some-key' => 'some-data', 'jira' => { JiraImportData::FORCE_IMPORT_KEY => true } })
expect(import_data.force_import?).to be false
end
it 'sets force import when data and jira project data exist' do
import_data = described_class.new(data: { jira: { projects: [symbol_keys_project], JiraImportData::FORCE_IMPORT_KEY => false }, 'some-key': 'some-data' })
import_data.force_import!
expect(import_data.data['jira'][JiraImportData::FORCE_IMPORT_KEY]).to be true
expect(import_data.data).to eq({ 'some-key' => 'some-data', 'jira' => { 'projects' => [symbol_keys_project.deep_stringify_keys!], JiraImportData::FORCE_IMPORT_KEY => true } })
expect(import_data.force_import?).to be true
end
end
describe '#force_import?' do
it 'returns false when data blank' do
expect(described_class.new.force_import?).to be false
end
it 'returns false if there is no project data present' do
import_data = described_class.new(data: { jira: { JiraImportData::FORCE_IMPORT_KEY => true }, 'one-key': 10 })
expect(import_data.force_import?).to be false
end
it 'returns false when force import set to false' do
import_data = described_class.new(data: { jira: { projects: [symbol_keys_project], JiraImportData::FORCE_IMPORT_KEY => false }, 'one-key': 10 })
expect(import_data.force_import?).to be false
end
it 'returns true when force import set to true' do
import_data = described_class.new(data: { jira: { projects: [symbol_keys_project], JiraImportData::FORCE_IMPORT_KEY => true } })
expect(import_data.force_import?).to be true
end
end
end
...@@ -2353,6 +2353,63 @@ describe Project do ...@@ -2353,6 +2353,63 @@ describe Project do
expect(project.add_import_job).to eq(import_jid) expect(project.add_import_job).to eq(import_jid)
end end
end end
context 'jira import' do
it 'schedules a jira import job' do
project = create(:project, import_type: 'jira')
expect(Gitlab::JiraImport::Stage::StartImportWorker).to receive(:perform_async).with(project.id).and_return(import_jid)
expect(project.add_import_job).to eq(import_jid)
end
end
end
describe '#jira_import?' do
subject(:project) { build(:project, import_type: 'jira') }
it { expect(project.jira_import?).to be true }
it { expect(project.import?).to be true }
end
describe '#jira_force_import?' do
let(:imported_jira_project) do
JiraImportData::JiraProjectDetails.new('xx', Time.now.strftime('%Y-%m-%d %H:%M:%S'), { user_id: 1, name: 'root' })
end
let(:jira_import_data) do
data = JiraImportData.new
data << imported_jira_project
data.force_import!
data
end
subject(:project) { build(:project, import_type: 'jira', import_data: jira_import_data) }
it { expect(project.jira_force_import?).to be true }
end
describe '#remove_import_data' do
let(:import_data) { ProjectImportData.new(data: { 'test' => 'some data' }) }
context 'when jira import' do
let!(:project) { create(:project, import_type: 'jira', import_data: import_data) }
it 'does not remove import data' do
expect(project.mirror?).to be false
expect(project.jira_import?).to be true
expect { project.remove_import_data }.not_to change { ProjectImportData.count }
end
end
context 'when not mirror neither jira import' do
let(:user) { create(:user) }
let!(:project) { create(:project, import_type: 'github', import_data: import_data) }
it 'removes import data' do
expect(project.mirror?).to be false
expect(project.jira_import?).to be false
expect { project.remove_import_data }.to change { ProjectImportData.count }.by(-1)
end
end
end end
describe '#gitlab_project_import?' do describe '#gitlab_project_import?' do
... ...
......
...@@ -40,6 +40,16 @@ describe Milestones::TransferService do ...@@ -40,6 +40,16 @@ describe Milestones::TransferService do
expect(new_milestone.project_milestone?).to be_truthy expect(new_milestone.project_milestone?).to be_truthy
end end
context 'when milestone is from an ancestor group' do
let(:old_group_ancestor) { create(:group) }
let(:old_group) { create(:group, parent: old_group_ancestor) }
let(:group_milestone) { create(:milestone, group: old_group_ancestor)}
it 'recreates the missing group milestones at project level' do
expect { service.execute }.to change(project.milestones, :count).by(1)
end
end
it 'deletes milestone issue counters cache for both milestones' do it 'deletes milestone issue counters cache for both milestones' do
new_milestone = create(:milestone, project: project, title: group_milestone.title) new_milestone = create(:milestone, project: project, title: group_milestone.title)
... ...
......
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples 'CI variable' do RSpec.shared_examples 'CI variable' do
it { is_expected.to include_module(HasVariable) } it { is_expected.to include_module(Ci::HasVariable) }
describe "variable type" do describe "variable type" do
it 'defines variable types' do it 'defines variable types' do
... ...
......
# frozen_string_literal: true
shared_examples 'include import workers modules' do
it { expect(described_class).to include_module(ApplicationWorker) }
it { expect(described_class).to include_module(Gitlab::JiraImport::QueueOptions) }
if described_class == Gitlab::JiraImport::Stage::StartImportWorker
it { expect(described_class).to include_module(ProjectStartImport) }
it { expect(described_class).to include_module(ProjectImportOptions) }
else
it { expect(described_class).to include_module(Gitlab::JiraImport::ImportWorker) }
end
end
shared_examples 'exit import not started' do
it 'does nothing, and exits' do
expect(Gitlab::JiraImport::AdvanceStageWorker).not_to receive(:perform_async)
worker.perform(project.id)
end
end
shared_examples 'advance to next stage' do |next_stage|
let(:job_waiter) { Gitlab::JobWaiter.new(2, 'some-job-key') }
it "advances to #{next_stage} stage" do
expect(Gitlab::JobWaiter).to receive(:new).and_return(job_waiter)
expect(Gitlab::JiraImport::AdvanceStageWorker).to receive(:perform_async).with(project.id, { job_waiter.key => job_waiter.jobs_remaining }, next_stage.to_sym)
worker.perform(project.id)
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::JiraImport::Stage::FinishImportWorker do
let(:project) { create(:project) }
let(:worker) { described_class.new }
describe 'modules' do
it_behaves_like 'include import workers modules'
end
describe '#perform' do
context 'when feature flag enabled' do
before do
stub_feature_flags(jira_issue_import: false)
end
it_behaves_like 'exit import not started'
end
context 'when feature flag enabled' do
before do
stub_feature_flags(jira_issue_import: true)
end
context 'when import did not start' do
let!(:import_state) { create(:import_state, project: project) }
it_behaves_like 'exit import not started'
end
context 'when import started' do
let(:imported_jira_project) do
JiraImportData::JiraProjectDetails.new('xx', Time.now.strftime('%Y-%m-%d %H:%M:%S'), { user_id: 1, name: 'root' })
end
let(:jira_import_data) do
data = JiraImportData.new
data << imported_jira_project
data.force_import!
data
end
let(:import_state) { create(:import_state, status: :started) }
let(:project) { create(:project, import_type: 'jira', import_data: jira_import_data, import_state: import_state) }
it 'changes import state to finished' do
worker.perform(project.id)
expect(project.reload.import_state.status).to eq "finished"
end
it 'removes force-import flag' do
expect(project.reload.import_data.data['jira'][JiraImportData::FORCE_IMPORT_KEY]).to be true
worker.perform(project.id)
expect(project.reload.import_data.data['jira'][JiraImportData::FORCE_IMPORT_KEY]).to be nil
expect(project.reload.import_data.data['jira']).not_to be nil
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::JiraImport::Stage::ImportAttachmentsWorker do
let(:project) { create(:project) }
let(:worker) { described_class.new }
describe 'modules' do
it_behaves_like 'include import workers modules'
end
describe '#perform' do
context 'when feature flag enabled' do
before do
stub_feature_flags(jira_issue_import: false)
end
it_behaves_like 'exit import not started'
end
context 'when feature flag enabled' do
before do
stub_feature_flags(jira_issue_import: true)
end
context 'when import did not start' do
let!(:import_state) { create(:import_state, project: project) }
it_behaves_like 'exit import not started'
end
context 'when import started' do
let!(:import_state) { create(:import_state, status: :started, project: project) }
it_behaves_like 'advance to next stage', :notes
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::JiraImport::Stage::ImportIssuesWorker do
let(:project) { create(:project) }
let(:worker) { described_class.new }
describe 'modules' do
it_behaves_like 'include import workers modules'
end
describe '#perform' do
context 'when feature flag enabled' do
before do
stub_feature_flags(jira_issue_import: false)
end
it_behaves_like 'exit import not started'
end
context 'when feature flag enabled' do
before do
stub_feature_flags(jira_issue_import: true)
end
context 'when import did not start' do
let!(:import_state) { create(:import_state, project: project) }
it_behaves_like 'exit import not started'
end
context 'when import started' do
let!(:import_state) { create(:import_state, status: :started, project: project) }
it_behaves_like 'advance to next stage', :attachments
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::JiraImport::Stage::ImportLabelsWorker do
let(:project) { create(:project) }
let(:worker) { described_class.new }
describe 'modules' do
it_behaves_like 'include import workers modules'
end
describe '#perform' do
context 'when feature flag enabled' do
before do
stub_feature_flags(jira_issue_import: false)
end
it_behaves_like 'exit import not started'
end
context 'when feature flag enabled' do
before do
stub_feature_flags(jira_issue_import: true)
end
context 'when import did not start' do
let!(:import_state) { create(:import_state, project: project) }
it_behaves_like 'exit import not started'
end
context 'when import started' do
let!(:import_state) { create(:import_state, status: :started, project: project) }
it_behaves_like 'advance to next stage', :issues
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::JiraImport::Stage::ImportNotesWorker do
let(:project) { create(:project) }
let(:worker) { described_class.new }
describe 'modules' do
it_behaves_like 'include import workers modules'
end
describe '#perform' do
context 'when feature flag enabled' do
before do
stub_feature_flags(jira_issue_import: false)
end
it_behaves_like 'exit import not started'
end
context 'when feature flag enabled' do
before do
stub_feature_flags(jira_issue_import: true)
end
context 'when import did not start' do
let!(:import_state) { create(:import_state, project: project) }
it_behaves_like 'exit import not started'
end
context 'when import started' do
let!(:import_state) { create(:import_state, status: :started, project: project) }
it_behaves_like 'advance to next stage', :finish
end
end
end
end