Commit d4cc99bb authored by drew cimino's avatar drew cimino

Reduce scope of Builds query for coverage badge

Only use the latest of each acceptable pipeline status, so build
queries can be scoped to commit_id
parent eed9f5cb
......@@ -103,6 +103,10 @@ module Ci
)
end
scope :in_pipelines, ->(pipelines) do
where(pipeline: pipelines)
end
scope :with_existing_job_artifacts, ->(query) do
where('EXISTS (?)', ::Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').merge(query))
end
......
......@@ -354,6 +354,14 @@ module Ci
end
end
def self.latest_running_for_ref(ref)
newest_first(ref: ref).running.take
end
def self.latest_failed_for_ref(ref)
newest_first(ref: ref).failed.take
end
# Returns a Hash containing the latest pipeline for every given
# commit.
#
......
......@@ -40,16 +40,31 @@ module Gitlab
private
def pipeline
@pipeline ||= @project.ci_pipelines.latest_successful_for_ref(@ref)
def successful_pipeline
@successful_pipeline ||= @project.ci_pipelines.latest_successful_for_ref(@ref)
end
def failed_pipeline
@failed_pipeline ||= @project.ci_pipelines.latest_failed_for_ref(@ref)
end
def running_pipeline
@running_pipeline ||= @project.ci_pipelines.latest_running_for_ref(@ref)
end
def raw_coverage
latest =
if @job.present?
@project.builds.latest.success.for_ref(@ref).by_name(@job).order_id_desc.first
builds = ::Ci::Build
.in_pipelines([successful_pipeline, running_pipeline, failed_pipeline])
.latest
.success
.for_ref(@ref)
.by_name(@job)
builds.max_by(&:created_at)
else
@project.ci_pipelines.latest_successful_for_ref(@ref)
successful_pipeline
end
latest&.coverage
......
......@@ -3,13 +3,15 @@
require 'spec_helper'
RSpec.describe Gitlab::Badge::Coverage::Report do
let_it_be(:project) { create(:project) }
let_it_be(:pipeline) { create(:ci_pipeline, :success, project: project) }
let_it_be(:project) { create(:project) }
let_it_be(:success_pipeline) { create(:ci_pipeline, :success, project: project) }
let_it_be(:running_pipeline) { create(:ci_pipeline, :running, project: project) }
let_it_be(:failure_pipeline) { create(:ci_pipeline, :failed, project: project) }
let_it_be(:builds) do
[
create(:ci_build, :success, pipeline: pipeline, coverage: 40, name: 'first'),
create(:ci_build, :success, pipeline: pipeline, coverage: 60)
create(:ci_build, :success, pipeline: success_pipeline, coverage: 40, created_at: 9.seconds.ago, name: 'coverage'),
create(:ci_build, :success, pipeline: success_pipeline, coverage: 60, created_at: 8.seconds.ago)
]
end
......@@ -38,28 +40,26 @@ RSpec.describe Gitlab::Badge::Coverage::Report do
end
describe '#status' do
before do
allow(badge).to receive(:pipeline).and_return(pipeline)
end
context 'with no pipeline' do
let(:pipeline) { nil }
it 'returns coverage from that job' do
expect(badge.status).to eq(40)
end
end
context 'with no job specified' do
it 'returns the pipeline coverage value' do
it 'returns the most recent successful pipeline coverage value' do
expect(badge.status).to eq(50.00)
end
context 'and no successful pipelines' do
before do
allow(badge).to receive(:successful_pipeline).and_return(nil)
end
it 'returns nil' do
expect(badge.status).to eq(nil)
end
end
end
context 'with a blank job name' do
let(:job_name) { ' ' }
it 'returns the pipeline coverage value' do
it 'returns the latest successful pipeline coverage value' do
expect(badge.status).to eq(50.00)
end
end
......@@ -73,11 +73,27 @@ RSpec.describe Gitlab::Badge::Coverage::Report do
end
context 'with a matching job name specified' do
let(:job_name) { 'first' }
let(:job_name) { 'coverage' }
it 'returns the pipeline coverage value' do
expect(badge.status).to eq(40.00)
end
context 'with a more recent running pipeline' do
let!(:another_build) { create(:ci_build, :success, pipeline: running_pipeline, coverage: 20, created_at: 7.seconds.ago, name: 'coverage') }
it 'returns the running pipeline coverage value' do
expect(badge.status).to eq(20.00)
end
end
context 'with a more recent failed pipeline' do
let!(:another_build) { create(:ci_build, :success, pipeline: failure_pipeline, coverage: 10, created_at: 6.seconds.ago, name: 'coverage') }
it 'returns the failed pipeline coverage value' do
expect(badge.status).to eq(10.00)
end
end
end
end
end
......@@ -1972,6 +1972,32 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
describe '.latest_running_for_ref' do
include_context 'with some outdated pipelines'
let!(:latest_running_pipeline) do
create_pipeline(:running, 'ref', 'D', project)
end
it 'returns the latest running pipeline' do
expect(described_class.latest_running_for_ref('ref'))
.to eq(latest_running_pipeline)
end
end
describe '.latest_failed_for_ref' do
include_context 'with some outdated pipelines'
let!(:latest_failed_pipeline) do
create_pipeline(:failed, 'ref', 'D', project)
end
it 'returns the latest failed pipeline' do
expect(described_class.latest_failed_for_ref('ref'))
.to eq(latest_failed_pipeline)
end
end
describe '.latest_successful_for_sha' do
include_context 'with some outdated pipelines'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment