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