diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 5bd2b4371da035d3eebd936ec95486e3996c9ef8..fdcb877dcab93cad2ca6a0ff0ad93a9fbca57f2a 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -268,6 +268,10 @@ def with_preloads !build.any_unmet_prerequisites? # If false is returned, it stops the transition end + before_transition on: :enqueue do |build| + !build.waiting_for_deployment_approval? # If false is returned, it stops the transition + end + after_transition created: :scheduled do |build| build.run_after_commit do Ci::BuildScheduleWorker.perform_at(build.scheduled_at, build.id) @@ -424,7 +428,7 @@ def archived? end def playable? - action? && !archived? && (manual? || scheduled? || retryable?) + action? && !archived? && (manual? || scheduled? || retryable?) && !waiting_for_deployment_approval? end def waiting_for_deployment_approval? diff --git a/app/models/deployment.rb b/app/models/deployment.rb index 453c6bce362e9a011b3322ffeb83832bb6f52cf4..2f04d99f9f63b12ab579a5aa0990ccf62f30c5dd 100644 --- a/app/models/deployment.rb +++ b/app/models/deployment.rb @@ -70,6 +70,10 @@ class Deployment < ApplicationRecord transition created: :blocked end + event :unblock do + transition blocked: :created + end + event :succeed do transition any - [:success] => :success end diff --git a/ee/app/services/deployments/approval_service.rb b/ee/app/services/deployments/approval_service.rb index 8c19b2d42afda43d21369097f26bcb9d857515f8..f6c88921930b83b402886605136d3b31fafcee6d 100644 --- a/ee/app/services/deployments/approval_service.rb +++ b/ee/app/services/deployments/approval_service.rb @@ -32,6 +32,7 @@ def process_build!(deployment, approval) if approval.rejected? deployment.deployable.drop!(:deployment_rejected) elsif deployment.pending_approval_count <= 0 + deployment.unblock! deployment.deployable.enqueue! end end diff --git a/ee/spec/services/deployments/approval_service_spec.rb b/ee/spec/services/deployments/approval_service_spec.rb index bc07b9f49fdc9fc3cccc41a2e8e73629c8d113bf..5acf1c05d4bd51222a77ec8ad4b5068d748c7644 100644 --- a/ee/spec/services/deployments/approval_service_spec.rb +++ b/ee/spec/services/deployments/approval_service_spec.rb @@ -103,9 +103,11 @@ let(:required_approval_count) { 1 } it 'enqueues the build' do - subject + expect { subject }.to change { deployment.deployable.status }.from('manual').to('pending') + end - expect(deployment.deployable.status).to eq('pending') + it 'unblocks the deployment' do + expect { subject }.to change { deployment.status }.from('blocked').to('created') end end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index c4f4e2cb2dc38c8ef741917bd07e1759d2bf76e0..a5af0cd32fd4aea06fbf17e94a956e6747f636c7 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -2468,6 +2468,16 @@ it { is_expected.not_to be_playable } end + + context 'when build is waiting for deployment approval' do + subject { build_stubbed(:ci_build, :manual, environment: 'production') } + + before do + create(:deployment, :blocked, deployable: subject) + end + + it { is_expected.not_to be_playable } + end end describe 'project settings' do @@ -3792,6 +3802,18 @@ end end + describe 'when the build is waiting for deployment approval' do + let(:build) { create(:ci_build, :manual, environment: 'production') } + + before do + create(:deployment, :blocked, deployable: build) + end + + it 'does not allow the build to be enqueued' do + expect { build.enqueue! }.to raise_error(StateMachines::InvalidTransition) + end + end + describe 'state transition: any => [:pending]' do let(:build) { create(:ci_build, :created) }