diff options
author | Tiger <twatson@gitlab.com> | 2019-03-04 10:56:20 +1100 |
---|---|---|
committer | Tiger <twatson@gitlab.com> | 2019-03-20 12:04:40 +1100 |
commit | 00f0d356b71fa87f8190810b01add0cc4586e90a (patch) | |
tree | e6b59c822bba6db3ea1e80079e644d010b84f806 /spec | |
parent | 42ca9c6f0de34dfa7ae09cc0e9672ea5857afd38 (diff) | |
download | gitlab-ce-00f0d356b71fa87f8190810b01add0cc4586e90a.tar.gz |
Create framework for build prerequisites
Introduces the concept of Prerequisites for a CI build.
If a build has unmet prerequisites it will go through the
:preparing state before being made available to a runner.
There are no actual prerequisites yet, so current
behaviour is unchanged.
Diffstat (limited to 'spec')
-rw-r--r-- | spec/features/projects/badges/pipeline_badge_spec.rb | 3 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/build/prerequisite/factory_spec.rb | 34 | ||||
-rw-r--r-- | spec/models/ci/build_spec.rb | 57 | ||||
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 6 | ||||
-rw-r--r-- | spec/models/commit_status_spec.rb | 6 | ||||
-rw-r--r-- | spec/requests/api/runner_spec.rb | 9 | ||||
-rw-r--r-- | spec/services/ci/prepare_build_service_spec.rb | 54 | ||||
-rw-r--r-- | spec/workers/ci/build_prepare_worker_spec.rb | 30 |
8 files changed, 197 insertions, 2 deletions
diff --git a/spec/features/projects/badges/pipeline_badge_spec.rb b/spec/features/projects/badges/pipeline_badge_spec.rb index 96efa06d843..4ac4e8f0fcb 100644 --- a/spec/features/projects/badges/pipeline_badge_spec.rb +++ b/spec/features/projects/badges/pipeline_badge_spec.rb @@ -47,10 +47,11 @@ describe 'Pipeline Badge' do before do # Prevent skipping directly to 'pending' allow(Ci::BuildPrepareWorker).to receive(:perform_async) + allow(job).to receive(:prerequisites).and_return([double]) end it 'displays the preparing badge' do - job.prepare + job.enqueue visit pipeline_project_badges_path(project, ref: ref, format: :svg) diff --git a/spec/lib/gitlab/ci/build/prerequisite/factory_spec.rb b/spec/lib/gitlab/ci/build/prerequisite/factory_spec.rb new file mode 100644 index 00000000000..5187f99a441 --- /dev/null +++ b/spec/lib/gitlab/ci/build/prerequisite/factory_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Ci::Build::Prerequisite::Factory do + let(:build) { create(:ci_build) } + + describe '.for_build' do + let(:kubernetes_namespace) do + instance_double( + Gitlab::Ci::Build::Prerequisite::KubernetesNamespace, + unmet?: unmet) + end + + subject { described_class.new(build).unmet } + + before do + expect(Gitlab::Ci::Build::Prerequisite::KubernetesNamespace) + .to receive(:new).with(build).and_return(kubernetes_namespace) + end + + context 'prerequisite is unmet' do + let(:unmet) { true } + + it { is_expected.to eq [kubernetes_namespace] } + end + + context 'prerequisite is met' do + let(:unmet) { false } + + it { is_expected.to be_empty } + end + end +end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 9ca4241d7d8..b31c4fcceb3 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -186,6 +186,37 @@ describe Ci::Build do end end + describe '#enqueue' do + let(:build) { create(:ci_build, :created) } + + subject { build.enqueue } + + before do + allow(build).to receive(:any_unmet_prerequisites?).and_return(has_prerequisites) + allow(Ci::PrepareBuildService).to receive(:perform_async) + end + + context 'build has unmet prerequisites' do + let(:has_prerequisites) { true } + + it 'transitions to preparing' do + subject + + expect(build).to be_preparing + end + end + + context 'build has no prerequisites' do + let(:has_prerequisites) { false } + + it 'transitions to pending' do + subject + + expect(build).to be_pending + end + end + end + describe '#actionize' do context 'when build is a created' do before do @@ -344,6 +375,18 @@ describe Ci::Build do expect(build).to be_pending end + + context 'build has unmet prerequisites' do + before do + allow(build).to receive(:prerequisites).and_return([double]) + end + + it 'transits to preparing' do + subject + + expect(build).to be_preparing + end + end end end @@ -2928,6 +2971,20 @@ describe Ci::Build do end end + describe 'state transition: any => [:preparing]' do + let(:build) { create(:ci_build, :created) } + + before do + allow(build).to receive(:prerequisites).and_return([double]) + end + + it 'queues BuildPrepareWorker' do + expect(Ci::BuildPrepareWorker).to receive(:perform_async).with(build.id) + + build.enqueue + end + end + describe 'state transition: any => [:pending]' do let(:build) { create(:ci_build, :created) } diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index d35caac33dc..2ac056f63b2 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -1804,7 +1804,11 @@ describe Ci::Pipeline, :mailer do context 'on prepare' do before do - build.prepare + # Prevent skipping directly to 'pending' + allow(build).to receive(:prerequisites).and_return([double]) + allow(Ci::BuildPrepareWorker).to receive(:perform_async) + + build.enqueue end it { is_expected.to eq('preparing') } diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb index 1d241bf6000..e2b7f5c6ee2 100644 --- a/spec/models/commit_status_spec.rb +++ b/spec/models/commit_status_spec.rb @@ -489,6 +489,12 @@ describe CommitStatus do it { is_expected.to be_script_failure } end + + context 'when failure_reason is unmet_prerequisites' do + let(:reason) { :unmet_prerequisites } + + it { is_expected.to be_unmet_prerequisites } + end end describe 'ensure stage assignment' do diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb index 9087cccb759..3ccedd8dd06 100644 --- a/spec/requests/api/runner_spec.rb +++ b/spec/requests/api/runner_spec.rb @@ -918,6 +918,15 @@ describe API::Runner, :clean_gitlab_redis_shared_state do it { expect(job).to be_job_execution_timeout } end + + context 'when failure_reason is unmet_prerequisites' do + before do + update_job(state: 'failed', failure_reason: 'unmet_prerequisites') + job.reload + end + + it { expect(job).to be_unmet_prerequisites } + end end context 'when trace is given' do diff --git a/spec/services/ci/prepare_build_service_spec.rb b/spec/services/ci/prepare_build_service_spec.rb new file mode 100644 index 00000000000..1797f8f964f --- /dev/null +++ b/spec/services/ci/prepare_build_service_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Ci::PrepareBuildService do + describe '#execute' do + let(:build) { create(:ci_build, :preparing) } + + subject { described_class.new(build).execute } + + before do + allow(build).to receive(:prerequisites).and_return(prerequisites) + end + + shared_examples 'build enqueueing' do + it 'enqueues the build' do + expect(build).to receive(:enqueue).once + + subject + end + end + + context 'build has unmet prerequisites' do + let(:prerequisite) { double(complete!: true) } + let(:prerequisites) { [prerequisite] } + + it 'completes each prerequisite' do + expect(prerequisites).to all(receive(:complete!)) + + subject + end + + include_examples 'build enqueueing' + + context 'prerequisites fail to complete' do + before do + allow(build).to receive(:enqueue).and_return(false) + end + + it 'drops the build' do + expect(build).to receive(:drop!).with(:unmet_prerequisites).once + + subject + end + end + end + + context 'build has no prerequisites' do + let(:prerequisites) { [] } + + include_examples 'build enqueueing' + end + end +end diff --git a/spec/workers/ci/build_prepare_worker_spec.rb b/spec/workers/ci/build_prepare_worker_spec.rb new file mode 100644 index 00000000000..9f76696ee66 --- /dev/null +++ b/spec/workers/ci/build_prepare_worker_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Ci::BuildPrepareWorker do + subject { described_class.new.perform(build_id) } + + context 'build exists' do + let(:build) { create(:ci_build) } + let(:build_id) { build.id } + let(:service) { double(execute: true) } + + it 'calls the prepare build service' do + expect(Ci::PrepareBuildService).to receive(:new).with(build).and_return(service) + expect(service).to receive(:execute).once + + subject + end + end + + context 'build does not exist' do + let(:build_id) { -1 } + + it 'does not attempt to prepare the build' do + expect(Ci::PrepareBuildService).not_to receive(:new) + + subject + end + end +end |