summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/matching/runner_matcher.rb
blob: a729ca8a821cd965bcc731aea26c48b457b3d1e3 (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
65
66
67
68
69
# frozen_string_literal: true

module Gitlab
  module Ci
    module Matching
      ###
      # This class is used to check if a build can be picked by a runner:
      #
      # runner = Ci::Runner.find(id)
      # build  = Ci::Build.find(id)
      # runner.runner_matcher.matches?(build.build_matcher)
      #
      # There are also class level methods to build matchers:
      #
      # `project.builds.build_matchers(project)` returns a distinct collection
      # of build matchers.
      # `Ci::Runner.runner_matchers` returns a distinct collection of runner matchers.
      #
      class RunnerMatcher
        ATTRIBUTES = %i[
          runner_ids
          runner_type
          public_projects_minutes_cost_factor
          private_projects_minutes_cost_factor
          run_untagged
          access_level
          tag_list
        ].freeze

        attr_reader(*ATTRIBUTES)

        def initialize(params)
          ATTRIBUTES.each do |attribute|
            instance_variable_set("@#{attribute}", params.fetch(attribute))
          end
        end

        def matches?(build_matcher)
          ensure_build_matcher_instance!(build_matcher)
          return false if ref_protected? && !build_matcher.protected?

          accepting_tags?(build_matcher)
        end

        def instance_type?
          runner_type.to_sym == :instance_type
        end

        private

        def ref_protected?
          access_level.to_sym == :ref_protected
        end

        def accepting_tags?(build_matcher)
          (run_untagged || build_matcher.has_tags?) && (build_matcher.tag_list - tag_list).empty?
        end

        def ensure_build_matcher_instance!(build_matcher)
          return if build_matcher.is_a?(Matching::BuildMatcher)

          raise ArgumentError, 'only Gitlab::Ci::Matching::BuildMatcher are allowed'
        end
      end
    end
  end
end

Gitlab::Ci::Matching::RunnerMatcher.prepend_mod_with('Gitlab::Ci::Matching::RunnerMatcher')