diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 20492c54729..49a123d488b 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -15,9 +15,6 @@ module Ci scope :with_artifacts, ->() { where.not(artifacts_file: nil) } scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) } scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) } - scope :latest_successful_with_artifacts, ->() do - with_artifacts.success.order(id: :desc) - end scope :manual_actions, ->() { where(when: :manual) } mount_uploader :artifacts_file, ArtifactUploader diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 3646baea88e..63246de4692 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -22,7 +22,7 @@ module Ci # ref can't be HEAD or SHA, can only be branch/tag name scope :latest_successful_for, ->(ref = default_branch) do - where(ref: ref).success.order(id: :desc) + where(ref: ref).success.order(id: :desc).limit(1) end def self.truncate_sha(sha) diff --git a/app/models/project.rb b/app/models/project.rb index 5cfc1d407e4..4fd635abbb3 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -431,8 +431,13 @@ class Project < ActiveRecord::Base # ref can't be HEAD, can only be branch/tag name or SHA def latest_successful_builds_for(ref = default_branch) - builds.joins(:pipeline).merge(pipelines.latest_successful_for(ref)). - latest_successful_with_artifacts + latest_successful_pipeline = pipelines.latest_successful_for(ref).first + + if latest_successful_pipeline + latest_successful_pipeline.builds.with_artifacts.latest + else + builds.none + end end def merge_base_commit(first_commit_id, second_commit_id) diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index b4112d65a34..163b7caf55a 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1148,6 +1148,36 @@ describe Project, models: true do end end + context 'with many builds' do + before do + @pipeline1 = create_pipeline + @pipeline2 = create_pipeline + @build1_p2 = create_build(@pipeline2, 'test') + @build1_p1 = create_build(@pipeline1, 'test') + @build2_p1 = create_build(@pipeline1, 'test2') + @build2_p2 = create_build(@pipeline2, 'test2') + end + + it 'gives the latest build from latest pipeline' do + latest_builds = project.latest_successful_builds_for + + expect(latest_builds).to contain_exactly(@build2_p2, @build1_p2) + end + + def create_pipeline + create(:ci_pipeline, project: project, + sha: project.commit.sha, + ref: project.default_branch, + status: 'success') + end + + def create_build(pipe, name = 'test') + create(:ci_build, :success, :artifacts, + pipeline: pipe, + name: name) + end + end + context 'with multiple pipelines and builds' do shared_examples 'latest successful one' do it 'gives the latest build from latest pipeline' do @@ -1157,27 +1187,6 @@ describe Project, models: true do end end - context 'with all succeeded pipeline' do - before do - old_pipelines = Array.new(3).map do - create(:ci_pipeline, project: project, - sha: project.commit.sha, - ref: project.default_branch, - status: 'success') - end - - # should not give this old build for the latest pipeline - create(:ci_build, :success, :artifacts, pipeline: pipeline) - build - - old_pipelines.reverse_each do |pipe| - create(:ci_build, :success, :artifacts, pipeline: pipe) - end - end - - it_behaves_like 'latest successful one' - end - context 'with some pending pipeline' do before do # make sure pipeline was old, but still the latest success one