spec/lib/release_tools/services/branches_status_service_spec.rb (280 lines of code) (raw):

# frozen_string_literal: true require 'spec_helper' describe ReleaseTools::Services::BranchesStatusService do describe '#execute' do subject(:branch_verifier) { described_class.new(release_type: release_type, versions: versions) } let(:notifier) { stub_const('ReleaseTools::Slack::ReleaseJobEndNotifier', spy) } let(:projects) { [ReleaseTools::Project::GitlabCe, ReleaseTools::Project::GitlabEe] } let(:statuses) do [ { project_name: 'project_name', branch: 'branch_name', link: 'link', status: 'failed' } ] end before do stub_const("ReleaseTools::Services::BranchesStatusService::PROJECTS", projects) end context "on monthly release" do let(:release_type) { :monthly } let(:versions) { [ReleaseTools::Version.new("15.9")] } it "returns all stable branches are green on success status" do expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.first, branch: '15-9-stable', release_type: :monthly ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'success')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.second, branch: '15-9-stable-ee', release_type: :monthly ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'success')) expect(branch_verifier.logger).to receive(:info).with(/All branches are green/) expect(notifier).to receive(:send_notification) branch_verifier.execute end context 'when some statuses are not success and raises an exception' do it 'outputs the component versions that are not successful' do logger_output = " ❌ The following branches do not have green pipelines: - gitlab-ce - 15-9-stable - failed: https://gitlab.com/gitlab-org/gitlab-foss/-/commits/15-9-stable - gitlab-ee - 15-9-stable-ee - canceled: https://gitlab.com/gitlab-org/gitlab/-/commits/15-9-stable-ee" expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.first, branch: '15-9-stable', release_type: :monthly ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'failed')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.second, branch: '15-9-stable-ee', release_type: :monthly ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'canceled')) expect(branch_verifier.logger).to receive(:info).with(logger_output) expect(notifier).to receive(:send_notification) expect { branch_verifier.execute }.to raise_error(described_class::FailedBranchError) end end context 'when the job is unable to complete and an error is raised' do before do allow(branch_verifier).to receive(:statuses).and_return(statuses) end it 'outputs manual instructions and raises an error' do log_message = "Project status check failed. If this job continues to fail, the status of the projects can be checked manually:\n\n- project_name - branch_name: link" allow(ReleaseTools::Services::ComponentStatusService).to receive(:new) .and_raise(Gitlab::Error::Error) expect(ReleaseTools::Slack::ReleaseJobEndNotifier).to receive(:new).with( job_type: 'Branches Status', status: :failed, release_type: :monthly ).and_return(instance_double(ReleaseTools::Slack::ReleaseJobEndNotifier, send_notification: true)) expect(branch_verifier.logger).to receive(:fatal).with(log_message, error: anything) expect { branch_verifier.execute }.to raise_error(Gitlab::Error::Error) end end end context "on patch release preparation" do let(:release_type) { :patch } let(:versions) { [ReleaseTools::Version.new("17.1"), ReleaseTools::Version.new("16.10"), ReleaseTools::Version.new("15.11")] } before do allow(branch_verifier).to receive(:projects).and_return(projects) end it "returns all branches are green on success status" do expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.first, branch: '17-1-stable', release_type: :patch ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'success')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.first, branch: '16-10-stable', release_type: :patch ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'success')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.first, branch: '15-11-stable', release_type: :patch ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'success')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.second, branch: '17-1-stable-ee', release_type: :patch ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'success')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.second, branch: '16-10-stable-ee', release_type: :patch ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'success')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.second, branch: '15-11-stable-ee', release_type: :patch ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'success')) expect(branch_verifier.logger).to receive(:info).with(/All branches are green/) expect(notifier).to receive(:send_notification) branch_verifier.execute end context 'when some statuses are not success and raises an exception' do it 'outputs the component versions that are not successful' do logger_output = " ❌ The following branches do not have green pipelines: - gitlab-ce - 17-1-stable - failed: https://gitlab.com/gitlab-org/security/gitlab-foss/-/commits/17-1-stable - gitlab-ce - 16-10-stable - failed: https://gitlab.com/gitlab-org/security/gitlab-foss/-/commits/16-10-stable - gitlab-ce - 15-11-stable - failed: https://gitlab.com/gitlab-org/security/gitlab-foss/-/commits/15-11-stable - gitlab-ee - 17-1-stable-ee - canceled: https://gitlab.com/gitlab-org/security/gitlab/-/commits/17-1-stable-ee - gitlab-ee - 16-10-stable-ee - running: https://gitlab.com/gitlab-org/security/gitlab/-/commits/16-10-stable-ee - gitlab-ee - 15-11-stable-ee - failed: https://gitlab.com/gitlab-org/security/gitlab/-/commits/15-11-stable-ee" expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.first, branch: '17-1-stable', release_type: :patch ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'failed')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.first, branch: '16-10-stable', release_type: :patch ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'failed')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.first, branch: '15-11-stable', release_type: :patch ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'failed')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.second, branch: '17-1-stable-ee', release_type: :patch ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'canceled')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.second, branch: '16-10-stable-ee', release_type: :patch ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'running')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.second, branch: '15-11-stable-ee', release_type: :patch ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'failed')) expect(branch_verifier.logger).to receive(:info).with(logger_output) expect(notifier).to receive(:send_notification) expect(branch_verifier.logger).not_to receive(:fatal) expect { branch_verifier.execute }.to raise_error(described_class::FailedBranchError) end end context 'when the job is unable to complete and an error is raised' do before do allow(branch_verifier).to receive(:statuses).and_return(statuses) allow(ReleaseTools::Services::ComponentStatusService).to receive(:new) .and_raise(Gitlab::Error::Error) end it 'outputs manual instructions and raises an error' do log_message = "Project status check failed. If this job continues to fail, the status of the projects can be checked manually:\n\n- project_name - branch_name: link" expect(branch_verifier).to receive(:generate_link_list) .with(projects, versions, release_type) .and_yield('project_name', 'branch_name', 'link') expect(ReleaseTools::Slack::ReleaseJobEndNotifier).to receive(:new).with( job_type: 'Branches Status', status: :failed, release_type: :patch ).and_return(instance_double(ReleaseTools::Slack::ReleaseJobEndNotifier, send_notification: true)) expect(branch_verifier.logger).to receive(:fatal).with(log_message, error: anything) expect { branch_verifier.execute }.to raise_error(Gitlab::Error::Error) end it 'does not log the failure message (info) and does not raise FailedBranchError' do expect(branch_verifier.logger).not_to receive(:info) expect { branch_verifier.execute }.not_to raise_error(described_class::FailedBranchError) end end end context "on internal release" do let(:release_type) { :internal } let(:versions) do [ ReleaseTools::Version.new('15.2.1-internal1'), ReleaseTools::Version.new('15.1.2-internal1') ] end before do allow(branch_verifier).to receive(:projects).and_return(projects) end it "returns all branches are green on success status" do expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.first, branch: '15-2-stable', release_type: :internal ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'success')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.first, branch: '15-1-stable', release_type: :internal ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'success')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.second, branch: '15-2-stable-ee', release_type: :internal ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'success')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.second, branch: '15-1-stable-ee', release_type: :internal ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'success')) expect(branch_verifier.logger).to receive(:info).with(/All branches are green/) expect(notifier).to receive(:send_notification) branch_verifier.execute end context 'when some statuses are not success and raises an exception' do it 'outputs the component versions that are not successful' do logger_output = " ❌ The following branches do not have green pipelines: - gitlab-ce - 15-2-stable - failed: https://gitlab.com/gitlab-org/security/gitlab-foss/-/commits/15-2-stable - gitlab-ce - 15-1-stable - failed: https://gitlab.com/gitlab-org/security/gitlab-foss/-/commits/15-1-stable - gitlab-ee - 15-2-stable-ee - canceled: https://gitlab.com/gitlab-org/security/gitlab/-/commits/15-2-stable-ee - gitlab-ee - 15-1-stable-ee - running: https://gitlab.com/gitlab-org/security/gitlab/-/commits/15-1-stable-ee" expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.first, branch: '15-2-stable', release_type: :internal ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'failed')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.first, branch: '15-1-stable', release_type: :internal ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'failed')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.second, branch: '15-2-stable-ee', release_type: :internal ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'canceled')) expect(ReleaseTools::Services::ComponentStatusService).to receive(:new).with( project: projects.second, branch: '15-1-stable-ee', release_type: :internal ).and_return(instance_double(ReleaseTools::Services::ComponentStatusService, execute: 'running')) expect(branch_verifier.logger).to receive(:info).with(logger_output) expect(notifier).to receive(:send_notification) expect(branch_verifier.logger).not_to receive(:fatal) expect { branch_verifier.execute }.to raise_error(described_class::FailedBranchError) end end context 'when the job is unable to complete and an error is raised' do before do allow(branch_verifier).to receive(:statuses).and_return(statuses) allow(ReleaseTools::Services::ComponentStatusService).to receive(:new) .and_raise(StandardError) end it 'outputs manual instructions and raises an error' do log_message = "Project status check failed. If this job continues to fail, the status of the projects can be checked manually:\n\n- project_name - branch_name: link" expect(branch_verifier).to receive(:generate_link_list) .with(projects, versions, release_type) .and_yield('project_name', 'branch_name', 'link') expect(ReleaseTools::Slack::ReleaseJobEndNotifier).to receive(:new).with( job_type: 'Branches Status', status: :failed, release_type: :internal ).and_return(instance_double(ReleaseTools::Slack::ReleaseJobEndNotifier, send_notification: true)) expect(branch_verifier.logger).to receive(:fatal).with(log_message, error: anything) expect { branch_verifier.execute }.to raise_error(StandardError) end end it 'does not log the failure message (info) and does not raise FailedBranchError' do expect(branch_verifier.logger).not_to receive(:info) expect { branch_verifier.execute }.not_to raise_error(described_class::FailedBranchError) end end end end