Welcome to mirror list, hosted at ThFree Co, Russian Federation.

backfill_default_branch_protection_namespace_setting.rb « background_migration « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 8da29a61d6114f8ee97d70df9d82e89682d1a06d (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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# frozen_string_literal: true

module Gitlab
  module BackgroundMigration
    # This class is used to update the default_branch_protection_defaults column
    # for user namespaces of the namespace_settings table.
    class BackfillDefaultBranchProtectionNamespaceSetting < BatchedMigrationJob
      operation_name :set_default_branch_protection_defaults
      feature_category :database

      # Migration only version of `namespaces` table
      class Namespace < ::ApplicationRecord
        self.table_name = 'namespaces'
        self.inheritance_column = :_type_disabled

        has_one :namespace_setting,
          class_name: '::Gitlab::BackgroundMigration::BackfillDefaultBranchProtectionNamespaceSetting::NamespaceSetting'
      end

      # Migration only version of `namespace_settings` table
      class NamespaceSetting < ::ApplicationRecord
        self.table_name = 'namespace_settings'
        belongs_to :namespace,
          class_name: '::Gitlab::BackgroundMigration::BackfillDefaultBranchProtectionNamespaceSetting::Namespace'
      end

      # Migration only version of Gitlab::Access:BranchProtection application code.
      class BranchProtection
        attr_reader :level

        def initialize(level)
          @level = level
        end

        PROTECTION_NONE = 0
        PROTECTION_DEV_CAN_PUSH = 1
        PROTECTION_FULL = 2
        PROTECTION_DEV_CAN_MERGE = 3
        PROTECTION_DEV_CAN_INITIAL_PUSH = 4

        DEVELOPER = 30
        MAINTAINER = 40

        def to_hash
          case level
          when PROTECTION_NONE
            self.class.protection_none
          when PROTECTION_DEV_CAN_PUSH
            self.class.protection_partial
          when PROTECTION_FULL
            self.class.protected_fully
          when PROTECTION_DEV_CAN_MERGE
            self.class.protected_against_developer_pushes
          when PROTECTION_DEV_CAN_INITIAL_PUSH
            self.class.protected_after_initial_push
          end
        end

        class << self
          def protection_none
            {
              allowed_to_push: [{ 'access_level' => DEVELOPER }],
              allowed_to_merge: [{ 'access_level' => DEVELOPER }],
              allow_force_push: true
            }
          end

          def protection_partial
            protection_none.merge(allow_force_push: false)
          end

          def protected_fully
            {
              allowed_to_push: [{ 'access_level' => MAINTAINER }],
              allowed_to_merge: [{ 'access_level' => MAINTAINER }],
              allow_force_push: false
            }
          end

          def protected_against_developer_pushes
            {
              allowed_to_push: [{ 'access_level' => MAINTAINER }],
              allowed_to_merge: [{ 'access_level' => DEVELOPER }],
              allow_force_push: true
            }
          end

          def protected_after_initial_push
            {
              allowed_to_push: [{ 'access_level' => MAINTAINER }],
              allowed_to_merge: [{ 'access_level' => DEVELOPER }],
              allow_force_push: true,
              developer_can_initial_push: true
            }
          end
        end
      end

      def perform
        each_sub_batch do |sub_batch|
          update_default_protection_branch_defaults(sub_batch)
        end
      end

      private

      def update_default_protection_branch_defaults(batch)
        namespace_settings = NamespaceSetting.where(namespace_id: batch.pluck(:namespace_id)).includes(:namespace)

        values_list = namespace_settings.map do |namespace_setting|
          level = namespace_setting.namespace.default_branch_protection.to_i
          value = BranchProtection.new(level).to_hash.to_json
          "(#{namespace_setting.namespace_id}, '#{value}'::jsonb)"
        end.join(", ")

        sql = <<~SQL
          WITH new_values (namespace_id, default_branch_protection_defaults) AS (
            VALUES
              #{values_list}
          )
          UPDATE namespace_settings
          SET default_branch_protection_defaults = new_values.default_branch_protection_defaults
          FROM new_values
          WHERE namespace_settings.namespace_id = new_values.namespace_id;
        SQL

        connection.execute(sql)
      end
    end
  end
end