From 1d01ffb782a1bf44d5826666590408b24fba2332 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 12 Jan 2017 12:45:00 +0100 Subject: 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. --- lib/gitlab/ci/status/factory.rb | 18 ++++-- spec/lib/gitlab/ci/status/factory_spec.rb | 97 ++++++++++++++++++++++++++++--- 2 files changed, 102 insertions(+), 13 deletions(-) diff --git a/lib/gitlab/ci/status/factory.rb b/lib/gitlab/ci/status/factory.rb index ae9ef895df4..71c54aebcc3 100644 --- a/lib/gitlab/ci/status/factory.rb +++ b/lib/gitlab/ci/status/factory.rb @@ -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 diff --git a/spec/lib/gitlab/ci/status/factory_spec.rb b/spec/lib/gitlab/ci/status/factory_spec.rb index f92a1c149bf..d78d563a9b9 100644 --- a/spec/lib/gitlab/ci/status/factory_spec.rb +++ b/spec/lib/gitlab/ci/status/factory_spec.rb @@ -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 -- cgit v1.2.1