spec/lib/release_tools/commits_spec.rb (133 lines of code) (raw):

# frozen_string_literal: true require 'spec_helper' describe ReleaseTools::Commits do subject(:instance) { described_class.new(project) } let(:project) { ReleaseTools::Project::GitlabCe } before do # Reduce our fixture payload stub_const('ReleaseTools::Commits::MAX_COMMITS_TO_CHECK', 5) end describe '#latest_successful_on_build' do it 'handles a missing commit on dev' do allow(ReleaseTools::GitlabDevClient) .to receive(:commit) .at_least(:twice) .and_raise(gitlab_error(:NotFound)) expect(instance).not_to receive(:find_last_auto_deploy_limit_sha) VCR.use_cassette('commits/list') do expect( instance.latest_successful_on_build(since_last_auto_deploy: false) do |_| true end ).to be_nil end end it 'returns a commit found on dev' do allow(ReleaseTools::GitlabDevClient) .to receive(:commit) .and_return('foo') expect(instance).not_to receive(:find_last_auto_deploy_limit_sha) VCR.use_cassette('commits/list') do predicate = ->(_) { true } expect(instance.latest_successful_on_build(since_last_auto_deploy: false, &predicate)).not_to be_nil end end context 'when limited to the last auto deploy package' do let(:project) { ReleaseTools::Project::GitlabEe } it 'limits the search to the merge base with the last package SHA' do commits = build_list(:commit, 5) last_pkg_sha = commits[1].id last_product_version = build(:product_version, releases: build(:releases_metadata, gitlab_ee: build(:component_metadata, sha: last_pkg_sha))) expect(ReleaseTools::ProductVersion).to receive(:last_auto_deploy).and_return(last_product_version) expect(instance).to receive(:commit_list).and_return(commits) expect(instance).to receive(:merge_base).once.and_return(last_pkg_sha) first_commit_sha = commits.first.id block_received_first_commit_sha = false commit = instance.latest_successful_on_build(since_last_auto_deploy: true) do |sha| # verify the block was invoked block_received_first_commit_sha = (sha == first_commit_sha) # verify it was only invoked with the first commit expect(sha).to eq(first_commit_sha) false end expect(block_received_first_commit_sha).to be true expect(commit.id).to eq(last_pkg_sha) end end end describe '#merge_base' do let(:project) { ReleaseTools::Project::GitlabEe } let(:ref) { '12-10-auto-deploy-20200405' } let(:client) { double('ReleaseTools::GitlabClient') } subject(:commits) { described_class.new(project, client: client, ref: ref) } it 'returns the merge-base commit id' do merge_base = double('merge_base', id: '123abc') expect(client) .to receive(:merge_base) .with(project.auto_deploy_path, [ref, 'another_ref']) .and_return(merge_base) .once merge_base_id = commits.merge_base('another_ref') expect(merge_base_id).to eq(merge_base.id) end end describe '#next_commit' do let(:instance) { described_class.new(project, client: client) } let(:client) { class_spy(ReleaseTools::GitlabClient) } it 'returns the next newer commit from the commit_list' do allow(client) .to receive(:commits) .with(project.auto_deploy_path, hash_including(ref_name: 'master')) .and_return([double(id: 'commit1'), double(id: 'commit2')]) expect(instance.next_commit('commit2').id).to eq('commit1') end it 'does not call commits API when memoized' do instance.instance_variable_set(:@commit_list, [double(id: 'commit1'), double(id: 'commit2')]) expect(client).not_to receive(:commits) expect(instance.next_commit('commit2').id).to eq('commit1') end it 'returns nil if there is no newer commit' do allow(instance) .to receive(:commit_list) .and_return([double(id: 'commit1')]) expect(instance.next_commit('commit1')).to be_nil end it 'returns nil if given commit cannot be found' do allow(instance) .to receive(:commit_list) .and_return([double(id: 'commit1')]) expect(instance.next_commit('commit3')).to be_nil end end describe '#find_last_auto_deploy_limit_sha' do let(:project) { ReleaseTools::Project::GitlabEe } let(:client) { double('ReleaseTools::GitlabClient') } let(:instance) { described_class.new(project, client: client) } context 'when a previous auto-deploy package exists' do it 'gets the SHA from the last auto-deploy ProductVersion and finds the merge base' do previous_sha = 'abcde123456' merge_base_result = 'def456' product_version = build( :product_version, releases: build(:releases_metadata, gitlab_ee: build(:component_metadata, sha: previous_sha)) ) # Expect to get the last auto-deploy version expect(ReleaseTools::ProductVersion) .to receive(:last_auto_deploy) .and_return(product_version) .once # Expect to find merge base with that SHA expect(instance).to receive(:merge_base) .with(previous_sha) .and_return(merge_base_result) # Verify the correct SHA is returned result = instance.find_last_auto_deploy_limit_sha expect(result).to eq(merge_base_result) # Verify it gets memoized by calling again even though we're expecting last_auto_deploy to be called only once expect(instance.find_last_auto_deploy_limit_sha).to eq(merge_base_result) end end context 'when project is not a supported auto-deploy project' do let(:project) { ReleaseTools::Project::Gitaly } it 'returns nil without checking ProductVersion' do expect(ReleaseTools::ProductVersion).not_to receive(:last_auto_deploy) expect(instance).not_to receive(:merge_base) expect(instance.find_last_auto_deploy_limit_sha).to be_nil end end end end