summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/pipeline/chain/limit/rate_limit.rb
blob: cb02f09f8199553efc884d36b2f1eae6cd3cf289 (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
70
71
72
# frozen_string_literal: true

module Gitlab
  module Ci
    module Pipeline
      module Chain
        module Limit
          class RateLimit < Chain::Base
            include Chain::Helpers

            def perform!
              return unless throttle_enabled?

              # We exclude child-pipelines from the rate limit because they represent
              # sub-pipelines that would otherwise hit the rate limit due to having the
              # same scope (project, user, sha).
              #
              return if pipeline.parent_pipeline?

              if rate_limit_throttled?
                create_log_entry
                error(throttle_message) unless dry_run?
              end
            end

            def break?
              @pipeline.errors.any?
            end

            private

            def rate_limit_throttled?
              ::Gitlab::ApplicationRateLimiter.throttled?(
                :pipelines_create, scope: [project, current_user, command.sha]
              )
            end

            def create_log_entry
              Gitlab::AppJsonLogger.info(
                class: self.class.name,
                namespace_id: project.namespace_id,
                project_id: project.id,
                commit_sha: command.sha,
                current_user_id: current_user.id,
                subscription_plan: project.actual_plan_name,
                message: 'Activated pipeline creation rate limit'
              )
            end

            def throttle_message
              'Too many pipelines created in the last minute. Try again later.'
            end

            def throttle_enabled?
              ::Feature.enabled?(
                :ci_throttle_pipelines_creation,
                project,
                default_enabled: :yaml)
            end

            def dry_run?
              ::Feature.enabled?(
                :ci_throttle_pipelines_creation_dry_run,
                project,
                default_enabled: :yaml)
            end
          end
        end
      end
    end
  end
end