spec/lib/release_tools/patch_release/security_issue_spec.rb (212 lines of code) (raw):

# frozen_string_literal: true require 'spec_helper' describe ReleaseTools::PatchRelease::SecurityIssue do let(:crawler) do instance_spy( ReleaseTools::Security::IssueCrawler, related_security_issues: [create(:issue)] ) end let(:versions) do [ ReleaseTools::Version.new('12.7.4'), ReleaseTools::Version.new('12.6.6'), ReleaseTools::Version.new('12.5.9') ] end let(:helm_version_finder) { instance_double(ReleaseTools::Helm::HelmVersionFinder) } before do coordinator = instance_double( ReleaseTools::PatchRelease::Coordinator, versions: versions ) allow(ReleaseTools::PatchRelease::Coordinator) .to receive(:new) .and_return(coordinator) allow(ReleaseTools::Security::IssueCrawler) .to receive(:new) .and_return(crawler) allow(ReleaseTools::Helm::HelmVersionFinder) .to receive(:new) .and_return(helm_version_finder) allow(helm_version_finder).to receive(:execute).with('12.7.4').and_return('1.3.4') allow(helm_version_finder).to receive(:execute).with('12.6.6').and_return('1.4.5') allow(helm_version_finder).to receive(:execute).with('12.5.9').and_return('1.5.6') end subject(:issue) { described_class.new } it_behaves_like 'issuable #initialize' describe '#title' do context 'with a regular patch release' do it 'includes all the versions' do expect(issue.title).to eq('Patch release: 12.7.4, 12.6.6, 12.5.9') end end context 'with a critical patch release' do it 'includes the critical part' do allow(ReleaseTools::SharedStatus) .to receive(:critical_patch_release?) .and_return(true) expect(issue.title).to eq('Critical patch release: 12.7.4, 12.6.6, 12.5.9') end end end describe '#confidential?' do it 'is always confidential' do expect(issue).to be_confidential end end describe '#labels' do it 'includes the "security" label' do expect(issue.labels).to eq 'Monthly Release,security' end end describe '#description' do let(:tracking_issue) { build(:issue, web_url: 'http://example.com') } let(:security_release_pipeline) { build(:issue, web_url: 'http://example.com') } before do allow(issue).to receive_messages(security_release_tracking_issue: tracking_issue, release_pipeline: security_release_pipeline) end it 'includes a step to perform a patch release' do content = issue.description expect(content).to include 'Start the `security_release_release_preparation:start` job of the security pipeline' end it 'includes a step to publish the packages' do content = issue.description expect(content).to include 'Start the `security_release_publish:start` job of the security pipeline' end it 'includes the correct instance for packages' do content = issue.description expect(content).to include 'release.gitlab.net' end it 'returns Helm versions' do content = issue.description expect(content).to include 'https://dev.gitlab.org/gitlab/charts/gitlab/-/pipelines/?ref=v1.3.4' expect(content).to include 'https://dev.gitlab.org/gitlab/charts/gitlab/-/pipelines/?ref=v1.4.5' expect(content).to include 'https://dev.gitlab.org/gitlab/charts/gitlab/-/pipelines/?ref=v1.5.6' end end describe '#version' do it 'returns the highest version' do expect(issue.version).to eq('12.7.4') end context 'with unsorted versions' do let(:versions) do [ ReleaseTools::Version.new('12.6.6'), ReleaseTools::Version.new('12.7.4'), ReleaseTools::Version.new('12.5.9') ] end it 'returns the highest version' do expect(issue.version).to eq('12.7.4') end end end describe '#critical?' do context 'with a regular patch release' do it { is_expected.not_to be_critical } end context 'with a critical patch release' do before do allow(ReleaseTools::SharedStatus) .to receive(:critical_patch_release?) .and_return(true) end it { is_expected.to be_critical } end end describe '#regular?' do context 'with a regular patch release' do it { is_expected.to be_regular } end context 'with a critical patch release' do before do allow(ReleaseTools::SharedStatus) .to receive(:critical_patch_release?) .and_return(true) end it { is_expected.not_to be_regular } end end describe '#create' do it 'creates a security pipeline' do expect(issue).to receive(:release_pipeline) expect(ReleaseTools::GitlabClient).to receive(:create_issue) .with(issue, issue.project).and_return(true) issue.create end end describe '#release_pipeline' do let(:web_url) { "https://gitlab.example.com/pipelines/123" } let(:dry_run_url) { "https://example.com/foo/bar/-/pipelines/1" } it "creates a security pipeline on the ops instance" do expect(ReleaseTools::GitlabOpsClient).to receive(:create_pipeline).with( ReleaseTools::Project::ReleaseTools, { SECURITY_RELEASE_PIPELINE: 'true', SECURITY: nil } ).and_return(double(web_url: web_url)) without_dry_run do expect(issue.release_pipeline.web_url).to eq(web_url) end end context 'critical patch release' do it "creates a patch release injecting the SECURITY variable" do expect(ReleaseTools::GitlabOpsClient).to receive(:create_pipeline).with( ReleaseTools::Project::ReleaseTools, { SECURITY_RELEASE_PIPELINE: 'true', SECURITY: 'critical' } ).and_return(double(web_url: web_url)) without_dry_run do ClimateControl.modify('SECURITY' => 'critical') do expect(issue.release_pipeline.web_url).to eq(web_url) end end expect(issue.release_pipeline.web_url).to eq(web_url) end end context 'in dry run mode' do it 'imitates the create_pipeline API response' do expect(ReleaseTools::GitlabOpsClient).not_to receive(:create_pipeline) expect(issue.release_pipeline.web_url).to eq(dry_run_url) end end end describe '#unsupported_projects_list' do it 'returns a comma separated string list of the managed versioning projects' do expect(issue.unsupported_projects_list).to eq('cng-ee, gitaly, gitlab-pages') end end describe '#security_release_tracking_issue' do it 'returns the patch release tracking issue' do tracking_issue = build(:issue) expect(ReleaseTools::GitlabClient).to receive(:next_security_tracking_issue) .and_return(tracking_issue) expect(issue.security_release_tracking_issue).to eq(tracking_issue) end end describe '#version_type' do it 'returns the patch release type' do expect(issue.version_type).to eq('Non Critical') end context 'on a critical patch release' do it 'returns the associated patch release type' do allow(ReleaseTools::SharedStatus) .to receive(:critical_patch_release?) .and_return(true) expect(issue.version_type).to eq('Critical') end end end describe '#due_date' do it 'returns the same date as the tracking issue' do tracking_issue = build(:issue, due_date: '2024-04-01') allow(ReleaseTools::GitlabClient) .to receive(:next_security_tracking_issue) .and_return(tracking_issue) expect(issue.due_date).to eq('2024-04-01') end end end