summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/build/rules.rb
blob: a39afee194c50d25a03e02bd8084a4ad6d730780 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# frozen_string_literal: true

module Gitlab
  module Ci
    module Build
      class Rules
        include ::Gitlab::Utils::StrongMemoize

        Result = Struct.new(:when, :start_in, :allow_failure, :variables) do
          def build_attributes(seed_attributes = {})
            {
              when: self.when,
              options: { start_in: start_in }.compact,
              allow_failure: allow_failure,
              yaml_variables: yaml_variables(seed_attributes[:yaml_variables])
            }.compact
          end

          def pass?
            self.when != 'never'
          end

          private

          def yaml_variables(seed_variables)
            return unless variables && seed_variables

            indexed_seed_variables = seed_variables.deep_dup.index_by { |var| var[:key] }

            variables.each_with_object(indexed_seed_variables) do |var, hash|
              hash[var[0].to_s] = { key: var[0].to_s, value: var[1], public: true }
            end.values
          end
        end

        def initialize(rule_hashes, default_when:)
          @rule_list    = Rule.fabricate_list(rule_hashes)
          @default_when = default_when
        end

        def evaluate(pipeline, context)
          if @rule_list.nil?
            Result.new(@default_when)
          elsif matched_rule = match_rule(pipeline, context)
            Result.new(
              matched_rule.attributes[:when] || @default_when,
              matched_rule.attributes[:start_in],
              matched_rule.attributes[:allow_failure],
              matched_rule.attributes[:variables]
            )
          else
            Result.new('never')
          end
        end

        private

        def match_rule(pipeline, context)
          @rule_list.find { |rule| rule.matches?(pipeline, context) }
        end
      end
    end
  end
end