Make it possible to combine extended CI/CD statuses

This commit also makes it possible to configure exclusive groups.
There can be only one detailed status matched within an exclusive group,
which is important from the performance perspective.
This commit is contained in:
Grzegorz Bizon 2017-01-12 12:45:00 +01:00
parent 9f1279184b
commit 1d01ffb782
2 changed files with 102 additions and 13 deletions

View file

@ -8,10 +8,12 @@ module Gitlab
end end
def fabricate! def fabricate!
if extended_status if extended_statuses.none?
extended_status.new(core_status)
else
core_status core_status
else
extended_statuses.inject(core_status) do |status, extended|
extended.new(status)
end
end end
end end
@ -36,10 +38,14 @@ module Gitlab
.extend(self.class.common_helpers) .extend(self.class.common_helpers)
end end
def extended_status def extended_statuses
@extended ||= self.class.extended_statuses.find do |status| return @extended_statuses if defined?(@extended_statuses)
status.matches?(@subject, @user)
groups = self.class.extended_statuses.map do |group|
Array(group).find { |status| status.matches?(@subject, @user) }
end end
@extended_statuses = groups.flatten.compact
end end
end end
end end

View file

@ -1,18 +1,14 @@
require 'spec_helper' require 'spec_helper'
describe Gitlab::Ci::Status::Factory do describe Gitlab::Ci::Status::Factory do
subject do
described_class.new(resource, user)
end
let(:user) { create(:user) } let(:user) { create(:user) }
let(:status) { factory.fabricate! }
let(:status) { subject.fabricate! } let(:factory) { described_class.new(resource, user) }
context 'when object has a core status' do context 'when object has a core status' do
HasStatus::AVAILABLE_STATUSES.each do |core_status| HasStatus::AVAILABLE_STATUSES.each do |core_status|
context "when core status is #{core_status}" do context "when core status is #{core_status}" do
let(:resource) { double(status: core_status) } let(:resource) { double('resource', status: core_status) }
it "fabricates a core status #{core_status}" do it "fabricates a core status #{core_status}" do
expect(status).to be_a( expect(status).to be_a(
@ -21,4 +17,91 @@ describe Gitlab::Ci::Status::Factory do
end end
end end
end end
context 'when resource supports multiple extended statuses' do
let(:resource) { double('resource', status: :success) }
let(:first_extended_status) do
Class.new(SimpleDelegator) do
def first_method
'first return value'
end
def second_method
'second return value'
end
def self.matches?(*)
true
end
end
end
let(:second_extended_status) do
Class.new(SimpleDelegator) do
def first_method
'decorated return value'
end
def third_method
'third return value'
end
def self.matches?(*)
true
end
end
end
shared_examples 'compound decorator factory' do
it 'fabricates compound decorator' do
expect(status.first_method).to eq 'decorated return value'
expect(status.second_method).to eq 'second return value'
expect(status.third_method).to eq 'third return value'
end
it 'delegates to core status' do
expect(status.text).to eq 'passed'
end
it 'latest matches status becomes a status name' do
expect(status.class).to eq second_extended_status
end
end
context 'when exclusive statuses are matches' do
before do
allow(described_class).to receive(:extended_statuses)
.and_return([[first_extended_status, second_extended_status]])
end
it 'fabricates compound decorator' do
expect(status.first_method).to eq 'first return value'
expect(status.second_method).to eq 'second return value'
expect(status).not_to respond_to(:third_method)
end
it 'delegates to core status' do
expect(status.text).to eq 'passed'
end
end
context 'when exclusive statuses are not matched' do
before do
allow(described_class).to receive(:extended_statuses)
.and_return([[first_extended_status], [second_extended_status]])
end
it_behaves_like 'compound decorator factory'
end
context 'when using simplified status grouping' do
before do
allow(described_class).to receive(:extended_statuses)
.and_return([first_extended_status, second_extended_status])
end
it_behaves_like 'compound decorator factory'
end
end
end end