spec/support/shared_examples/component_updater_shared_examples.rb (144 lines of code) (raw):

# frozen_string_literal: true RSpec.shared_examples 'component updater' do |project_class, merge_request_class, slack_notification_method| let(:token) { 'a token' } # Use the subject provided by the including spec # This allows us to handle both class and module cases describe '.new' do context 'when GITLAB_BOT_PRODUCTION_TOKEN is not available' do let(:token) { nil } it 'raises error' do ClimateControl.modify(GITLAB_BOT_PRODUCTION_TOKEN: nil) do expect { task }.to raise_error('key not found: "GITLAB_BOT_PRODUCTION_TOKEN"') end end end end describe '#execute' do context 'when there are no changes' do it 'does nothing' do expect(task).to receive(:changed?).and_return(false) expect(task).not_to receive(:merge_request) expect(task).not_to receive(:ensure_source_branch_exists) expect(task).not_to receive(:create_or_show_merge_request) expect(ReleaseTools::Services::UpdateComponentService) .not_to receive(:new) expect(ReleaseTools::Services::AutoMergeService).not_to receive(:new) without_dry_run do task.execute end end end context 'when the merge request already exists' do let(:merge_request) do instance_double( ReleaseTools::UpdateKasMergeRequest, exists?: true, url: 'an url', merge_when_pipeline_succeeds?: false, remote_issuable: build(:merge_request), detailed_merge_status: merge_status, notifiable?: notifiable ) end let(:notifiable) { true } before do allow(task).to receive(:merge_request).and_return(merge_request) end context 'when the merge request is mergeable' do %w[mergeable unchecked not_approved].each do |merge_status| let(:merge_status) { merge_status } it "sets auto merge for the merge request with status #{merge_status}" do expect(task).to receive(:changed?).and_return(true) expect(task).to receive(:create_merge_request_and_set_auto_merge) expect(task).not_to receive(:notify_stale_merge_request) without_dry_run do task.execute end end end end context 'when the merge request is not mergeable' do context 'when the merge request is notifiable' do let(:merge_status) { 'ci_still_running' } it 'sends a notification if MR is stale' do expect(task).to receive(:changed?).and_return(true) expect(task).not_to receive(:create_merge_request_and_set_auto_merge) if slack_notification_method expect(ReleaseTools::Slack::AutoDeployNotification) .to receive(slack_notification_method) .with(merge_request) else expect(task).to receive(:send_slack_notification) end expect(merge_request).to receive(:mark_as_stale) without_dry_run do task.execute end end end context 'when the merge request is not notifiable' do let(:merge_status) { 'ci_still_running' } let(:notifiable) { false } it 'does not notify' do expect(task).to receive(:changed?).and_return(true) expect(task).not_to receive(:create_merge_request_and_set_auto_merge) expect(task).not_to receive(:notify_stale_merge_request) without_dry_run do task.execute end end end end end context 'when the merge request does not exist' do it 'makes sure the source branch exists, creates the merge request, updates component versions and auto-merge' do expect(task).to receive(:changed?).and_return(true) merge_request = instance_double(merge_request_class, exists?: false, project: double) allow(task).to receive(:merge_request).and_return(merge_request) expect(task).to receive(:ensure_source_branch_exists) expect(task).to receive(:create_or_show_merge_request).with(merge_request) update_component_service = instance_double(ReleaseTools::Services::UpdateComponentService) expect(ReleaseTools::Services::UpdateComponentService) .to receive(:new) .with(project_class, task.source_branch, { skip_ci: true }) .and_return(update_component_service) commit = instance_double(ReleaseTools::Commits) expect(update_component_service).to receive(:execute).and_return(commit) auto_merge_service = instance_double(ReleaseTools::Services::AutoMergeService) expect(ReleaseTools::Services::AutoMergeService).to receive(:new).with(merge_request, { token: token, commit: commit }).and_return(auto_merge_service) expect(auto_merge_service).to receive(:execute) without_dry_run do task.execute end end end end describe '#ensure_source_branch_exist' do it 'delegates to GitlabClient.find_or_create_branch' do branch = instance_double(ReleaseTools::Branch) # Use TARGET_PROJECT from the class if it's a class constant, otherwise use the project parameter target_project = defined?(described_class::TARGET_PROJECT) ? described_class::TARGET_PROJECT : task.class::TARGET_PROJECT expect(ReleaseTools::GitlabClient) .to receive(:find_or_create_branch) .with(task.source_branch, 'master', target_project) .and_return(branch) without_dry_run do expect(task.ensure_source_branch_exists).to eq(branch) end end end describe '#changed?' do it 'checks for changes in master' do changed = double('changed?') # rubocop:disable RSpec/VerifiedDoubles expect(ReleaseTools::Services::UpdateComponentService) .to receive(:new) .with(project_class, 'master') .and_return(instance_double(ReleaseTools::Services::UpdateComponentService, changed?: changed)) expect(task.changed?).to eq(changed) end end describe '#merge_request' do it 'is a merge request from source_branch' do expect(merge_request_class) .to receive(:new) .with({ source_branch: task.source_branch }) task.merge_request end end end