Commit 478a4137 authored by Kamil Trzciński's avatar Kamil Trzciński

Fix failures

parent 35a464cc
...@@ -30,7 +30,11 @@ module Ci ...@@ -30,7 +30,11 @@ module Ci
end end
def status def status
@status ||= statuses.latest.status @status ||=
Gitlab::Ci::Status::GroupedStatuses
.new(statuses.latest)
.one[:status]
end end
def detailed_status(current_user) def detailed_status(current_user)
...@@ -52,8 +56,11 @@ module Ci ...@@ -52,8 +56,11 @@ module Ci
end end
def has_warnings? def has_warnings?
if @warnings.is_a?(Integer) case @warnings
when Integer
@warnings > 0 @warnings > 0
when TrueClass, FalseClass
@warnings
else else
statuses.latest.failed_but_allowed.any? statuses.latest.failed_but_allowed.any?
end end
......
...@@ -29,6 +29,14 @@ class CommitStatus < ApplicationRecord ...@@ -29,6 +29,14 @@ class CommitStatus < ApplicationRecord
where(allow_failure: true, status: [:failed, :canceled]) where(allow_failure: true, status: [:failed, :canceled])
end end
scope :exclude_ignored, -> do
# We want to ignore failed but allowed to fail jobs.
#
# TODO, we also skip ignored optional manual actions.
where("allow_failure = ? OR status IN (?)",
false, all_state_names - [:failed, :canceled, :manual])
end
scope :latest, -> { where(retried: [false, nil]) } scope :latest, -> { where(retried: [false, nil]) }
scope :retried, -> { where(retried: true) } scope :retried, -> { where(retried: true) }
scope :ordered, -> { order(:name) } scope :ordered, -> { order(:name) }
......
...@@ -58,6 +58,12 @@ module HasStatus ...@@ -58,6 +58,12 @@ module HasStatus
all.pluck(legacy_status_sql).first all.pluck(legacy_status_sql).first
end end
def slow_composite_status
Gitlab::Ci::Status::GroupedStatuses
.new(all)
.one[:status]
end
def started_at def started_at
all.minimum(:started_at) all.minimum(:started_at)
end end
......
...@@ -4,27 +4,25 @@ module Gitlab ...@@ -4,27 +4,25 @@ module Gitlab
module Ci module Ci
module Status module Status
class CompositeStatus class CompositeStatus
attr_reader :warnings
def initialize(all_statuses) def initialize(all_statuses)
@warnings = false @warnings = 0
@status_set = Set.new @status_set = Set.new
build_status_set(all_statuses) build_status_set(all_statuses)
end end
def status def status
case case
when only_of?(:skipped) && warnings? when none? || only_of?(:skipped)
:success warnings? ? :success : :skipped
when only_of?(:skipped) when only_of?(:success, :skipped)
:skipped
when only_of?(:success)
:success :success
when only_of?(:created) when only_of?(:created)
:created :created
when only_of?(:preparing) when only_of?(:preparing)
:preparing :preparing
when only_of?(:success, :skipped)
:success
when only_of?(:success, :skipped, :canceled) when only_of?(:success, :skipped, :canceled)
:canceled :canceled
when only_of?(:created, :skipped, :pending) when only_of?(:created, :skipped, :pending)
...@@ -45,11 +43,15 @@ module Gitlab ...@@ -45,11 +43,15 @@ module Gitlab
end end
def warnings? def warnings?
@warnings @warnings > 0
end end
private private
def none?
@status_set.empty?
end
def any_of?(*names) def any_of?(*names)
names.any? { |name| @status_set.include?(name) } names.any? { |name| @status_set.include?(name) }
end end
...@@ -62,7 +64,7 @@ module Gitlab ...@@ -62,7 +64,7 @@ module Gitlab
def build_status_set(all_statuses) def build_status_set(all_statuses)
all_statuses.each do |status| all_statuses.each do |status|
if status[:allow_failure] && HasStatus::WARNING_STATUSES.include?(status[:status]) if status[:allow_failure] && HasStatus::WARNING_STATUSES.include?(status[:status])
@warnings = true @warnings += 1
else else
@status_set.add(status[:status].to_sym) @status_set.add(status[:status].to_sym)
end end
......
...@@ -70,7 +70,8 @@ module Gitlab ...@@ -70,7 +70,8 @@ module Gitlab
key.merge( key.merge(
status: composite_status.status.to_s, status: composite_status.status.to_s,
warnings: composite_status.warnings?) warnings: composite_status.warnings?
)
end end
end end
end end
......
...@@ -216,7 +216,7 @@ describe Ci::LegacyStage do ...@@ -216,7 +216,7 @@ describe Ci::LegacyStage do
context 'when stage has warnings' do context 'when stage has warnings' do
context 'when using memoized warnings flag' do context 'when using memoized warnings flag' do
context 'when there are warnings' do context 'when there are warnings' do
let(:stage) { build(:ci_stage, warnings: 2) } let(:stage) { build(:ci_stage, warnings: true) }
it 'returns true using memoized value' do it 'returns true using memoized value' do
expect(stage).not_to receive(:statuses) expect(stage).not_to receive(:statuses)
...@@ -225,7 +225,7 @@ describe Ci::LegacyStage do ...@@ -225,7 +225,7 @@ describe Ci::LegacyStage do
end end
context 'when there are no warnings' do context 'when there are no warnings' do
let(:stage) { build(:ci_stage, warnings: 0) } let(:stage) { build(:ci_stage, warnings: false) }
it 'returns false using memoized value' do it 'returns false using memoized value' do
expect(stage).not_to receive(:statuses) expect(stage).not_to receive(:statuses)
...@@ -234,7 +234,7 @@ describe Ci::LegacyStage do ...@@ -234,7 +234,7 @@ describe Ci::LegacyStage do
end end
context 'when number of warnings is not a valid value' do context 'when number of warnings is not a valid value' do
let(:stage) { build(:ci_stage, warnings: true) } let(:stage) { build(:ci_stage, warnings: 'aa') }
it 'calculates statuses using database queries' do it 'calculates statuses using database queries' do
expect(stage).to receive(:statuses).and_call_original expect(stage).to receive(:statuses).and_call_original
......
...@@ -2301,36 +2301,38 @@ describe Ci::Pipeline, :mailer do ...@@ -2301,36 +2301,38 @@ describe Ci::Pipeline, :mailer do
describe '#update_status' do describe '#update_status' do
context 'when pipeline is empty' do context 'when pipeline is empty' do
it 'updates does not change pipeline status' do it 'updates does not change pipeline status' do
expect(pipeline.statuses.latest.status).to be_nil expect(pipeline.statuses.latest.slow_composite_status).to be_nil
expect { pipeline.update_status } expect { pipeline.update_status }
.to change { pipeline.reload.status }.to 'skipped' .to change { pipeline.reload.status }
.from('created')
.to('skipped')
end end
end end
context 'when updating status to pending' do context 'when updating status to pending' do
before do before do
allow(pipeline) create(:ci_build, pipeline: pipeline, status: :running)
.to receive_message_chain(:statuses, :latest, :status)
.and_return(:running)
end end
it 'updates pipeline status to running' do it 'updates pipeline status to running' do
expect { pipeline.update_status } expect { pipeline.update_status }
.to change { pipeline.reload.status }.to 'running' .to change { pipeline.reload.status }
.from('created')
.to('running')
end end
end end
context 'when updating status to scheduled' do context 'when updating status to scheduled' do
before do before do
allow(pipeline) create(:ci_build, pipeline: pipeline, status: :scheduled)
.to receive_message_chain(:statuses, :latest, :status)
.and_return(:scheduled)
end end
it 'updates pipeline status to scheduled' do it 'updates pipeline status to scheduled' do
expect { pipeline.update_status } expect { pipeline.update_status }
.to change { pipeline.reload.status }.to 'scheduled' .to change { pipeline.reload.status }
.from('created')
.to('scheduled')
end end
end end
......
...@@ -130,7 +130,7 @@ describe Ci::Stage, :models do ...@@ -130,7 +130,7 @@ describe Ci::Stage, :models do
context 'when statuses status was not recognized' do context 'when statuses status was not recognized' do
before do before do
allow(stage) allow(stage)
.to receive_message_chain(:statuses, :latest, :status) .to receive(:latest_stage_status)
.and_return(:unknown) .and_return(:unknown)
end end
......
...@@ -298,7 +298,7 @@ describe CommitStatus do ...@@ -298,7 +298,7 @@ describe CommitStatus do
end end
it 'returns a correct compound status' do it 'returns a correct compound status' do
expect(described_class.all.status).to eq 'running' expect(described_class.all.slow_composite_status).to eq 'running'
end end
end end
...@@ -308,7 +308,7 @@ describe CommitStatus do ...@@ -308,7 +308,7 @@ describe CommitStatus do
end end
it 'returns status that indicates success' do it 'returns status that indicates success' do
expect(described_class.all.status).to eq 'success' expect(described_class.all.slow_composite_status).to eq 'success'
end end
end end
...@@ -319,7 +319,7 @@ describe CommitStatus do ...@@ -319,7 +319,7 @@ describe CommitStatus do
end end
it 'returns status according to the scope' do it 'returns status according to the scope' do
expect(described_class.latest.status).to eq 'success' expect(described_class.latest.slow_composite_status).to eq 'success'
end end
end end
end end
......
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