summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzesiek.bizon@gmail.com>2017-01-12 12:45:00 +0100
committerGrzegorz Bizon <grzesiek.bizon@gmail.com>2017-01-12 12:45:00 +0100
commit1d01ffb782a1bf44d5826666590408b24fba2332 (patch)
tree33b142611d70b56e8e8170275948913d1c39e955
parent9f1279184b85927a12b93df00896c57b12373a9a (diff)
downloadgitlab-ce-1d01ffb782a1bf44d5826666590408b24fba2332.tar.gz
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.
-rw-r--r--lib/gitlab/ci/status/factory.rb18
-rw-r--r--spec/lib/gitlab/ci/status/factory_spec.rb97
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