Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/environment_spec.rb')
-rw-r--r--spec/models/environment_spec.rb299
1 files changed, 173 insertions, 126 deletions
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 066763645ab..9d4699cb91e 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -16,13 +16,13 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching, feature_categ
it { is_expected.to be_kind_of(ReactiveCaching) }
it { is_expected.to nullify_if_blank(:external_url) }
it { is_expected.to nullify_if_blank(:kubernetes_namespace) }
+ it { is_expected.to nullify_if_blank(:flux_resource_path) }
it { is_expected.to belong_to(:project).required }
it { is_expected.to belong_to(:merge_request).optional }
it { is_expected.to belong_to(:cluster_agent).optional }
it { is_expected.to have_many(:deployments) }
- it { is_expected.to have_many(:metrics_dashboard_annotations) }
it { is_expected.to have_many(:alert_management_alerts) }
it { is_expected.to have_one(:upcoming_deployment) }
it { is_expected.to have_one(:latest_opened_most_severe_alert) }
@@ -38,6 +38,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching, feature_categ
it { is_expected.to validate_length_of(:external_url).is_at_most(255) }
it { is_expected.to validate_length_of(:kubernetes_namespace).is_at_most(63) }
+ it { is_expected.to validate_length_of(:flux_resource_path).is_at_most(255) }
describe 'validation' do
it 'does not become invalid record when external_url is empty' do
@@ -690,178 +691,214 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching, feature_categ
subject { environment.stop_with_actions!(user) }
- before do
- expect(environment).to receive(:available?).and_call_original
- end
-
- context 'when no other actions' do
- context 'environment is available' do
- before do
- environment.update!(state: :available)
- end
-
- it do
- actions = subject
-
- expect(environment).to be_stopped
- expect(actions).to match_array([])
- end
+ shared_examples_for 'stop with playing a teardown job' do
+ before do
+ expect(environment).to receive(:available?).and_call_original
end
- context 'environment is already stopped' do
- before do
- environment.update!(state: :stopped)
- end
+ context 'when no other actions' do
+ context 'environment is available' do
+ before do
+ environment.update!(state: :available)
+ end
- it do
- subject
+ it do
+ actions = subject
- expect(environment).to be_stopped
+ expect(environment).to be_stopped
+ expect(actions).to match_array([])
+ end
end
- end
- end
-
- context 'when matching action is defined' do
- let(:pipeline) { create(:ci_pipeline, project: project) }
- let(:build_a) { create(:ci_build, :success, pipeline: pipeline) }
- before do
- create(:deployment, :success,
- environment: environment,
- deployable: build_a,
- on_stop: 'close_app_a')
- end
+ context 'environment is already stopped' do
+ before do
+ environment.update!(state: :stopped)
+ end
- context 'when user is not allowed to stop environment' do
- let!(:close_action) do
- create(:ci_build, :manual, pipeline: pipeline, name: 'close_app_a')
- end
+ it do
+ subject
- it 'raises an exception' do
- expect { subject }.to raise_error(Gitlab::Access::AccessDeniedError)
+ expect(environment).to be_stopped
+ end
end
end
- context 'when user is allowed to stop environment' do
- before do
- project.add_developer(user)
+ context 'when matching action is defined' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:job_a) { create(factory_type, :success, pipeline: pipeline, **factory_options) }
- create(:protected_branch, :developers_can_merge, name: 'master', project: project)
+ before do
+ create(:deployment, :success,
+ environment: environment,
+ deployable: job_a,
+ on_stop: 'close_app_a')
end
- context 'when action did not yet finish' do
+ context 'when user is not allowed to stop environment' do
let!(:close_action) do
- create(:ci_build, :manual, pipeline: pipeline, name: 'close_app_a')
+ create(factory_type, :manual, pipeline: pipeline, name: 'close_app_a', **factory_options)
end
- it 'returns the same action' do
- action = subject.first
- expect(action).to eq(close_action)
- expect(action.user).to eq(user)
+ it 'raises an exception' do
+ expect { subject }.to raise_error(Gitlab::Access::AccessDeniedError)
end
+ end
- it 'environment is not stopped' do
- subject
+ context 'when user is allowed to stop environment' do
+ before do
+ project.add_developer(user)
- expect(environment).not_to be_stopped
+ create(:protected_branch, :developers_can_merge, name: 'master', project: project)
end
- end
- context 'if action did finish' do
- let!(:close_action) do
- create(:ci_build, :manual, :success, pipeline: pipeline, name: 'close_app_a')
- end
+ context 'when action did not yet finish' do
+ let!(:close_action) do
+ create(factory_type, :manual, pipeline: pipeline, name: 'close_app_a', **factory_options)
+ end
- it 'returns a new action of the same type' do
- action = subject.first
+ it 'returns the same action' do
+ action = subject.first
+ expect(action).to eq(close_action)
+ expect(action.user).to eq(user)
+ end
- expect(action).to be_persisted
- expect(action.name).to eq(close_action.name)
- expect(action.user).to eq(user)
- end
- end
+ it 'environment is not stopped' do
+ subject
- context 'close action does not raise ActiveRecord::StaleObjectError' do
- let!(:close_action) do
- create(:ci_build, :manual, pipeline: pipeline, name: 'close_app_a')
+ expect(environment).not_to be_stopped
+ end
end
- before do
- # preload the build
- environment.stop_actions
+ context 'if action did finish' do
+ let!(:close_action) do
+ create(factory_type, :manual, :success, pipeline: pipeline, name: 'close_app_a', **factory_options)
+ end
- # Update record as the other process. This makes `environment.stop_action` stale.
- close_action.drop!
- end
+ it 'returns a new action of the same type when build job' do
+ skip unless factory_type == :ci_build
- it 'successfully plays the build even if the build was a stale object' do
- # Since build is droped.
- expect(close_action.processed).to be_falsey
+ action = subject.first
+
+ expect(action).to be_persisted
+ expect(action.name).to eq(close_action.name)
+ expect(action.user).to eq(user)
+ end
- # it encounters the StaleObjectError at first, but reloads the object and runs `build.play`
- expect { subject }.not_to raise_error
+ it 'does nothing when bridge job' do
+ skip unless factory_type == :ci_bridge
- # Now the build should be processed.
- expect(close_action.reload.processed).to be_truthy
+ action = subject.first
+
+ expect(action).to be_nil
+ end
end
- end
- end
- end
- context 'when there are more then one stop action for the environment' do
- let(:pipeline) { create(:ci_pipeline, project: project) }
- let(:build_a) { create(:ci_build, :success, pipeline: pipeline) }
- let(:build_b) { create(:ci_build, :success, pipeline: pipeline) }
+ context 'close action does not raise ActiveRecord::StaleObjectError' do
+ let!(:close_action) do
+ create(factory_type, :manual, pipeline: pipeline, name: 'close_app_a', **factory_options)
+ end
- let!(:close_actions) do
- [
- create(:ci_build, :manual, pipeline: pipeline, name: 'close_app_a'),
- create(:ci_build, :manual, pipeline: pipeline, name: 'close_app_b')
- ]
- end
+ before do
+ # preload the job
+ environment.stop_actions
- before do
- project.add_developer(user)
+ # Update record as the other process. This makes `environment.stop_action` stale.
+ close_action.drop!
+ end
- create(:deployment, :success,
- environment: environment,
- deployable: build_a,
- finished_at: 5.minutes.ago,
- on_stop: 'close_app_a')
+ it 'successfully plays the job even if the job was a stale object when build job' do
+ skip unless factory_type == :ci_build
- create(:deployment, :success,
- environment: environment,
- deployable: build_b,
- finished_at: 1.second.ago,
- on_stop: 'close_app_b')
- end
+ # Since job is droped.
+ expect(close_action.processed).to be_falsey
+
+ # it encounters the StaleObjectError at first, but reloads the object and runs `job.play`
+ expect { subject }.not_to raise_error
+
+ # Now the job should be processed.
+ expect(close_action.reload.processed).to be_truthy
+ end
+
+ it 'does nothing when bridge job' do
+ skip unless factory_type == :ci_bridge
+
+ expect(close_action.processed).to be_falsey
- it 'returns the same actions' do
- actions = subject
+ # it encounters the StaleObjectError at first, but reloads the object and runs `job.play`
+ expect { subject }.not_to raise_error
- expect(actions.count).to eq(close_actions.count)
- expect(actions.pluck(:id)).to match_array(close_actions.pluck(:id))
- expect(actions.pluck(:user)).to match_array(close_actions.pluck(:user))
+ # Bridge is not retried currently.
+ expect(close_action.processed).to be_falsey
+ end
+ end
+ end
end
- context 'when there are failed builds' do
+ context 'when there are more then one stop action for the environment' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:job_a) { create(factory_type, :success, pipeline: pipeline, **factory_options) }
+ let(:job_b) { create(factory_type, :success, pipeline: pipeline, **factory_options) }
+
+ let!(:close_actions) do
+ [
+ create(factory_type, :manual, pipeline: pipeline, name: 'close_app_a', **factory_options),
+ create(factory_type, :manual, pipeline: pipeline, name: 'close_app_b', **factory_options)
+ ]
+ end
+
before do
- create(:ci_build, :failed, pipeline: pipeline, name: 'close_app_c')
+ project.add_developer(user)
+
+ create(:deployment, :success,
+ environment: environment,
+ deployable: job_a,
+ finished_at: 5.minutes.ago,
+ on_stop: 'close_app_a')
- create(:deployment, :failed,
+ create(:deployment, :success,
environment: environment,
- deployable: create(:ci_build, pipeline: pipeline),
- on_stop: 'close_app_c')
+ deployable: job_b,
+ finished_at: 1.second.ago,
+ on_stop: 'close_app_b')
end
- it 'returns only stop actions from successful builds' do
+ it 'returns the same actions' do
actions = subject
- expect(actions).to match_array(close_actions)
- expect(actions.count).to eq(pipeline.latest_successful_builds.count)
+ expect(actions.count).to eq(close_actions.count)
+ expect(actions.pluck(:id)).to match_array(close_actions.pluck(:id))
+ expect(actions.pluck(:user)).to match_array(close_actions.pluck(:user))
+ end
+
+ context 'when there are failed builds' do
+ before do
+ create(factory_type, :failed, pipeline: pipeline, name: 'close_app_c', **factory_options)
+
+ create(:deployment, :failed,
+ environment: environment,
+ deployable: create(factory_type, pipeline: pipeline, **factory_options),
+ on_stop: 'close_app_c')
+ end
+
+ it 'returns only stop actions from successful builds' do
+ actions = subject
+
+ expect(actions).to match_array(close_actions)
+ expect(actions.count).to eq(pipeline.latest_successful_jobs.count)
+ end
end
end
end
+
+ it_behaves_like 'stop with playing a teardown job' do
+ let(:factory_type) { :ci_build }
+ let(:factory_options) { {} }
+ end
+
+ it_behaves_like 'stop with playing a teardown job' do
+ let(:factory_type) { :ci_bridge }
+ let(:factory_options) { { downstream: project } }
+ end
end
describe '#stop_actions' do
@@ -1814,13 +1851,23 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching, feature_categ
let_it_be(:project) { create(:project, :repository) }
let_it_be(:environment, reload: true) { create(:environment, project: project) }
- let!(:deployment) { create(:deployment, project: project, environment: environment, deployable: build) }
- let!(:build) { create(:ci_build, :running, project: project, environment: environment) }
+ let!(:deployment) { create(:deployment, project: project, environment: environment, deployable: job) }
+ let!(:job) { create(:ci_build, :running, project: project, environment: environment) }
it 'cancels an active deployment job' do
subject
- expect(build.reset).to be_canceled
+ expect(job.reset).to be_canceled
+ end
+
+ context 'when deployment job is bridge' do
+ let!(:job) { create(:ci_bridge, :running, project: project, environment: environment) }
+
+ it 'does not cancel an active deployment job' do
+ subject
+
+ expect(job.reset).to be_running
+ end
end
context 'when deployable does not exist' do
@@ -1831,7 +1878,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching, feature_categ
it 'does not raise an error' do
expect { subject }.not_to raise_error
- expect(build.reset).to be_running
+ expect(job.reset).to be_running
end
end
end