spec/lib/release_tools/pipeline_tracer/pipeline_spec.rb (324 lines of code) (raw):

# frozen_string_literal: true require 'spec_helper' describe ReleaseTools::PipelineTracer::Pipeline do describe '.from_url' do it 'create instance' do instance = described_class.from_url('https://ops.gitlab.net/gitlab-org/release/tools/-/pipelines/1590941') expect(instance.gitlab_instance).to eq('ops.gitlab.net') expect(instance.project).to eq('gitlab-org/release/tools') expect(instance.id).to eq('1590941') end end describe '#details' do subject(:details) { described_class.new('ops.gitlab.net', 'gitlab-org/release/tools', '1590941').details } let(:pipeline_details) { Gitlab::ObjectifiedHash.new({ kind: 'correct' }) } before do allow(ReleaseTools::GitlabOpsClient).to receive(:pipeline).and_return(pipeline_details) end it 'calls pipeline API' do expect(ReleaseTools::GitlabOpsClient) .to receive(:pipeline) .with('gitlab-org/release/tools', '1590941') expect(details).to eq(pipeline_details) end end describe '#bridge_jobs' do subject(:bridge_jobs) { described_class.new('ops.gitlab.net', 'gitlab-org/release/tools', '1590941').bridge_jobs } let(:pipeline_bridge_jobs) { [Gitlab::ObjectifiedHash.new({ kind: 'correct' })] } before do allow(ReleaseTools::GitlabOpsClient).to receive(:pipeline_bridges).and_return(pipeline_bridge_jobs) end it 'calls pipeline bridge API' do expect(ReleaseTools::GitlabOpsClient) .to receive(:pipeline_bridges) .with('gitlab-org/release/tools', '1590941') expect(bridge_jobs).to eq(pipeline_bridge_jobs) end end describe '#jobs' do subject(:jobs) { described_class.new('ops.gitlab.net', 'gitlab-org/release/tools', '1590941').jobs } let(:pipeline_jobs) { [Gitlab::ObjectifiedHash.new({ kind: 'correct' })] } before do allow(ReleaseTools::GitlabOpsClient).to receive(:pipeline_jobs).and_return(pipeline_jobs) end it 'calls pipeline jobs API' do expect(ReleaseTools::GitlabOpsClient) .to receive(:pipeline_jobs) .with('gitlab-org/release/tools', '1590941', { include_retried: true, per_page: 100 }) expect(jobs).to eq(pipeline_jobs) end end describe '#url' do subject(:url) { described_class.new('ops.gitlab.net', 'gitlab-org/release/tools', '1590941').url } it 'returns URL' do expect(url).to eq('https://ops.gitlab.net/gitlab-org/release/tools/-/pipelines/1590941') end end describe '#start_time' do subject(:start_time) { described_class.new('ops.gitlab.net', 'gitlab-org/release/tools', '1590941').start_time } before do allow(ReleaseTools::GitlabOpsClient).to receive(:pipeline).and_return(pipeline_details) end context 'with started_at available' do let(:pipeline_details) { Gitlab::ObjectifiedHash.new({ created_at: '2022-12-07T16:21:00.557Z', started_at: '2022-12-07T16:21:03.514Z' }) } it 'returns started_at' do expect(ReleaseTools::GitlabOpsClient) .to receive(:pipeline) .with('gitlab-org/release/tools', '1590941') expect(start_time).to eq('2022-12-07T16:21:03.514Z') end end context 'with started_at nil' do let(:pipeline_details) { Gitlab::ObjectifiedHash.new({ created_at: '2022-12-07T16:21:00.557Z', started_at: nil }) } it 'returns created_at' do expect(ReleaseTools::GitlabOpsClient) .to receive(:pipeline) .with('gitlab-org/release/tools', '1590941') expect(start_time).to eq('2022-12-07T16:21:00.557Z') end end end describe '#end_time' do subject(:end_time) { described_class.new('ops.gitlab.net', 'gitlab-org/release/tools', '1590941').end_time } before do allow(ReleaseTools::GitlabOpsClient).to receive(:pipeline).and_return(pipeline_details) end context 'with complete pipeline' do let(:pipeline_details) do build( :pipeline, :success, { updated_at: '2022-12-07T16:21:00.557Z', finished_at: '2022-12-07T16:21:03.514Z' } ) end it 'returns finished_at' do expect(ReleaseTools::GitlabOpsClient) .to receive(:pipeline) .with('gitlab-org/release/tools', '1590941') expect(end_time).to eq('2022-12-07T16:21:03.514Z') end context 'when finished_at is nil' do let(:pipeline_details) do build( :pipeline, :success, { updated_at: '2022-12-07T16:21:00.557Z', finished_at: nil } ) end it 'returns updated_at' do expect(ReleaseTools::GitlabOpsClient) .to receive(:pipeline) .with('gitlab-org/release/tools', '1590941') expect(end_time).to eq('2022-12-07T16:21:00.557Z') end end end context 'with incomplete pipeline' do let(:pipeline_details) do build( :pipeline, :running, { updated_at: '2022-12-07T16:21:00.557Z', finished_at: '2022-12-07T16:21:03.514Z' } ) end let(:pipeline_jobs) do [build(:job, :success, finished_at: '2022-12-07T17:21:03Z'), build(:job, finished_at: nil)] end let(:pipeline_bridge_jobs) do [build(:bridge_job, :success, finished_at: '2022-12-07T18:21:03Z'), build(:bridge_job, finished_at: nil)] end before do allow(ReleaseTools::GitlabOpsClient) .to receive_messages(pipeline_jobs: Gitlab::PaginatedResponse.new(pipeline_jobs), pipeline_bridges: Gitlab::PaginatedResponse.new(pipeline_bridge_jobs)) end it 'returns last job finished_at' do expect(end_time).to eq(pipeline_bridge_jobs[0].finished_at) end context 'when there are no bridge jobs' do let(:pipeline_bridge_jobs) { [] } it 'returns last job finished_at' do expect(end_time).to eq(pipeline_jobs[0].finished_at) end end context 'with no complete jobs' do let(:pipeline_bridge_jobs) { [build(:bridge_job, :running, finished_at: nil)] } let(:pipeline_jobs) do [build(:job, :running, finished_at: nil), build(:job, finished_at: nil)] end it 'returns nil' do expect(end_time).to be_nil end end context 'with ignored job' do let(:pipeline_bridge_jobs) { [] } let(:pipeline_jobs) do [ build(:job, :success, finished_at: '2022-12-07T17:21:03Z'), build(:job, name: 'metrics:trace-pipeline', finished_at: '2022-12-07T18:21:03Z') ] end it 'returns correct finished_at' do expect(end_time).to eq(pipeline_jobs[0].finished_at) end end end end describe '#valid_finished_at?' do subject(:pipeline) { described_class.new('ops.gitlab.net', 'gitlab-org/release/tools', '1590941') } let(:pipeline_details) { build(:pipeline, status) } before do allow(ReleaseTools::GitlabOpsClient).to receive(:pipeline).and_return(pipeline_details) end context 'with non completed status' do let(:status) { 'running' } it { is_expected.not_to be_valid_finished_at } end %w[success failed canceled].each do |status| let(:status) { status } context "with #{status} status" do it { is_expected.to be_valid_finished_at } end end end describe '#real_time_duration' do subject(:real_time_duration) { described_class.new('ops.gitlab.net', 'gitlab-org/release/tools', '1590941').real_time_duration } context 'with running pipeline' do let(:pipeline_details) do build( :pipeline, :running, { started_at: '2022-12-07T16:21:00Z', finished_at: nil } ) end let(:pipeline_jobs) do [build(:job, :success, finished_at: '2022-12-07T17:21:00Z'), build(:job, finished_at: nil)] end let(:pipeline_bridge_jobs) do [build(:bridge_job, :success, finished_at: '2022-12-07T18:21:00Z'), build(:bridge_job, finished_at: nil)] end before do allow(ReleaseTools::GitlabOpsClient) .to receive(:pipeline) .with('gitlab-org/release/tools', '1590941') .and_return(pipeline_details) allow(ReleaseTools::GitlabOpsClient) .to receive_messages(pipeline_jobs: Gitlab::PaginatedResponse.new(pipeline_jobs), pipeline_bridges: Gitlab::PaginatedResponse.new(pipeline_bridge_jobs)) end it 'returns duration calculated from latest completed job' do expect(real_time_duration).to eq(7200.0) end end context 'with finished_at' do let(:pipeline_details) do build( :pipeline, :success, { started_at: '2022-12-07T16:21:00.557Z', finished_at: '2022-12-07T17:21:00.557Z' } ) end it 'returns duration calculated from finished_at' do allow(ReleaseTools::GitlabOpsClient) .to receive(:pipeline) .with('gitlab-org/release/tools', '1590941') .and_return(pipeline_details) expect(real_time_duration).to eq(3600) end end end describe '#root_attributes' do let(:pipeline_details) do Gitlab::ObjectifiedHash.new({ "id" => 1_590_941, "iid" => 407_638, "project_id" => 130, "sha" => "b1a943132a61095f6284bba885322fc8a5c71309", "ref" => "15.7.202212071620", "status" => "success", "source" => "push", "created_at" => "2022-12-07T16:21:00.557Z", "updated_at" => "2022-12-07T22:52:01.402Z", "web_url" => "https://ops.gitlab.net/gitlab-org/release/tools/-/pipelines/1590941", "before_sha" => "0000000000000000000000000000000000000000", "tag" => true, "yaml_errors" => nil, "user" => { "id" => 49, "username" => "gitlab-release-tools-bot", "name" => "GitLab Release Tools Bot", "state" => "active", "avatar_url" => "https://ops.gitlab.net/uploads/-/system/user/avatar/49/avatar.png", "web_url" => "https://ops.gitlab.net/gitlab-release-tools-bot" }, "started_at" => "2022-12-07T16:21:03.514Z", "finished_at" => "2022-12-07T22:52:01.395Z", "committed_at" => nil, "duration" => 1034, "queued_duration" => 2, "coverage" => nil, "detailed_status" => { "icon" => "status_success", "text" => "passed", "label" => "passed", "group" => "success", "tooltip" => "passed", "has_details" => false, "details_path" => "/gitlab-org/release/tools/-/pipelines/1590941", "illustration" => nil, "favicon" => "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png" } }) end subject(:root_attributes) { described_class.new('ops.gitlab.net', 'gitlab-org/release/tools', '1590941').root_attributes } before do allow(ReleaseTools::GitlabOpsClient).to receive(:pipeline).and_return(pipeline_details) end context 'with started_at available' do it 'returns finished_at' do expect(ReleaseTools::GitlabOpsClient) .to receive(:pipeline) .with('gitlab-org/release/tools', '1590941') expect(root_attributes).to eq( user: "gitlab-release-tools-bot", web_url: "https://ops.gitlab.net/gitlab-org/release/tools/-/pipelines/1590941", created_at: "2022-12-07T16:21:00.557Z", updated_at: "2022-12-07T22:52:01.402Z", status: "success", ref: "15.7.202212071620", duration: 1034, queued_duration: 2, started_at: "2022-12-07T16:21:03.514Z", finished_at: "2022-12-07T22:52:01.395Z" ) end end end describe 'deploy_environment' do subject(:deploy_environment) { described_class.new('ops.gitlab.net', 'gitlab-org/release/tools', '1590941').deploy_environment } it 'calls pipeline_variables' do expect(ReleaseTools::GitlabOpsClient) .to receive(:pipeline_variables) .with('gitlab-org/release/tools', '1590941') .and_return([build(:gitlab_response, key: 'DEPLOY_ENVIRONMENT', value: 'gstg-cny')]) expect(deploy_environment).to eq('gstg-cny') end context 'when DEPLOY_ENVIRONMENT does not exist' do it 'calls pipeline_variables' do expect(ReleaseTools::GitlabOpsClient) .to receive(:pipeline_variables) .with('gitlab-org/release/tools', '1590941') .and_return([]) expect(deploy_environment).to be_nil end end end end