diff options
Diffstat (limited to 'spec/models/ci/build_spec.rb')
-rw-r--r-- | spec/models/ci/build_spec.rb | 162 |
1 files changed, 107 insertions, 55 deletions
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 5b07bd8923f..339dffa507f 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -585,6 +585,68 @@ RSpec.describe Ci::Build do is_expected.to be_falsey end end + + context 'with runners_cached_states feature flag enabled' do + before do + stub_feature_flags(runners_cached_states: true) + end + + it 'caches the result in Redis' do + expect(Rails.cache).to receive(:fetch).with(['has-online-runners', build.id], expires_in: 1.minute) + + build.any_runners_online? + end + end + + context 'with runners_cached_states feature flag disabled' do + before do + stub_feature_flags(runners_cached_states: false) + end + + it 'does not cache' do + expect(Rails.cache).not_to receive(:fetch).with(['has-online-runners', build.id], expires_in: 1.minute) + + build.any_runners_online? + end + end + end + + describe '#any_runners_available?' do + subject { build.any_runners_available? } + + context 'when no runners' do + it { is_expected.to be_falsey } + end + + context 'when there are runners' do + let!(:runner) { create(:ci_runner, :project, projects: [build.project]) } + + it { is_expected.to be_truthy } + end + + context 'with runners_cached_states feature flag enabled' do + before do + stub_feature_flags(runners_cached_states: true) + end + + it 'caches the result in Redis' do + expect(Rails.cache).to receive(:fetch).with(['has-available-runners', build.project.id], expires_in: 1.minute) + + build.any_runners_available? + end + end + + context 'with runners_cached_states feature flag disabled' do + before do + stub_feature_flags(runners_cached_states: false) + end + + it 'does not cache' do + expect(Rails.cache).not_to receive(:fetch).with(['has-available-runners', build.project.id], expires_in: 1.minute) + + build.any_runners_available? + end + end end describe '#artifacts?' do @@ -821,45 +883,6 @@ RSpec.describe Ci::Build do { cache: [{ key: "key", paths: ["public"], policy: "pull-push" }] } end - context 'with multiple_cache_per_job FF disabled' do - before do - stub_feature_flags(multiple_cache_per_job: false) - end - let(:options) { { cache: { key: "key", paths: ["public"], policy: "pull-push" } } } - - subject { build.cache } - - context 'when build has cache' do - before do - allow(build).to receive(:options).and_return(options) - end - - context 'when project has jobs_cache_index' do - before do - allow_any_instance_of(Project).to receive(:jobs_cache_index).and_return(1) - end - - it { is_expected.to be_an(Array).and all(include(key: "key-1")) } - end - - context 'when project does not have jobs_cache_index' do - before do - allow_any_instance_of(Project).to receive(:jobs_cache_index).and_return(nil) - end - - it { is_expected.to eq([options[:cache]]) } - end - end - - context 'when build does not have cache' do - before do - allow(build).to receive(:options).and_return({}) - end - - it { is_expected.to eq([]) } - end - end - subject { build.cache } context 'when build has cache' do @@ -1174,6 +1197,8 @@ RSpec.describe Ci::Build do end describe 'state transition as a deployable' do + subject { build.send(event) } + let!(:build) { create(:ci_build, :with_deployment, :start_review_app, project: project, pipeline: pipeline) } let(:deployment) { build.deployment } let(:environment) { deployment.environment } @@ -1188,54 +1213,78 @@ RSpec.describe Ci::Build do expect(environment.name).to eq('review/master') end - context 'when transits to running' do - before do - build.run! + shared_examples_for 'avoid deadlock' do + it 'executes UPDATE in the right order' do + recorded = ActiveRecord::QueryRecorder.new { subject } + + index_for_build = recorded.log.index { |l| l.include?("UPDATE \"ci_builds\"") } + index_for_deployment = recorded.log.index { |l| l.include?("UPDATE \"deployments\"") } + + expect(index_for_build).to be < index_for_deployment end + end + + context 'when transits to running' do + let(:event) { :run! } + + it_behaves_like 'avoid deadlock' it 'transits deployment status to running' do + subject + expect(deployment).to be_running end end context 'when transits to success' do + let(:event) { :success! } + before do allow(Deployments::UpdateEnvironmentWorker).to receive(:perform_async) allow(Deployments::ExecuteHooksWorker).to receive(:perform_async) - build.success! end + it_behaves_like 'avoid deadlock' + it 'transits deployment status to success' do + subject + expect(deployment).to be_success end end context 'when transits to failed' do - before do - build.drop! - end + let(:event) { :drop! } + + it_behaves_like 'avoid deadlock' it 'transits deployment status to failed' do + subject + expect(deployment).to be_failed end end context 'when transits to skipped' do - before do - build.skip! - end + let(:event) { :skip! } + + it_behaves_like 'avoid deadlock' it 'transits deployment status to skipped' do + subject + expect(deployment).to be_skipped end end context 'when transits to canceled' do - before do - build.cancel! - end + let(:event) { :cancel! } + + it_behaves_like 'avoid deadlock' it 'transits deployment status to canceled' do + subject + expect(deployment).to be_canceled end end @@ -2500,6 +2549,7 @@ RSpec.describe Ci::Build do { key: 'CI_COMMIT_DESCRIPTION', value: pipeline.git_commit_description, public: true, masked: false }, { key: 'CI_COMMIT_REF_PROTECTED', value: (!!pipeline.protected_ref?).to_s, public: true, masked: false }, { key: 'CI_COMMIT_TIMESTAMP', value: pipeline.git_commit_timestamp, public: true, masked: false }, + { key: 'CI_COMMIT_AUTHOR', value: pipeline.git_author_full_text, public: true, masked: false }, { key: 'CI_BUILD_REF', value: build.sha, public: true, masked: false }, { key: 'CI_BUILD_BEFORE_SHA', value: build.before_sha, public: true, masked: false }, { key: 'CI_BUILD_REF_NAME', value: build.ref, public: true, masked: false }, @@ -3620,10 +3670,10 @@ RSpec.describe Ci::Build do end describe 'state transition when build fails' do - let(:service) { MergeRequests::AddTodoWhenBuildFailsService.new(project, user) } + let(:service) { ::MergeRequests::AddTodoWhenBuildFailsService.new(project, user) } before do - allow(MergeRequests::AddTodoWhenBuildFailsService).to receive(:new).and_return(service) + allow(::MergeRequests::AddTodoWhenBuildFailsService).to receive(:new).and_return(service) allow(service).to receive(:close) end @@ -3708,7 +3758,7 @@ RSpec.describe Ci::Build do subject.drop! end - it 'creates a todo' do + it 'creates a todo async', :sidekiq_inline do project.add_developer(user) expect_next_instance_of(TodoService) do |todo_service| @@ -3741,6 +3791,7 @@ RSpec.describe Ci::Build do describe '.matches_tag_ids' do let_it_be(:build, reload: true) { create(:ci_build, project: project, user: user) } + let(:tag_ids) { ::ActsAsTaggableOn::Tag.named_any(tag_list).ids } subject { described_class.where(id: build).matches_tag_ids(tag_ids) } @@ -4192,6 +4243,7 @@ RSpec.describe Ci::Build do describe '#artifacts_metadata_entry' do let_it_be(:build) { create(:ci_build, project: project) } + let(:path) { 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif' } around do |example| |