spec/lib/release_tools/tasks/auto_build/timer_spec.rb (201 lines of code) (raw):

# frozen_string_literal: true require 'spec_helper' require 'release_tools/tasks' RSpec.describe ReleaseTools::Tasks::AutoBuild::Timer do subject(:task) { described_class.new } let(:schedule_env) { '0, 3, 6,21' } around do |ex| ClimateControl.modify(AUTO_DEPLOY_SCHEDULE: schedule_env) do ex.run end end describe '#execute' do let(:prepare_task) { instance_double(ReleaseTools::Tasks::AutoBuild::Prepare) } let(:tag_task) { instance_double(ReleaseTools::Tasks::AutoDeploy::Tag) } let(:pick_service) { instance_double(ReleaseTools::CherryPick::AutoDeployService) } let(:current_auto_deploy_branch) { 'auto-deploy-01' } let(:new_auto_deploy_branch) { 'auto-deploy-02' } tests = [ { auto_build_time: true, no_auto_deploy_branch: true, should_prepare: true }, { auto_build_time: true, no_auto_deploy_branch: false, should_prepare: false }, { auto_build_time: false, no_auto_deploy_branch: false, should_prepare: false }, { auto_build_time: false, no_auto_deploy_branch: true, should_prepare: false } ] before do allow(ReleaseTools::Tasks::AutoBuild::Prepare).to receive(:new).and_return(prepare_task) allow(ReleaseTools::Tasks::AutoDeploy::Tag).to receive(:new).and_return(tag_task) allow(task).to receive_messages(auto_build_time?: auto_build_time, no_auto_deploy_branch?: no_auto_deploy_branch) end around do |ex| ClimateControl.modify(AUTO_DEPLOY_BRANCH: current_auto_deploy_branch) do ex.run end end tests.each do |test_case| context "when auto_build_time: #{test_case[:auto_build_time]} no_auto_deploy_branch: #{test_case[:no_auto_deploy_branch]}" do let(:auto_build_time) { test_case[:auto_build_time] } let(:no_auto_deploy_branch) { test_case[:no_auto_deploy_branch] } it 'correctly handles prepare, pick, and tag' do branch_name = current_auto_deploy_branch if test_case[:should_prepare] expect(prepare_task).to receive(:execute).and_return( [ ReleaseTools::Services::AutoDeployBranchService::Result.new( ReleaseTools::Project::GitlabEe.auto_deploy_path, new_auto_deploy_branch, build(:branch, name: new_auto_deploy_branch), false ) ] ) branch_name = new_auto_deploy_branch else expect(prepare_task).not_to receive(:execute) end expect(ReleaseTools::CherryPick::AutoDeployService).to receive(:new).with(ReleaseTools::Project::GitlabEe, branch_name).and_return(pick_service) expect(ReleaseTools::CherryPick::AutoDeployService).to receive(:new).with(ReleaseTools::Project::OmnibusGitlab, branch_name).and_return(pick_service) expect(ReleaseTools::CherryPick::AutoDeployService).to receive(:new).with(ReleaseTools::Project::CNGImage, branch_name).and_return(pick_service) expect(pick_service).to receive(:execute).exactly(3) expect(tag_task).to receive(:execute) task.execute end end end context 'when there are no new commits and auto deploy branch is not created' do let(:auto_build_time) { true } let(:no_auto_deploy_branch) { true } let(:pick_service) { instance_spy(ReleaseTools::CherryPick::AutoDeployService) } let(:tag_task) { instance_spy(ReleaseTools::Tasks::AutoDeploy::Tag) } before do allow(ReleaseTools::CherryPick::AutoDeployService).to receive(:new).and_return(pick_service) end it 'does not modify AUTO_DEPLOY_BRANCH' do expect(ENV.fetch('AUTO_DEPLOY_BRANCH', nil)).to eq(current_auto_deploy_branch) expect(prepare_task).to receive(:execute).and_return([]) task.execute expect(ENV.fetch('AUTO_DEPLOY_BRANCH', nil)).to eq(current_auto_deploy_branch) end end context 'with TAG_PACKAGERS_ONLY' do let(:auto_build_time) { true } let(:no_auto_deploy_branch) { false } it 'tags packagers only' do allow(tag_task).to receive(:execute) allow(ReleaseTools::CherryPick::AutoDeployService).to receive(:new).and_return(pick_service) allow(pick_service).to receive(:execute) expect(ReleaseTools::Tasks::AutoDeploy::Tag).to receive(:new).with(packagers_only: true) ClimateControl.modify(TAG_PACKAGERS_ONLY: 'true') do task.execute end end end end describe '#schedule' do it 'returns an array of integers' do expect(task.schedule).to eq([0, 3, 6, 21]) end context 'when AUTO_DEPLOY_SCHEDULE is not set' do let(:schedule_env) { nil } it 'raise an error' do expect { task.schedule }.to raise_error('Missing schedule definition in AUTO_DEPLOY_SCHEDULE') end end context 'when AUTO_DEPLOY_SCHEDULE is empty' do let(:schedule_env) { '' } # this is important for manual pipelines that disable the schedule and # only perform pick and tag it 'returns an empty array' do expect(task.schedule).to be_empty end end context 'when AUTO_DEPLOY_SCHEDULE contains unexpected characters' do let(:schedule_env) { '0,f,3' } it 'raise an error' do expect { task.schedule }.to raise_error(ArgumentError) end end context 'when AUTO_DEPLOY_SCHEDULE contains more than 24 hours' do let(:schedule_env) { (0..66).to_a.join(',') } it 'raise an error' do expect { task.schedule }.to raise_error(ArgumentError) end end context 'when AUTO_DEPLOY_SCHEDULE contains number higher than 23' do let(:schedule_env) { '0,24,5' } it 'raise an error' do expect { task.schedule }.to raise_error(ArgumentError, '24 is not a valid hour of the day') end end context 'when AUTO_DEPLOY_SCHEDULE contains negative numbers' do let(:schedule_env) { '9,-6,5' } it 'raise an error' do expect { task.schedule }.to raise_error(ArgumentError, '-6 is not a valid hour of the day') end end end describe '#auto_build_time?' do it 'is auto build time when hour matches the schedule' do schedule_env.split(',') do |hour| now = Time.utc(2023, 5, 3, hour.to_i, 45) Timecop.travel(now) do expect(task).to be_auto_build_time end end end it 'is not auto build time when hour is outside of the schedule' do 0.upto(23) do |hour| next if task.schedule.include?(hour) now = Time.utc(2023, 5, 3, hour.to_i, 45) Timecop.travel(now) do expect(task).not_to be_auto_build_time end end end it 'is not auto build time on weekend' do 0.upto(23) do |hour| saturday = Time.utc(2023, 4, 29, hour.to_i, 45) Timecop.travel(saturday) do expect(task).not_to be_auto_build_time end Timecop.travel(saturday + 1.day) do expect(task).not_to be_auto_build_time end end end it 'can be forced true with CREATE_AUTO_DEPLOY_BRANCH_SCHEDULE' do ClimateControl.modify(CREATE_AUTO_DEPLOY_BRANCH_SCHEDULE: '1') do saturday = Time.utc(2023, 4, 29) Timecop.travel(saturday) do expect(task).to be_auto_build_time end end end end describe '#no_auto_deploy_branch?' do it 'returns true when the current auto-deploy branch does not exist' do branch = '16-0-auto-deploy-2023050308' expect(ReleaseTools::AutoDeploy::Naming).to receive(:branch).and_return(branch) expect(ReleaseTools::GitlabClient).to receive(:find_branch).with(branch, ReleaseTools::Project::GitlabEe.auto_deploy_path).and_return(nil) expect(task).to be_no_auto_deploy_branch end it 'returns false when the current auto-deploy branch exists' do branch = '16-0-auto-deploy-2023050308' expect(ReleaseTools::AutoDeploy::Naming).to receive(:branch).and_return(branch) expect(ReleaseTools::GitlabClient).to receive(:find_branch).with(branch, ReleaseTools::Project::GitlabEe.auto_deploy_path).and_return(build(:branch)) expect(task).not_to be_no_auto_deploy_branch end end end