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