spec/lib/release_tools/deployments/deployment_tracker_spec.rb (330 lines of code) (raw):
# frozen_string_literal: true
require 'spec_helper'
describe ReleaseTools::Deployments::DeploymentTracker do
describe '#commit_range' do
let(:version) { '12.7.202001101501-94b8fd8d152.6fea3031ec9' }
context 'when deploying to a QA environment with deployments' do
it 'returns the current and previous deployment SHAs' do
tracker = described_class.new(version: version)
allow(ReleaseTools::GitlabClient)
.to receive(:deployments)
.and_return([
double(:deployment, sha: 'bar'),
double(:deployment, sha: 'foo')
])
expect(tracker.commit_range).to eq(%w[foo bar])
end
end
context 'when deploying to a QA environment with for the first time' do
it 'does not return the previous deployment SHA' do
tracker = described_class.new(version: version)
allow(ReleaseTools::GitlabClient)
.to receive(:deployments)
.and_return([])
expect(tracker.commit_range).to eq([])
end
end
context 'when deploying to a non-QA environment' do
it 'returns an empty Array' do
tracker = described_class.new(version: version)
allow(ReleaseTools::GitlabClient)
.to receive(:deployments)
.and_return([])
expect(tracker.commit_range).to be_empty
end
end
end
describe '#track' do
context 'when using a valid status' do
let(:version) { '12.7.202001101501-94b8fd8d152.6fea3031ec9' }
let(:product_version) { ReleaseTools::ProductVersion.from_package_version(version) }
let(:product_meta) do
{
'releases' => {
'gitlab-ee' => {
'ref' => '1-2-auto-deploy-01022020',
'sha' => '123',
'tag' => false
},
'omnibus-gitlab-ee' => {
'ref' => '1-2-auto-deploy-01022020',
'sha' => '456',
'tag' => false
},
'gitaly' => {
'sha' => '94b8fd8d152680445ec14241f14d1e4c04b0b5ab',
'ref' => 'master',
'tag' => false
},
'gitlab_kas' => {
'ref' => 'master',
'sha' => '5bbaac6e3d907fba9568a2e36aa1e521f589c897',
'tag' => false
}
}
}
end
before do
allow(ReleaseTools::ProductVersion)
.to receive(:from_package_version)
.and_return(product_version)
allow(product_version)
.to receive(:metadata)
.and_return(product_meta)
# We test the logging of previous deployments separately.
allow(ReleaseTools::GitlabClient)
.to receive(:last_successful_deployment)
end
it 'tracks the deployment of GitLab, Gitaly, kas, and Omnibus GitLab in 2 repositories' do
tracker = described_class.new(environment: 'staging', status: 'running', version: version)
allow(tracker).to receive(:log_previous_deployment)
# Verify the Security deploys on the auto-deploy branch
expect(ReleaseTools::GitlabClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::GitlabEe.auto_deploy_path,
'staging',
{
ref: '1-2-auto-deploy-01022020',
sha: '123',
status: 'running',
tag: false
}
)
.and_return(build(:deployment, id: 1, sha: '123'))
expect(ReleaseTools::GitlabClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::Gitaly.auto_deploy_path,
'staging',
{
ref: 'master', # Gitaly will always use `master`
sha: '94b8fd8d152680445ec14241f14d1e4c04b0b5ab',
status: 'running',
tag: false
}
)
.and_return(build(:deployment, id: 2, sha: '94b8fd8d152680445ec14241f14d1e4c04b0b5ab'))
expect(ReleaseTools::GitlabClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::OmnibusGitlab.auto_deploy_path,
'staging',
{
ref: '1-2-auto-deploy-01022020',
sha: '456',
status: 'running',
tag: false
}
)
.and_return(build(:deployment, id: 3, sha: '456'))
expect(ReleaseTools::GitlabClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::Kas.auto_deploy_path,
'staging',
{
ref: 'master',
sha: '5bbaac6e3d907fba9568a2e36aa1e521f589c897',
status: 'running',
tag: false
}
)
.and_return(build(:deployment, id: 4, sha: '5bbaac6e3d907fba9568a2e36aa1e521f589c897'))
# Verify the Canonical deploys on the `master` branch
expect(tracker).to receive(:auto_deploy_intersection)
.with(ReleaseTools::Project::GitlabEe, '123')
.and_return('abcde')
expect(tracker).to receive(:auto_deploy_intersection)
.with(ReleaseTools::Project::Gitaly, '94b8fd8d152680445ec14241f14d1e4c04b0b5ab')
.and_return('94b8fd8d152680445ec14241f14d1e4c04b0b5ab')
expect(tracker).to receive(:auto_deploy_intersection)
.with(ReleaseTools::Project::OmnibusGitlab, '456')
.and_return('fghij')
expect(tracker).to receive(:auto_deploy_intersection)
.with(ReleaseTools::Project::Kas, '5bbaac6e3d907fba9568a2e36aa1e521f589c897')
.and_return('5bbaac6e3d907fba9568a2e36aa1e521f589c897')
expect(ReleaseTools::GitlabClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::GitlabEe.path,
'staging',
{
ref: 'master',
sha: 'abcde',
status: 'running',
tag: false
}
)
.and_return(build(:deployment, id: 5, sha: 'abcde'))
expect(ReleaseTools::GitlabClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::Gitaly.path,
'staging',
{
ref: 'master',
sha: '94b8fd8d152680445ec14241f14d1e4c04b0b5ab',
status: 'running',
tag: false
}
)
.and_return(build(:deployment, id: 6, sha: '94b8fd8d152680445ec14241f14d1e4c04b0b5ab'))
expect(ReleaseTools::GitlabClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::OmnibusGitlab.path,
'staging',
{
ref: 'master',
sha: 'fghij',
status: 'running',
tag: false
}
)
.and_return(build(:deployment, id: 7, sha: 'fghij'))
expect(ReleaseTools::GitlabClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::Kas.path,
'staging',
{
ref: 'master',
sha: '5bbaac6e3d907fba9568a2e36aa1e521f589c897',
status: 'running',
tag: false
}
)
.and_return(build(:deployment, id: 8, sha: '5bbaac6e3d907fba9568a2e36aa1e521f589c897'))
deployments = without_dry_run { tracker.track }
expect(deployments.length).to eq(8)
expect(deployments.collect(&:id)).to contain_exactly(1, 2, 3, 4, 5, 6, 7, 8)
expect(deployments.collect(&:project_path)).to include(
ReleaseTools::Project::GitlabEe.auto_deploy_path,
ReleaseTools::Project::GitlabEe.path
)
end
it 'does not create a canonical deployment when no canonical commit is found' do
tracker = described_class.new(environment: 'staging', status: 'success', version: version)
expect(ReleaseTools::GitlabClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::GitlabEe.auto_deploy_path,
'staging',
{
ref: '1-2-auto-deploy-01022020',
sha: '123',
status: 'success',
tag: false
}
)
.and_return(build(:deployment, id: 1, sha: '123'))
expect(ReleaseTools::GitlabClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::Gitaly.auto_deploy_path,
'staging',
{
ref: 'master', # Gitaly will always use `master`
sha: '94b8fd8d152680445ec14241f14d1e4c04b0b5ab',
status: 'success',
tag: false
}
)
.and_return(build(:deployment, id: 2, sha: '94b8fd8d152680445ec14241f14d1e4c04b0b5ab'))
expect(ReleaseTools::GitlabClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::OmnibusGitlab.auto_deploy_path,
'staging',
{
ref: '1-2-auto-deploy-01022020',
sha: '456',
status: 'success',
tag: false
}
)
.and_return(build(:deployment, id: 3, sha: '456'))
expect(ReleaseTools::GitlabClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::Kas.auto_deploy_path,
'staging',
{
ref: 'master',
sha: '5bbaac6e3d907fba9568a2e36aa1e521f589c897',
status: 'success',
tag: false
}
)
.and_return(build(:deployment, id: 4, sha: '5bbaac6e3d907fba9568a2e36aa1e521f589c897'))
expect(tracker).to receive(:auto_deploy_intersection)
.and_return(nil)
.exactly(4).times
deployments = without_dry_run { tracker.track }
expect(deployments.length).to eq(4)
expect(deployments.collect(&:id)).to contain_exactly(1, 2, 3, 4)
end
end
context 'when using an invalid status' do
it 'raises ArgumentError' do
version = '12.7.202001101501-94b8fd8d152.6fea3031ec9'
expect { described_class.new('staging', 'foo', version).track }
.to raise_error(ArgumentError)
end
end
end
describe '.record_metadata_deployment' do
context 'when using a valid status' do
let(:version) { '12.7.202001101501-94b8fd8d152.6fea3031ec9' }
let(:product_version) { ReleaseTools::ProductVersion.from_package_version(version) }
before do
allow(ReleaseTools::ProductVersion)
.to receive(:from_package_version)
.and_return(product_version)
end
it 'tracks the deployment on release/metadata' do
tracker = described_class.new(environment: 'staging', status: 'running', version: version)
metadata_commit_id = '123abc'
allow(product_version).to receive(:metadata_commit_id).and_return(metadata_commit_id)
expect(ReleaseTools::GitlabOpsClient)
.to receive(:update_or_create_deployment)
.with(
ReleaseTools::Project::Release::Metadata,
'staging',
{
ref: 'master',
sha: metadata_commit_id,
status: 'running'
}
)
without_dry_run { tracker.record_metadata_deployment }
end
end
context 'when using an invalid status' do
it 'raises ArgumentError' do
version = '12.7.202001101501-94b8fd8d152.6fea3031ec9'
expect { described_class.new('staging', 'foo', version).record_metadata_deployment }
.to raise_error(ArgumentError)
end
end
end
describe '#log_new_deployment' do
it 'logs a new deployment' do
deploy = double(:deployment, id: 1, iid: 1, ref: 'master', sha: 'abc')
version = '12.7.202001101501-94b8fd8d152.6fea3031ec9'
tracker = described_class.new(environment: 'staging', status: 'success', version: version)
expect(tracker.logger).to receive(:log)
tracker.send(:log_new_deployment, 'foo/bar', deploy)
end
end
describe '#log_previous_deployment' do
it 'logs the previous deployment deployment' do
deploy = double(:deployment, id: 1, iid: 1, ref: 'master', sha: 'abc')
version = '12.7.202001101501-94b8fd8d152.6fea3031ec9'
tracker = described_class.new(environment: 'staging', status: 'success', version: version)
expect(ReleaseTools::GitlabClient)
.to receive(:last_successful_deployment)
.with('foo/bar', 'staging')
.and_return(deploy)
expect(tracker.logger).to receive(:log)
tracker.send(:log_previous_deployment, 'foo/bar')
end
end
end