diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-01-18 22:00:14 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-01-18 22:00:14 +0300 |
commit | 05f0ebba3a2c8ddf39e436f412dc2ab5bf1353b2 (patch) | |
tree | 11d0f2a6ec31c7793c184106cedc2ded3d9a2cc5 /spec/workers | |
parent | ec73467c23693d0db63a797d10194da9e72a74af (diff) |
Add latest changes from gitlab-org/gitlab@15-8-stable-eev15.8.0-rc42
Diffstat (limited to 'spec/workers')
21 files changed, 423 insertions, 236 deletions
diff --git a/spec/workers/ci/build_finished_worker_spec.rb b/spec/workers/ci/build_finished_worker_spec.rb index e8bb3988001..049f3af1dd7 100644 --- a/spec/workers/ci/build_finished_worker_spec.rb +++ b/spec/workers/ci/build_finished_worker_spec.rb @@ -65,6 +65,12 @@ RSpec.describe Ci::BuildFinishedWorker do subject end end + + context 'when it has a token' do + it 'removes the token' do + expect { subject }.to change { build.reload.token }.to(nil) + end + end end context 'when build does not exist' do diff --git a/spec/workers/ci/initial_pipeline_process_worker_spec.rb b/spec/workers/ci/initial_pipeline_process_worker_spec.rb index 5fb8671fd5c..c7bbe83433e 100644 --- a/spec/workers/ci/initial_pipeline_process_worker_spec.rb +++ b/spec/workers/ci/initial_pipeline_process_worker_spec.rb @@ -2,12 +2,13 @@ require 'spec_helper' -RSpec.describe Ci::InitialPipelineProcessWorker do - describe '#perform' do - let_it_be_with_reload(:pipeline) do - create(:ci_pipeline, :with_job, status: :created) - end +RSpec.describe Ci::InitialPipelineProcessWorker, feature_category: :continuous_integration do + let_it_be(:project) { create(:project, :repository) } + let(:job) { build(:ci_build, project: project) } + let(:stage) { build(:ci_stage, project: project, statuses: [job]) } + let(:pipeline) { create(:ci_pipeline, stages: [stage], status: :created, project: project, builds: [job]) } + describe '#perform' do include_examples 'an idempotent worker' do let(:job_args) { pipeline.id } @@ -19,5 +20,52 @@ RSpec.describe Ci::InitialPipelineProcessWorker do expect(pipeline.reload).to be_pending end end + + context 'when a pipeline does not contain a deployment job' do + it 'does not create any deployments' do + expect { subject }.not_to change { Deployment.count } + end + end + + context 'when a pipeline contains a teardown job' do + let(:job) { build(:ci_build, :stop_review_app, project: project) } + + before do + create(:environment, name: job.expanded_environment_name) + end + + it 'does not create a deployment record' do + expect { subject }.not_to change { Deployment.count } + + expect(job.deployment).to be_nil + end + end + + context 'when a pipeline contains a deployment job' do + let(:job) { build(:ci_build, :start_review_app, project: project) } + let!(:environment) { create(:environment, project: project, name: job.expanded_environment_name) } + + it 'creates a deployment record' do + expect { subject }.to change { Deployment.count }.by(1) + + expect(job.deployment).to have_attributes( + project: job.project, + ref: job.ref, + sha: job.sha, + deployable: job, + deployable_type: 'CommitStatus', + environment: job.persisted_environment) + end + + context 'when the corresponding environment does not exist' do + let(:environment) {} + + it 'does not create a deployment record' do + expect { subject }.not_to change { Deployment.count } + + expect(job.deployment).to be_nil + end + end + end end end diff --git a/spec/workers/cluster_provision_worker_spec.rb b/spec/workers/cluster_provision_worker_spec.rb deleted file mode 100644 index 2d6ca4ab7e3..00000000000 --- a/spec/workers/cluster_provision_worker_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ClusterProvisionWorker do - describe '#perform' do - context 'when provider type is gcp' do - let(:cluster) { create(:cluster, provider_type: :gcp, provider_gcp: provider) } - let(:provider) { create(:cluster_provider_gcp, :scheduled) } - - it 'provision a cluster' do - expect_any_instance_of(Clusters::Gcp::ProvisionService).to receive(:execute).with(provider) - - described_class.new.perform(cluster.id) - end - end - - context 'when provider type is aws' do - let(:cluster) { create(:cluster, provider_type: :aws, provider_aws: provider) } - let(:provider) { create(:cluster_provider_aws, :scheduled) } - - it 'provision a cluster' do - expect_any_instance_of(Clusters::Aws::ProvisionService).to receive(:execute).with(provider) - - described_class.new.perform(cluster.id) - end - end - - context 'when provider type is user' do - let(:cluster) { create(:cluster, :provided_by_user) } - - it 'does not provision a cluster' do - expect_any_instance_of(Clusters::Gcp::ProvisionService).not_to receive(:execute) - - described_class.new.perform(cluster.id) - end - end - - context 'when cluster does not exist' do - it 'does not provision a cluster' do - expect_any_instance_of(Clusters::Gcp::ProvisionService).not_to receive(:execute) - - described_class.new.perform(123) - end - end - end -end diff --git a/spec/workers/counters/cleanup_refresh_worker_spec.rb b/spec/workers/counters/cleanup_refresh_worker_spec.rb new file mode 100644 index 00000000000..a56c98f72a0 --- /dev/null +++ b/spec/workers/counters/cleanup_refresh_worker_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Counters::CleanupRefreshWorker do + let(:model) { create(:project_statistics) } + + describe '#perform', :redis do + let(:attribute) { :build_artifacts_size } + let(:worker) { described_class.new } + + subject { worker.perform(model.class.name, model.id, attribute) } + + it 'calls cleanup_refresh on the counter' do + expect_next_instance_of(Gitlab::Counters::BufferedCounter, model, attribute) do |counter| + expect(counter).to receive(:cleanup_refresh) + end + + subject + end + + context 'when model class does not exist' do + subject { worker.perform('NonExistentModel', 1, attribute) } + + it 'does nothing' do + expect(Gitlab::Counters::BufferedCounter).not_to receive(:new) + + subject + end + end + + context 'when record does not exist' do + subject { worker.perform(model.class.name, non_existing_record_id, attribute) } + + it 'does nothing' do + expect(Gitlab::Counters::BufferedCounter).not_to receive(:new) + + subject + end + end + end +end diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb index 788f5d8222c..c444e1f383c 100644 --- a/spec/workers/every_sidekiq_worker_spec.rb +++ b/spec/workers/every_sidekiq_worker_spec.rb @@ -210,6 +210,7 @@ RSpec.describe 'Every Sidekiq worker' do 'Deployments::LinkMergeRequestWorker' => 3, 'Deployments::SuccessWorker' => 3, 'Deployments::UpdateEnvironmentWorker' => 3, + 'Deployments::ApprovalWorker' => 3, 'DesignManagement::CopyDesignCollectionWorker' => 3, 'DesignManagement::NewVersionWorker' => 3, 'DestroyPagesDeploymentsWorker' => 3, diff --git a/spec/workers/gitlab/github_gists_import/finish_import_worker_spec.rb b/spec/workers/gitlab/github_gists_import/finish_import_worker_spec.rb index c4c19f2f9c5..cba6c578d11 100644 --- a/spec/workers/gitlab/github_gists_import/finish_import_worker_spec.rb +++ b/spec/workers/gitlab/github_gists_import/finish_import_worker_spec.rb @@ -2,13 +2,17 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubGistsImport::FinishImportWorker, feature_category: :importer do +RSpec.describe Gitlab::GithubGistsImport::FinishImportWorker, :clean_gitlab_redis_cache, feature_category: :importers do subject(:worker) { described_class.new } let_it_be(:user) { create(:user) } describe '#perform', :aggregate_failures do context 'when there are no remaining jobs' do + before do + allow(Gitlab::Cache::Import::Caching).to receive(:values_from_hash).and_return(nil) + end + it 'marks import status as finished' do waiter = instance_double(Gitlab::JobWaiter, key: :key, jobs_remaining: 0) expect(Gitlab::JobWaiter).to receive(:new).and_return(waiter) @@ -19,6 +23,8 @@ RSpec.describe Gitlab::GithubGistsImport::FinishImportWorker, feature_category: expect(Gitlab::GithubImport::Logger) .to receive(:info) .with(user_id: user.id, message: 'GitHub Gists import finished') + expect(Notify).not_to receive(:github_gists_import_errors_email) + expect(Gitlab::Cache::Import::Caching).to receive(:expire).and_call_original worker.perform(user.id, waiter.key, waiter.jobs_remaining) end @@ -35,6 +41,33 @@ RSpec.describe Gitlab::GithubGistsImport::FinishImportWorker, feature_category: worker.perform(user.id, waiter.key, waiter.jobs_remaining) end end + + context 'when some gists were failed to import' do + let(:errors) { { '12345' => 'Snippet maximum file count exceeded.' } } + let(:waiter) { instance_double(Gitlab::JobWaiter, key: :key, jobs_remaining: 0) } + let(:mail_instance) { instance_double(ActionMailer::MessageDelivery, deliver_now: true) } + + before do + allow(Gitlab::Cache::Import::Caching).to receive(:values_from_hash).and_return(errors) + allow(Gitlab::JobWaiter).to receive(:new).and_return(waiter) + allow(waiter).to receive(:wait).with(described_class::BLOCKING_WAIT_TIME) + end + + it 'sends an email to user' do + expect_next_instance_of(Gitlab::GithubGistsImport::Status) do |status| + expect(status).to receive(:finish!) + end + expect(Gitlab::GithubImport::Logger) + .to receive(:info) + .with(user_id: user.id, message: 'GitHub Gists import finished') + expect(Notify).to receive(:github_gists_import_errors_email) + .with(user.id, errors).once.and_return(mail_instance) + expect(mail_instance).to receive(:deliver_now) + expect(Gitlab::Cache::Import::Caching).to receive(:expire).and_call_original + + worker.perform(user.id, waiter.key, waiter.jobs_remaining) + end + end end describe '.sidekiq_retries_exhausted' do diff --git a/spec/workers/gitlab/github_gists_import/import_gist_worker_spec.rb b/spec/workers/gitlab/github_gists_import/import_gist_worker_spec.rb index dfc5084bb10..1c24cdcccae 100644 --- a/spec/workers/gitlab/github_gists_import/import_gist_worker_spec.rb +++ b/spec/workers/gitlab/github_gists_import/import_gist_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubGistsImport::ImportGistWorker, feature_category: :importer do +RSpec.describe Gitlab::GithubGistsImport::ImportGistWorker, feature_category: :importers do subject { described_class.new } let_it_be(:user) { create(:user) } diff --git a/spec/workers/gitlab/github_gists_import/start_import_worker_spec.rb b/spec/workers/gitlab/github_gists_import/start_import_worker_spec.rb index 523b7463a9d..220f2bb0c75 100644 --- a/spec/workers/gitlab/github_gists_import/start_import_worker_spec.rb +++ b/spec/workers/gitlab/github_gists_import/start_import_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubGistsImport::StartImportWorker, feature_category: :importer do +RSpec.describe Gitlab::GithubGistsImport::StartImportWorker, feature_category: :importers do subject(:worker) { described_class.new } let_it_be(:user) { create(:user) } diff --git a/spec/workers/gitlab/github_import/import_protected_branch_worker_spec.rb b/spec/workers/gitlab/github_import/import_protected_branch_worker_spec.rb index 4a3ef2bf560..c2b8ee661a3 100644 --- a/spec/workers/gitlab/github_import/import_protected_branch_worker_spec.rb +++ b/spec/workers/gitlab/github_import/import_protected_branch_worker_spec.rb @@ -14,7 +14,8 @@ RSpec.describe Gitlab::GithubImport::ImportProtectedBranchWorker do let(:json_hash) do { id: 'main', - allow_force_pushes: true + allow_force_pushes: true, + allowed_to_push_users: [] } end diff --git a/spec/workers/merge_requests/create_pipeline_worker_spec.rb b/spec/workers/merge_requests/create_pipeline_worker_spec.rb index 441d7652219..afb9fa1a549 100644 --- a/spec/workers/merge_requests/create_pipeline_worker_spec.rb +++ b/spec/workers/merge_requests/create_pipeline_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe MergeRequests::CreatePipelineWorker do +RSpec.describe MergeRequests::CreatePipelineWorker, feature_category: :continuous_integration do describe '#perform' do let(:user) { create(:user) } let(:project) { create(:project) } @@ -17,7 +17,7 @@ RSpec.describe MergeRequests::CreatePipelineWorker do expect_next_instance_of(MergeRequests::CreatePipelineService, project: project, current_user: user, - params: { push_options: nil }) do |service| + params: { allow_duplicate: nil, push_options: nil }) do |service| expect(service).to receive(:execute).with(merge_request) end @@ -38,7 +38,7 @@ RSpec.describe MergeRequests::CreatePipelineWorker do expect_next_instance_of(MergeRequests::CreatePipelineService, project: project, current_user: user, - params: { push_options: { ci: { skip: true } } }) do |service| + params: { allow_duplicate: nil, push_options: { ci: { skip: true } } }) do |service| expect(service).to receive(:execute).with(merge_request) end diff --git a/spec/workers/pages/invalidate_domain_cache_worker_spec.rb b/spec/workers/pages/invalidate_domain_cache_worker_spec.rb index c786d4658d4..b3c81b25a93 100644 --- a/spec/workers/pages/invalidate_domain_cache_worker_spec.rb +++ b/spec/workers/pages/invalidate_domain_cache_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Pages::InvalidateDomainCacheWorker do +RSpec.describe Pages::InvalidateDomainCacheWorker, feature_category: :pages do shared_examples 'clears caches with' do |event_class:, event_data:, caches:| include AfterNextHelpers @@ -22,44 +22,70 @@ RSpec.describe Pages::InvalidateDomainCacheWorker do end end + context 'when a project have multiple domains' do + include AfterNextHelpers + + let_it_be(:project) { create(:project) } + let_it_be(:pages_domain) { create(:pages_domain, project: project) } + let_it_be(:pages_domain2) { create(:pages_domain, project: project) } + + let(:event) do + Pages::PageDeployedEvent.new( + data: { + project_id: project.id, + namespace_id: project.namespace_id, + root_namespace_id: project.root_ancestor.id + } + ) + end + + subject { consume_event(subscriber: described_class, event: event) } + + it 'clears the cache with Gitlab::Pages::CacheControl' do + expect_next(Gitlab::Pages::CacheControl, type: :namespace, id: project.namespace_id) + .to receive(:clear_cache) + expect_next(Gitlab::Pages::CacheControl, type: :domain, id: pages_domain.id) + .to receive(:clear_cache) + expect_next(Gitlab::Pages::CacheControl, type: :domain, id: pages_domain2.id) + .to receive(:clear_cache) + + subject + end + end + it_behaves_like 'clears caches with', event_class: Pages::PageDeployedEvent, event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 }, caches: [ - { type: :namespace, id: 3 }, - { type: :project, id: 1 } + { type: :namespace, id: 3 } ] it_behaves_like 'clears caches with', event_class: Pages::PageDeletedEvent, event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 }, caches: [ - { type: :namespace, id: 3 }, - { type: :project, id: 1 } + { type: :namespace, id: 3 } ] it_behaves_like 'clears caches with', event_class: Projects::ProjectDeletedEvent, event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 }, caches: [ - { type: :namespace, id: 3 }, - { type: :project, id: 1 } + { type: :namespace, id: 3 } ] it_behaves_like 'clears caches with', event_class: Projects::ProjectCreatedEvent, event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 }, caches: [ - { type: :namespace, id: 3 }, - { type: :project, id: 1 } + { type: :namespace, id: 3 } ] it_behaves_like 'clears caches with', event_class: Projects::ProjectArchivedEvent, event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 }, caches: [ - { type: :namespace, id: 3 }, - { type: :project, id: 1 } + { type: :namespace, id: 3 } ] it_behaves_like 'clears caches with', @@ -72,8 +98,7 @@ RSpec.describe Pages::InvalidateDomainCacheWorker do new_path: 'new_path' }, caches: [ - { type: :namespace, id: 3 }, - { type: :project, id: 1 } + { type: :namespace, id: 3 } ] it_behaves_like 'clears caches with', @@ -86,7 +111,6 @@ RSpec.describe Pages::InvalidateDomainCacheWorker do new_root_namespace_id: 5 }, caches: [ - { type: :project, id: 1 }, { type: :namespace, id: 3 }, { type: :namespace, id: 5 } ] @@ -131,10 +155,11 @@ RSpec.describe Pages::InvalidateDomainCacheWorker do project_id: 1, namespace_id: 2, root_namespace_id: 3, + domain_id: 4, domain: 'somedomain.com' }, caches: [ - { type: :project, id: 1 }, + { type: :domain, id: 4 }, { type: :namespace, id: 3 } ] @@ -144,10 +169,11 @@ RSpec.describe Pages::InvalidateDomainCacheWorker do project_id: 1, namespace_id: 2, root_namespace_id: 3, + domain_id: 4, domain: 'somedomain.com' }, caches: [ - { type: :project, id: 1 }, + { type: :domain, id: 4 }, { type: :namespace, id: 3 } ] @@ -157,10 +183,11 @@ RSpec.describe Pages::InvalidateDomainCacheWorker do project_id: 1, namespace_id: 2, root_namespace_id: 3, + domain_id: 4, domain: 'somedomain.com' }, caches: [ - { type: :project, id: 1 }, + { type: :domain, id: 4 }, { type: :namespace, id: 3 } ] @@ -172,10 +199,11 @@ RSpec.describe Pages::InvalidateDomainCacheWorker do project_id: 1, namespace_id: 2, root_namespace_id: 3, + domain_id: 4, attributes: [attribute] }, caches: [ - { type: :project, id: 1 }, + { type: :domain, id: 4 }, { type: :namespace, id: 3 } ] end @@ -204,7 +232,6 @@ RSpec.describe Pages::InvalidateDomainCacheWorker do features: ['pages_access_level'] }, caches: [ - { type: :project, id: 1 }, { type: :namespace, id: 3 } ] @@ -234,7 +261,6 @@ RSpec.describe Pages::InvalidateDomainCacheWorker do new_root_namespace_id: 5 }, caches: [ - { type: :project, id: 1 }, { type: :namespace, id: 5 } ] end diff --git a/spec/workers/personal_access_tokens/expired_notification_worker_spec.rb b/spec/workers/personal_access_tokens/expired_notification_worker_spec.rb index 3ff67f47523..7c3c48b3f80 100644 --- a/spec/workers/personal_access_tokens/expired_notification_worker_spec.rb +++ b/spec/workers/personal_access_tokens/expired_notification_worker_spec.rb @@ -11,7 +11,7 @@ RSpec.describe PersonalAccessTokens::ExpiredNotificationWorker, type: :worker do it 'uses notification service to send email to the user' do expect_next_instance_of(NotificationService) do |notification_service| - expect(notification_service).to receive(:access_token_expired).with(expired_today.user) + expect(notification_service).to receive(:access_token_expired).with(expired_today.user, [expired_today.name]) end worker.perform @@ -25,7 +25,7 @@ RSpec.describe PersonalAccessTokens::ExpiredNotificationWorker, type: :worker do shared_examples 'expiry notification is not required to be sent for the token' do it do expect_next_instance_of(NotificationService) do |notification_service| - expect(notification_service).not_to receive(:access_token_expired).with(token.user) + expect(notification_service).not_to receive(:access_token_expired).with(token.user, [token.name]) end worker.perform diff --git a/spec/workers/pipeline_schedule_worker_spec.rb b/spec/workers/pipeline_schedule_worker_spec.rb index d23907a8def..db58dc00338 100644 --- a/spec/workers/pipeline_schedule_worker_spec.rb +++ b/spec/workers/pipeline_schedule_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe PipelineScheduleWorker do +RSpec.describe PipelineScheduleWorker, :sidekiq_inline, feature_category: :continuous_integration do include ExclusiveLeaseHelpers subject { described_class.new.perform } @@ -30,7 +30,7 @@ RSpec.describe PipelineScheduleWorker do project.add_maintainer(user) end - context 'when there is a scheduled pipeline within next_run_at', :sidekiq_inline do + context 'when there is a scheduled pipeline within next_run_at' do shared_examples 'successful scheduling' do it 'creates a new pipeline' do expect { subject }.to change { project.ci_pipelines.count }.by(1) @@ -49,7 +49,19 @@ RSpec.describe PipelineScheduleWorker do end end - it_behaves_like 'successful scheduling' + shared_examples 'successful scheduling with/without ci_use_run_pipeline_schedule_worker' do + it_behaves_like 'successful scheduling' + + context 'when feature flag ci_use_run_pipeline_schedule_worker is disabled' do + before do + stub_feature_flags(ci_use_run_pipeline_schedule_worker: false) + end + + it_behaves_like 'successful scheduling' + end + end + + it_behaves_like 'successful scheduling with/without ci_use_run_pipeline_schedule_worker' context 'when the latest commit contains [ci skip]' do before do @@ -58,7 +70,7 @@ RSpec.describe PipelineScheduleWorker do .and_return('some commit [ci skip]') end - it_behaves_like 'successful scheduling' + it_behaves_like 'successful scheduling with/without ci_use_run_pipeline_schedule_worker' end end @@ -123,4 +135,13 @@ RSpec.describe PipelineScheduleWorker do expect { subject }.not_to raise_error end end + + context 'when max retry attempts reach' do + let!(:lease) { stub_exclusive_lease_taken(described_class.name.underscore) } + + it 'does not raise error' do + expect(lease).to receive(:try_obtain).exactly(described_class::LOCK_RETRY + 1).times + expect { subject }.to raise_error(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError) + end + end end diff --git a/spec/workers/projects/delete_branch_worker_spec.rb b/spec/workers/projects/delete_branch_worker_spec.rb index c1289f56929..771ab3def84 100644 --- a/spec/workers/projects/delete_branch_worker_spec.rb +++ b/spec/workers/projects/delete_branch_worker_spec.rb @@ -64,9 +64,11 @@ RSpec.describe Projects::DeleteBranchWorker, feature_category: :source_code_mana expect(instance).to receive(:execute).with(branch).and_return(service_result) end - expect(service_result).to receive(:track_and_raise_exception).and_call_original + expect(service_result).to receive(:log_and_raise_exception).and_call_original - expect { worker.perform(project.id, user.id, branch) }.to raise_error(StandardError) + expect do + worker.perform(project.id, user.id, branch) + end.to raise_error(Projects::DeleteBranchWorker::GitReferenceLockedError) end end @@ -78,25 +80,7 @@ RSpec.describe Projects::DeleteBranchWorker, feature_category: :source_code_mana expect(instance).to receive(:execute).with(branch).and_return(service_result) end - expect(service_result).not_to receive(:track_and_raise_exception) - - expect { worker.perform(project.id, user.id, branch) }.not_to raise_error - end - end - - context 'when track_and_raise_delete_source_errors is disabled' do - let(:status_code) { 400 } - - before do - stub_feature_flags(track_and_raise_delete_source_errors: false) - end - - it 'does not track the exception' do - expect_next_instance_of(::Branches::DeleteService) do |instance| - expect(instance).to receive(:execute).with(branch).and_return(service_result) - end - - expect(service_result).not_to receive(:track_and_raise_exception) + expect(service_result).not_to receive(:log_and_raise_exception) expect { worker.perform(project.id, user.id, branch) }.not_to raise_error end diff --git a/spec/workers/projects/finalize_project_statistics_refresh_worker_spec.rb b/spec/workers/projects/finalize_project_statistics_refresh_worker_spec.rb new file mode 100644 index 00000000000..932ba29f806 --- /dev/null +++ b/spec/workers/projects/finalize_project_statistics_refresh_worker_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::FinalizeProjectStatisticsRefreshWorker do + let_it_be(:record) { create(:project_build_artifacts_size_refresh, :finalizing) } + + describe '#perform' do + let(:attribute) { record.class.counter_attributes.first } + let(:worker) { described_class.new } + + subject { worker.perform(record.class.name, record.id) } + + it 'stores the refresh increment to the buffered counter' do + expect(record.class).to receive(:find_by_id).and_return(record) + expect(record).to receive(:finalize!) + + subject + end + + context 'when record class does not exist' do + subject { worker.perform('NonExistentModel', 1) } + + it 'does nothing' do + expect(record).not_to receive(:finalize!) + + subject + end + end + + context 'when record does not exist' do + subject { worker.perform(record.class.name, non_existing_record_id) } + + it 'does nothing' do + expect(record).not_to receive(:finalize!) + + subject + end + end + end +end diff --git a/spec/workers/projects/git_garbage_collect_worker_spec.rb b/spec/workers/projects/git_garbage_collect_worker_spec.rb index ae567107443..899e3ed2007 100644 --- a/spec/workers/projects/git_garbage_collect_worker_spec.rb +++ b/spec/workers/projects/git_garbage_collect_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::GitGarbageCollectWorker do +RSpec.describe Projects::GitGarbageCollectWorker, feature_category: :source_code_management do let_it_be(:project) { create(:project, :repository) } it_behaves_like 'can collect git garbage' do @@ -24,8 +24,7 @@ RSpec.describe Projects::GitGarbageCollectWorker do end context 'when the repository has joined a pool' do - let!(:pool) { create(:pool_repository, :ready) } - let(:project) { pool.source_project } + let_it_be(:pool) { create(:pool_repository, :ready, source_project: project) } it 'ensures the repositories are linked' do expect(project.pool_repository).to receive(:link_repository).once diff --git a/spec/workers/projects/refresh_build_artifacts_size_statistics_worker_spec.rb b/spec/workers/projects/refresh_build_artifacts_size_statistics_worker_spec.rb index c7e45e7e4d7..00c45255316 100644 --- a/spec/workers/projects/refresh_build_artifacts_size_statistics_worker_spec.rb +++ b/spec/workers/projects/refresh_build_artifacts_size_statistics_worker_spec.rb @@ -62,14 +62,38 @@ RSpec.describe Projects::RefreshBuildArtifactsSizeStatisticsWorker do describe '#max_running_jobs' do subject { worker.max_running_jobs } - it { is_expected.to eq(10) } + before do + stub_feature_flags( + projects_build_artifacts_size_refresh: false, + projects_build_artifacts_size_refresh_medium: false, + projects_build_artifacts_size_refresh_high: false + ) + end - context 'when projects_build_artifacts_size_refresh flag is disabled' do + it { is_expected.to eq(0) } + + context 'when projects_build_artifacts_size_refresh flag is enabled' do before do - stub_feature_flags(projects_build_artifacts_size_refresh: false) + stub_feature_flags(projects_build_artifacts_size_refresh: true) end - it { is_expected.to eq(0) } + it { is_expected.to eq(described_class::MAX_RUNNING_LOW) } + end + + context 'when projects_build_artifacts_size_refresh_medium flag is enabled' do + before do + stub_feature_flags(projects_build_artifacts_size_refresh_medium: true) + end + + it { is_expected.to eq(described_class::MAX_RUNNING_MEDIUM) } + end + + context 'when projects_build_artifacts_size_refresh_high flag is enabled' do + before do + stub_feature_flags(projects_build_artifacts_size_refresh_high: true) + end + + it { is_expected.to eq(described_class::MAX_RUNNING_HIGH) } end end end diff --git a/spec/workers/repository_import_worker_spec.rb b/spec/workers/repository_import_worker_spec.rb index 1dc77fbf83f..ca7c13fe24e 100644 --- a/spec/workers/repository_import_worker_spec.rb +++ b/spec/workers/repository_import_worker_spec.rb @@ -2,92 +2,88 @@ require 'spec_helper' -RSpec.describe RepositoryImportWorker do +RSpec.describe RepositoryImportWorker, feature_category: :importers do describe '#perform' do - let(:project) { create(:project, :import_scheduled) } - let(:import_state) { project.import_state } - - context 'when worker was reset without cleanup' do - it 'imports the project successfully' do - jid = '12345678' - started_project = create(:project) - started_import_state = create(:import_state, :started, project: started_project, jid: jid) - - allow(subject).to receive(:jid).and_return(jid) + let(:project) { build_stubbed(:project, :import_scheduled, import_state: import_state, import_url: 'url') } + let(:import_state) { create(:import_state, status: :scheduled) } + let(:jid) { '12345678' } + + before do + allow(subject).to receive(:jid).and_return(jid) + allow(Project).to receive(:find_by_id).with(project.id).and_return(project) + allow(project).to receive(:after_import) + allow(import_state).to receive(:start).and_return(true) + end - expect_next_instance_of(Projects::ImportService) do |instance| - expect(instance).to receive(:execute).and_return({ status: :ok }) - end + context 'when project not found (deleted)' do + before do + allow(Project).to receive(:find_by_id).with(project.id).and_return(nil) + end - # Works around https://github.com/rspec/rspec-mocks/issues/910 - expect(Project).to receive(:find).with(started_project.id).and_return(started_project) - expect(started_project.repository).to receive(:expire_emptiness_caches) - expect(started_project.wiki.repository).to receive(:expire_emptiness_caches) - expect(started_import_state).to receive(:finish) + it 'does not raise any exception' do + expect(Projects::ImportService).not_to receive(:new) - subject.perform(started_project.id) + expect { subject.perform(project.id) }.not_to raise_error end end - context 'when the import was successful' do - it 'imports a project' do + context 'when import_state is scheduled' do + it 'imports the project successfully' do expect_next_instance_of(Projects::ImportService) do |instance| expect(instance).to receive(:execute).and_return({ status: :ok }) end - # Works around https://github.com/rspec/rspec-mocks/issues/910 - expect(Project).to receive(:find).with(project.id).and_return(project) - expect(project.repository).to receive(:expire_emptiness_caches) - expect(project.wiki.repository).to receive(:expire_emptiness_caches) - expect(import_state).to receive(:finish) - subject.perform(project.id) + + expect(project).to have_received(:after_import) + expect(import_state).to have_received(:start) end end - context 'when the import has failed' do - it 'updates the error on Import/Export & hides credentials from import URL' do - import_url = 'https://user:pass@test.com/root/repoC.git/' - error = "#{import_url} not found" - - import_state.update!(jid: '123') - project.update!(import_type: 'gitlab_project') + context 'when worker was reset without cleanup (import_state is started)' do + let(:import_state) { create(:import_state, :started, jid: jid) } + it 'imports the project successfully' do expect_next_instance_of(Projects::ImportService) do |instance| - expect(instance).to receive(:track_start_import).and_raise(StandardError, error) + expect(instance).to receive(:execute).and_return({ status: :ok }) end - expect { subject.perform(project.id) }.not_to raise_error + subject.perform(project.id) - import_state.reload - expect(import_state.jid).to eq('123') - expect(import_state.status).to eq('failed') - expect(import_state.last_error).to include("[FILTERED] not found") - expect(import_state.last_error).not_to include(import_url) + expect(project).to have_received(:after_import) + expect(import_state).not_to have_received(:start) end end context 'when using an asynchronous importer' do it 'does not mark the import process as finished' do - service = double(:service) + expect_next_instance_of(Projects::ImportService) do |instance| + expect(instance).to receive(:execute).and_return({ status: :ok }) + expect(instance).to receive(:async?).and_return(true) + end + + subject.perform(project.id) - allow(Projects::ImportService) - .to receive(:new) - .and_return(service) + expect(project).not_to have_received(:after_import) + end + end - allow(service) - .to receive(:execute) - .and_return(true) + context 'when the import has failed' do + let(:error) { "https://user:pass@test.com/root/repoC.git/ not found" } - allow(service) - .to receive(:async?) - .and_return(true) + before do + allow(import_state).to receive(:mark_as_failed) + end - expect_next_instance_of(ProjectImportState) do |instance| - expect(instance).not_to receive(:finish) + it 'marks import_state as failed' do + expect_next_instance_of(Projects::ImportService) do |instance| + expect(instance).to receive(:execute).and_return({ status: :error, message: error }) end subject.perform(project.id) + + expect(import_state).to have_received(:mark_as_failed).with(error) + expect(project).not_to have_received(:after_import) end end end diff --git a/spec/workers/run_pipeline_schedule_worker_spec.rb b/spec/workers/run_pipeline_schedule_worker_spec.rb index 4fdf6149435..25158de3341 100644 --- a/spec/workers/run_pipeline_schedule_worker_spec.rb +++ b/spec/workers/run_pipeline_schedule_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe RunPipelineScheduleWorker do +RSpec.describe RunPipelineScheduleWorker, feature_category: :continuous_integration do it 'has an until_executed deduplicate strategy' do expect(described_class.get_deduplicate_strategy).to eq(:until_executed) end @@ -21,6 +21,11 @@ RSpec.describe RunPipelineScheduleWorker do end end + it 'accepts an option' do + expect { worker.perform(pipeline_schedule.id, user.id, {}) }.not_to raise_error + expect { worker.perform(pipeline_schedule.id, user.id, {}, {}) }.to raise_error(ArgumentError) + end + context 'when a schedule not found' do it 'does not call the Service' do expect(Ci::CreatePipelineService).not_to receive(:new) @@ -56,37 +61,91 @@ RSpec.describe RunPipelineScheduleWorker do let(:create_pipeline_service) { instance_double(Ci::CreatePipelineService, execute: service_response) } let(:service_response) { instance_double(ServiceResponse, payload: pipeline, error?: false) } - before do - expect(Ci::CreatePipelineService).to receive(:new).with(project, user, ref: pipeline_schedule.ref).and_return(create_pipeline_service) + context 'when pipeline can be created' do + before do + expect(Ci::CreatePipelineService).to receive(:new).with(project, user, ref: pipeline_schedule.ref).and_return(create_pipeline_service) - expect(create_pipeline_service).to receive(:execute).with(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: pipeline_schedule).and_return(service_response) - end + expect(create_pipeline_service).to receive(:execute).with(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: pipeline_schedule).and_return(service_response) + end + + context "when pipeline is persisted" do + let(:pipeline) { instance_double(Ci::Pipeline, persisted?: true) } - context "when pipeline is persisted" do - let(:pipeline) { instance_double(Ci::Pipeline, persisted?: true) } + it "returns the service response" do + expect(worker.perform(pipeline_schedule.id, user.id)).to eq(service_response) + end - it "returns the service response" do - expect(worker.perform(pipeline_schedule.id, user.id)).to eq(service_response) + it "does not log errors" do + expect(worker).not_to receive(:log_extra_metadata_on_done) + + expect(worker.perform(pipeline_schedule.id, user.id)).to eq(service_response) + end + + it "changes the next_run_at" do + expect { worker.perform(pipeline_schedule.id, user.id) }.to change { pipeline_schedule.reload.next_run_at }.by(1.day) + end + + context 'when feature flag ci_use_run_pipeline_schedule_worker is disabled' do + before do + stub_feature_flags(ci_use_run_pipeline_schedule_worker: false) + end + + it 'does not change the next_run_at' do + expect { worker.perform(pipeline_schedule.id, user.id) }.not_to change { pipeline_schedule.reload.next_run_at } + end + end end - it "does not log errors" do - expect(worker).not_to receive(:log_extra_metadata_on_done) + context "when pipeline was not persisted" do + let(:service_response) { instance_double(ServiceResponse, error?: true, message: "Error", payload: pipeline) } + let(:pipeline) { instance_double(Ci::Pipeline, persisted?: false) } + + it "logs a pipeline creation error" do + expect(worker) + .to receive(:log_extra_metadata_on_done) + .with(:pipeline_creation_error, service_response.message) + .and_call_original - expect(worker.perform(pipeline_schedule.id, user.id)).to eq(service_response) + expect(worker.perform(pipeline_schedule.id, user.id)).to eq(service_response.message) + end end end - context "when pipeline was not persisted" do - let(:service_response) { instance_double(ServiceResponse, error?: true, message: "Error", payload: pipeline) } - let(:pipeline) { instance_double(Ci::Pipeline, persisted?: false) } + context 'when schedule is already executed' do + let(:time_in_future) { 1.hour.since } + + before do + pipeline_schedule.update_column(:next_run_at, time_in_future) + end + + it 'does not change the next_run_at' do + expect { worker.perform(pipeline_schedule.id, user.id) }.to not_change { pipeline_schedule.reload.next_run_at } + end + + it 'does not create a pipeline' do + expect(Ci::CreatePipelineService).not_to receive(:new) + + worker.perform(pipeline_schedule.id, user.id) + end + + context 'when feature flag ci_use_run_pipeline_schedule_worker is disabled' do + let(:pipeline) { instance_double(Ci::Pipeline, persisted?: true) } + + before do + stub_feature_flags(ci_use_run_pipeline_schedule_worker: false) + + expect(Ci::CreatePipelineService).to receive(:new).with(project, user, ref: pipeline_schedule.ref).and_return(create_pipeline_service) + + expect(create_pipeline_service).to receive(:execute).with(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: pipeline_schedule).and_return(service_response) + end - it "logs a pipeline creation error" do - expect(worker) - .to receive(:log_extra_metadata_on_done) - .with(:pipeline_creation_error, service_response.message) - .and_call_original + it 'does not change the next_run_at' do + expect { worker.perform(pipeline_schedule.id, user.id) }.to not_change { pipeline_schedule.reload.next_run_at } + end - expect(worker.perform(pipeline_schedule.id, user.id)).to eq(service_response.message) + it "returns the service response" do + expect(worker.perform(pipeline_schedule.id, user.id)).to eq(service_response) + end end end end diff --git a/spec/workers/wait_for_cluster_creation_worker_spec.rb b/spec/workers/wait_for_cluster_creation_worker_spec.rb deleted file mode 100644 index 9079dff1afe..00000000000 --- a/spec/workers/wait_for_cluster_creation_worker_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe WaitForClusterCreationWorker do - describe '#perform' do - context 'when provider type is gcp' do - let(:cluster) { create(:cluster, provider_type: :gcp, provider_gcp: provider) } - let(:provider) { create(:cluster_provider_gcp, :creating) } - - it 'provisions a cluster' do - expect_any_instance_of(Clusters::Gcp::VerifyProvisionStatusService).to receive(:execute).with(provider) - - described_class.new.perform(cluster.id) - end - end - - context 'when provider type is aws' do - let(:cluster) { create(:cluster, provider_type: :aws, provider_aws: provider) } - let(:provider) { create(:cluster_provider_aws, :creating) } - - it 'provisions a cluster' do - expect_any_instance_of(Clusters::Aws::VerifyProvisionStatusService).to receive(:execute).with(provider) - - described_class.new.perform(cluster.id) - end - end - - context 'when provider type is user' do - let(:cluster) { create(:cluster, provider_type: :user) } - - it 'does not provision a cluster' do - expect_any_instance_of(Clusters::Gcp::VerifyProvisionStatusService).not_to receive(:execute) - - described_class.new.perform(cluster.id) - end - end - - context 'when cluster does not exist' do - it 'does not provision a cluster' do - expect_any_instance_of(Clusters::Gcp::VerifyProvisionStatusService).not_to receive(:execute) - - described_class.new.perform(123) - end - end - end -end diff --git a/spec/workers/wikis/git_garbage_collect_worker_spec.rb b/spec/workers/wikis/git_garbage_collect_worker_spec.rb index 77c2e49a83a..2c6899848cf 100644 --- a/spec/workers/wikis/git_garbage_collect_worker_spec.rb +++ b/spec/workers/wikis/git_garbage_collect_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Wikis::GitGarbageCollectWorker do +RSpec.describe Wikis::GitGarbageCollectWorker, feature_category: :source_code_management do it_behaves_like 'can collect git garbage' do let_it_be(:resource) { create(:project_wiki) } let_it_be(:page) { create(:wiki_page, wiki: resource) } |