spec/support/shared_examples/environment_state_shared_examples.rb (146 lines of code) (raw):

# frozen_string_literal: true require 'spec_helper' RSpec.shared_examples 'staging and production' do subject(:perform_event) { service.perform_event(event) } let!(:service) { described_class.new } let(:deployments) { [build(:deployment, :success, sha: 'abcd1234')] } let(:gprd_version) do build(:product_version, auto_deploy_ref: '16.10.202402100400-abdf1234567.abcdef12345') end before do allow(ReleaseTools::GitlabOpsClient) .to receive(:deployments) .and_return(deployments) allow(ReleaseTools::ProductVersion) .to receive(:each) .and_yield(ReleaseTools::ProductVersion.new('16.10.202402101000')) .and_yield(ReleaseTools::ProductVersion.new('16.10.202402100800')) .and_yield(ReleaseTools::ProductVersion.new('16.10.202402100400')) allow(ReleaseTools::GitlabOpsClient) .to receive(:pipelines) .with(ReleaseTools::Project::ReleaseTools, name: 'Coordinator pipeline', ref: '16.10.202402101000') .and_return([build(:pipeline, id: 10, ref: '16.10.202402101000')]) allow(ReleaseTools::GitlabOpsClient) .to receive(:pipelines) .with(ReleaseTools::Project::ReleaseTools, name: 'Coordinator pipeline', ref: '16.10.202402100800') .and_return([build(:pipeline, id: 8, ref: '16.10.202402100800')]) allow(ReleaseTools::GitlabOpsClient) .to receive(:pipelines) .with(ReleaseTools::Project::ReleaseTools, name: 'Coordinator pipeline', ref: '16.10.202402100400') .and_return([build(:pipeline, id: 6, ref: '16.10.202402100400')]) allow(ReleaseTools::ProductVersion) .to receive(:from_metadata_sha) .with('abcd1234') .and_return(gprd_version) allow(ReleaseTools::GitlabOpsClient) .to receive(:pipeline_jobs) .with(ReleaseTools::Project::ReleaseTools, 10, scope: described_class::PROMOTE_JOB_VALID_STATES) .and_return(Gitlab::PaginatedResponse.new([])) allow(ReleaseTools::GitlabOpsClient) .to receive(:pipeline_jobs) .with(ReleaseTools::Project::ReleaseTools, 8, scope: described_class::PROMOTE_JOB_VALID_STATES) .and_return(Gitlab::PaginatedResponse.new([build(:job, name: 'promote')])) allow(ReleaseTools::GitlabOpsClient) .to receive(:pipeline_jobs) .with(ReleaseTools::Project::ReleaseTools, 6, scope: described_class::PROMOTE_JOB_VALID_STATES) .and_return(Gitlab::PaginatedResponse.new([build(:job, name: 'promote')])) end where(:locked_state_metric_value, :ready_state_metric_value, :baking_time_metric_value, :awaiting_promotion, :event, :validity, :new_state) do [ ['0', '0', '0', '0', 'success', true, 'awaiting_promotion'], ['0', '0', '0', '0', 'start', true, 'locked'], ['1', '0', '0', '0', 'success', true, 'awaiting_promotion'], ['1', '0', '0', '0', 'start', true, 'locked'], ['0', '1', '0', '0', 'start', true, 'locked'], ['0', '1', '0', '0', 'success', false, 'ready'], ['0', '1', '0', '0', 'baking_complete', true, 'awaiting_promotion'], ['1', '0', '0', '0', 'baking_complete', false, 'locked'] ] end with_them do it "returns validity" do expect(perform_event).to eq(validity) expect(service.current_state).to eq(new_state) end end context 'when there are no new packages available for promotion' do before do allow(ReleaseTools::GitlabOpsClient) .to receive(:pipeline_jobs) .with(ReleaseTools::Project::ReleaseTools, 8, scope: described_class::PROMOTE_JOB_VALID_STATES) .and_return(Gitlab::PaginatedResponse.new([])) end where(:locked_state_metric_value, :ready_state_metric_value, :baking_time_metric_value, :awaiting_promotion, :event, :validity, :new_state) do [ ['0', '0', '0', '0', 'success', true, 'ready'], ['1', '0', '0', '0', 'success', true, 'ready'], ['0', '1', '0', '0', 'baking_complete', false, 'ready'] ] end with_them do it "returns validity and moves state" do expect(perform_event).to eq(validity) expect(service.current_state).to eq(new_state) end end end end # Stub query to Prometheus for `auto_deploy_environment_state` metric RSpec.shared_context 'environment state transition context' do |environment, stage| let(:query_string) { "auto_deploy_environment_state{target_env=\"#{environment}\",target_stage=\"#{stage}\"}" } let(:query_spy) { instance_spy(ReleaseTools::Prometheus::Query) } let(:results) do [ { "metric" => { "__name__" => "auto_deploy_environment_state", "target_env" => "gstg", "target_stage" => "cny", "env_state" => 'ready' }, "value" => [1_435_781_451.781, ready_state_metric_value] }, { "metric" => { "__name__" => "auto_deploy_environment_state", "target_env" => "gstg", "target_stage" => "cny", "env_state" => 'locked' }, "value" => [1_435_781_451.781, locked_state_metric_value] } ] end let(:response) do { "status" => "success", "data" => { "resultType" => "vector", "result" => results } } end before do allow(ReleaseTools::Prometheus::Query).to receive(:new).and_return(query_spy) allow(query_spy).to receive(:run).with(query_string).and_return(response) end end RSpec.shared_examples 'environment state transition' do |environment, stage| include_context 'metric registry' include_context 'environment state transition context', environment, stage let(:new_state) { 'ready' } let(:ready_state_metric_value) { '0' } let(:locked_state_metric_value) { '1' } describe '#current_state' do subject(:current_state) { described_class.new.current_state } context 'with non nil current state' do it 'returns current_state' do expect(current_state).to eq('locked') end end context 'with nil state' do let(:locked_state_metric_value) { '0' } it 'returns initial state' do expect(current_state).to eq('initial') end end end end