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

20200526231421_update_index_approval_rule_name_for_code_owners_rule_type.rb « migrate « db - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2483ff7f8facfc74c4c1448210e03c059ffe3bd3 (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
# frozen_string_literal: true

class UpdateIndexApprovalRuleNameForCodeOwnersRuleType < ActiveRecord::Migration[6.0]
  include Gitlab::Database::MigrationHelpers

  DOWNTIME = false

  disable_ddl_transaction!

  LEGACY_INDEX_NAME_RULE_TYPE   = "index_approval_rule_name_for_code_owners_rule_type"
  LEGACY_INDEX_NAME_CODE_OWNERS = "approval_rule_name_index_for_code_owners"

  SECTIONAL_INDEX_NAME = "index_approval_rule_name_for_sectional_code_owners_rule_type"

  CODE_OWNER_RULE_TYPE = 2

  def up
    unless index_exists_by_name?(:approval_merge_request_rules, SECTIONAL_INDEX_NAME)
      # Ensure only 1 code_owner rule with the same name and section per merge_request
      #
      add_concurrent_index(
        :approval_merge_request_rules,
        [:merge_request_id, :name, :section],
        unique: true,
        where: "rule_type = #{CODE_OWNER_RULE_TYPE}",
        name: SECTIONAL_INDEX_NAME
      )
    end

    remove_concurrent_index_by_name :approval_merge_request_rules, LEGACY_INDEX_NAME_RULE_TYPE
    remove_concurrent_index_by_name :approval_merge_request_rules, LEGACY_INDEX_NAME_CODE_OWNERS

    add_concurrent_index(
      :approval_merge_request_rules,
      [:merge_request_id, :name],
      unique: true,
      where: "rule_type = #{CODE_OWNER_RULE_TYPE} AND section IS NULL",
      name: LEGACY_INDEX_NAME_RULE_TYPE
    )

    add_concurrent_index(
      :approval_merge_request_rules,
      [:merge_request_id, :code_owner, :name],
      unique: true,
      where: "code_owner = true AND section IS NULL",
      name: LEGACY_INDEX_NAME_CODE_OWNERS
    )
  end

  def down
    # In a rollback situation, we can't guarantee that there will not be
    #   records that were allowed under the more specific SECTIONAL_INDEX_NAME
    #   index but would cause uniqueness violations under both the
    #   LEGACY_INDEX_NAME_RULE_TYPE and LEGACY_INDEX_NAME_CODE_OWNERS indices.
    #   Therefore, we need to first find all the MergeRequests with
    #   ApprovalMergeRequestRules that would violate these "new" indices and
    #   delete those approval rules, then create the new index, then finally
    #   recreate the approval rules for those merge requests.
    #

    # First, find all MergeRequests with ApprovalMergeRequestRules that will
    #   violate the new index.
    #
    if Gitlab.ee?
      merge_request_ids = ApprovalMergeRequestRule
        .select(:merge_request_id)
        .where(rule_type: CODE_OWNER_RULE_TYPE)
        .group(:merge_request_id, :rule_type, :name)
        .includes(:merge_request)
        .having("count(*) > 1")
        .collect(&:merge_request_id)

      # Delete ALL their code_owner approval rules
      #
      merge_request_ids.each_slice(10) do |ids|
        ApprovalMergeRequestRule.where(merge_request_id: ids).code_owner.delete_all
      end
    end

    # Remove legacy partial indices that only apply to `section IS NULL` records
    #
    remove_concurrent_index_by_name :approval_merge_request_rules, LEGACY_INDEX_NAME_RULE_TYPE
    remove_concurrent_index_by_name :approval_merge_request_rules, LEGACY_INDEX_NAME_CODE_OWNERS

    # Reconstruct original "legacy" indices
    #
    add_concurrent_index(
      :approval_merge_request_rules,
      [:merge_request_id, :name],
      unique: true,
      where: "rule_type = #{CODE_OWNER_RULE_TYPE}",
      name: LEGACY_INDEX_NAME_RULE_TYPE
    )

    add_concurrent_index(
      :approval_merge_request_rules,
      [:merge_request_id, :code_owner, :name],
      unique: true,
      where: "code_owner = true",
      name: LEGACY_INDEX_NAME_CODE_OWNERS
    )

    # MergeRequest::SyncCodeOwnerApprovalRules recreates the code_owner rules
    #   from scratch, adding them to the index. Duplicates will be rejected.
    #
    if Gitlab.ee?
      merge_request_ids.each_slice(10) do |ids|
        MergeRequest.where(id: ids).each do |merge_request|
          MergeRequests::SyncCodeOwnerApprovalRules.new(merge_request).execute
        end
      end
    end

    remove_concurrent_index_by_name :approval_merge_request_rules, SECTIONAL_INDEX_NAME
  end
end