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

View file

@ -1,18 +1,14 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Factory do
subject do
described_class.new(resource, user)
end
let(:user) { create(:user) }
let(:status) { subject.fabricate! }
let(:status) { factory.fabricate! }
let(:factory) { described_class.new(resource, user) }
context 'when object has a core status' do
HasStatus::AVAILABLE_STATUSES.each do |core_status|
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
expect(status).to be_a(
@ -21,4 +17,91 @@ describe Gitlab::Ci::Status::Factory do
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