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 ...@@ -103,6 +103,10 @@ module Ci
) )
end end
scope :in_pipelines, ->(pipelines) do
where(pipeline: pipelines)
end
scope :with_existing_job_artifacts, ->(query) do scope :with_existing_job_artifacts, ->(query) do
where('EXISTS (?)', ::Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').merge(query)) where('EXISTS (?)', ::Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').merge(query))
end end
......
...@@ -354,6 +354,14 @@ module Ci ...@@ -354,6 +354,14 @@ module Ci
end end
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 # Returns a Hash containing the latest pipeline for every given
# commit. # commit.
# #
......
...@@ -40,16 +40,31 @@ module Gitlab ...@@ -40,16 +40,31 @@ module Gitlab
private private
def pipeline def successful_pipeline
@pipeline ||= @project.ci_pipelines.latest_successful_for_ref(@ref) @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 end
def raw_coverage def raw_coverage
latest = latest =
if @job.present? 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 else
@project.ci_pipelines.latest_successful_for_ref(@ref) successful_pipeline
end end
latest&.coverage latest&.coverage
......
...@@ -3,13 +3,15 @@ ...@@ -3,13 +3,15 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Badge::Coverage::Report do RSpec.describe Gitlab::Badge::Coverage::Report do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:pipeline) { create(:ci_pipeline, :success, project: 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 let_it_be(:builds) do
[ [
create(:ci_build, :success, pipeline: pipeline, coverage: 40, name: 'first'), create(:ci_build, :success, pipeline: success_pipeline, coverage: 40, created_at: 9.seconds.ago, name: 'coverage'),
create(:ci_build, :success, pipeline: pipeline, coverage: 60) create(:ci_build, :success, pipeline: success_pipeline, coverage: 60, created_at: 8.seconds.ago)
] ]
end end
...@@ -38,28 +40,26 @@ RSpec.describe Gitlab::Badge::Coverage::Report do ...@@ -38,28 +40,26 @@ RSpec.describe Gitlab::Badge::Coverage::Report do
end end
describe '#status' do 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 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) expect(badge.status).to eq(50.00)
end 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 end
context 'with a blank job name' do context 'with a blank job name' do
let(:job_name) { ' ' } 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) expect(badge.status).to eq(50.00)
end end
end end
...@@ -73,11 +73,27 @@ RSpec.describe Gitlab::Badge::Coverage::Report do ...@@ -73,11 +73,27 @@ RSpec.describe Gitlab::Badge::Coverage::Report do
end end
context 'with a matching job name specified' do context 'with a matching job name specified' do
let(:job_name) { 'first' } let(:job_name) { 'coverage' }
it 'returns the pipeline coverage value' do it 'returns the pipeline coverage value' do
expect(badge.status).to eq(40.00) expect(badge.status).to eq(40.00)
end 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 end
end end
...@@ -1972,6 +1972,32 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do ...@@ -1972,6 +1972,32 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end end
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 describe '.latest_successful_for_sha' do
include_context 'with some outdated pipelines' 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