Merge branch 'show-commit-status-from-latest-pipeline' into 'master'

Show commit status from latest pipeline

Show commit status from latest pipeline rather than compound status from all pipelines.

Closes #20560

See merge request !7333
This commit is contained in:
Grzegorz Bizon 2016-12-15 19:48:00 +00:00
commit f3c2855f8e
8 changed files with 105 additions and 33 deletions

View File

@ -88,8 +88,24 @@ module Ci
end end
# ref can't be HEAD or SHA, can only be branch/tag name # ref can't be HEAD or SHA, can only be branch/tag name
scope :latest, ->(ref = nil) do
max_id = unscope(:select)
.select("max(#{quoted_table_name}.id)")
.group(:ref, :sha)
if ref
where(id: max_id, ref: ref)
else
where(id: max_id)
end
end
def self.latest_status(ref = nil)
latest(ref).status
end
def self.latest_successful_for(ref) def self.latest_successful_for(ref)
where(ref: ref).order(id: :desc).success.first success.latest(ref).first
end end
def self.truncate_sha(sha) def self.truncate_sha(sha)

View File

@ -228,13 +228,9 @@ class Commit
def status(ref = nil) def status(ref = nil)
@statuses ||= {} @statuses ||= {}
if @statuses.key?(ref) return @statuses[ref] if @statuses.key?(ref)
@statuses[ref]
elsif ref @statuses[ref] = pipelines.latest_status(ref)
@statuses[ref] = pipelines.where(ref: ref).status
else
@statuses[ref] = pipelines.status
end
end end
def revert_branch_name def revert_branch_name
@ -270,7 +266,7 @@ class Commit
@merged_merge_request_hash ||= Hash.new do |hash, user| @merged_merge_request_hash ||= Hash.new do |hash, user|
hash[user] = merged_merge_request_no_cache(user) hash[user] = merged_merge_request_no_cache(user)
end end
@merged_merge_request_hash[current_user] @merged_merge_request_hash[current_user]
end end

View File

@ -1,13 +1,13 @@
module Ci module Ci
class ImageForBuildService class ImageForBuildService
def execute(project, opts) def execute(project, opts)
sha = opts[:sha] || ref_sha(project, opts[:ref]) ref = opts[:ref]
sha = opts[:sha] || ref_sha(project, ref)
pipelines = project.pipelines.where(sha: sha) pipelines = project.pipelines.where(sha: sha)
pipelines = pipelines.where(ref: opts[:ref]) if opts[:ref]
image_name = image_for_status(pipelines.status)
image_name = image_for_status(pipelines.latest_status(ref))
image_path = Rails.root.join('public/ci', image_name) image_path = Rails.root.join('public/ci', image_name)
OpenStruct.new(path: image_path, name: image_name) OpenStruct.new(path: image_path, name: image_name)
end end

View File

@ -0,0 +1,4 @@
---
title: Show commit status from latest pipeline
merge_request: 7333
author:

View File

@ -20,8 +20,8 @@ module Gitlab
def status def status
@project.pipelines @project.pipelines
.where(sha: @sha, ref: @ref) .where(sha: @sha)
.status || 'unknown' .latest_status(@ref) || 'unknown'
end end
def metadata def metadata

View File

@ -69,8 +69,8 @@ describe Gitlab::Badge::Build::Status do
new_build.success! new_build.success!
end end
it 'reports the compound status' do it 'does not take outdated pipeline into account' do
expect(badge.status).to eq 'failed' expect(badge.status).to eq 'success'
end end
end end
end end

View File

@ -381,6 +381,65 @@ describe Ci::Pipeline, models: true do
end end
end end
shared_context 'with some outdated pipelines' do
before do
create_pipeline(:canceled, 'ref', 'A')
create_pipeline(:success, 'ref', 'A')
create_pipeline(:failed, 'ref', 'B')
create_pipeline(:skipped, 'feature', 'C')
end
def create_pipeline(status, ref, sha)
create(:ci_empty_pipeline, status: status, ref: ref, sha: sha)
end
end
describe '.latest' do
include_context 'with some outdated pipelines'
context 'when no ref is specified' do
let(:pipelines) { described_class.latest.all }
it 'returns the latest pipeline for the same ref and different sha' do
expect(pipelines.map(&:sha)).to contain_exactly('A', 'B', 'C')
expect(pipelines.map(&:status)).
to contain_exactly('success', 'failed', 'skipped')
end
end
context 'when ref is specified' do
let(:pipelines) { described_class.latest('ref').all }
it 'returns the latest pipeline for ref and different sha' do
expect(pipelines.map(&:sha)).to contain_exactly('A', 'B')
expect(pipelines.map(&:status)).
to contain_exactly('success', 'failed')
end
end
end
describe '.latest_status' do
include_context 'with some outdated pipelines'
context 'when no ref is specified' do
let(:latest_status) { described_class.latest_status }
it 'returns the latest status for the same ref and different sha' do
expect(latest_status).to eq(described_class.latest.status)
expect(latest_status).to eq('failed')
end
end
context 'when ref is specified' do
let(:latest_status) { described_class.latest_status('ref') }
it 'returns the latest status for ref and different sha' do
expect(latest_status).to eq(described_class.latest_status('ref'))
expect(latest_status).to eq('failed')
end
end
end
describe '#status' do describe '#status' do
let!(:build) { create(:ci_build, :created, pipeline: pipeline, name: 'test') } let!(:build) { create(:ci_build, :created, pipeline: pipeline, name: 'test') }

View File

@ -213,23 +213,19 @@ eos
end end
describe '#status' do describe '#status' do
context 'without arguments for compound status' do context 'without ref argument' do
shared_examples 'giving the status from pipeline' do before do
it do %w[success failed created pending].each do |status|
expect(commit.status).to eq(Ci::Pipeline.status) create(:ci_empty_pipeline,
project: project,
sha: commit.sha,
status: status)
end end
end end
context 'with pipelines' do it 'gives compound status from latest pipelines' do
let!(:pipeline) do expect(commit.status).to eq(Ci::Pipeline.latest_status)
create(:ci_empty_pipeline, project: project, sha: commit.sha) expect(commit.status).to eq('pending')
end
it_behaves_like 'giving the status from pipeline'
end
context 'without pipelines' do
it_behaves_like 'giving the status from pipeline'
end end
end end
@ -255,8 +251,9 @@ eos
expect(commit.status('fix')).to eq(pipeline_from_fix.status) expect(commit.status('fix')).to eq(pipeline_from_fix.status)
end end
it 'gives compound status if ref is nil' do it 'gives compound status from latest pipelines if ref is nil' do
expect(commit.status(nil)).to eq(commit.status) expect(commit.status(nil)).to eq(Ci::Pipeline.latest_status)
expect(commit.status(nil)).to eq('failed')
end end
end end
end end