Avoid mixing builds from different pipelines:

So we no longer join anything, just find the latest pipeline
and load builds from there to avoid mixing builds.

Thanks Kamil for the help and tests.
This commit is contained in:
Lin Jen-Shin 2016-07-20 21:46:46 +08:00
parent a9f3f3c8c9
commit 9f70abf185
4 changed files with 38 additions and 27 deletions

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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