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

ignored_model_columns.rb « danger « tooling - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 50379eed85ccf2842e728c009ce05e3787614ced (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
# frozen_string_literal: true

require_relative 'suggestor'

module Tooling
  module Danger
    module IgnoredModelColumns
      include ::Tooling::Danger::Suggestor

      METHODS = %w[remove_column cleanup_concurrent_column_rename cleanup_conversion_of_integer_to_bigint].freeze
      MIGRATION_FILES_REGEX = %r{^db/(post_)?migrate}
      MIGRATION_METHODS_REGEX = /^\+\s*(.*\.)?(#{METHODS.join('|')})[(\s]/
      UP_METHOD_REGEX = /^.+(def\sup)/
      END_METHOD_REGEX = /^.+(end)/
      DOC_URL = "https://docs.gitlab.com/ee/development/database/avoiding_downtime_in_migrations.html"

      COMMENT = <<~COMMENT.freeze
        Column operations, like [dropping](#{DOC_URL}#dropping-columns), [renaming](#{DOC_URL}#renaming-columns) or
        [primary key conversion](#{DOC_URL}#migrating-integer-primary-keys-to-bigint), require columns to be ignored in
        the model. This step is necessary because Rails caches the columns and re-uses it in various places across the
        application. Please ensure that columns are properly ignored in the model.
      COMMENT

      def add_comment_for_ignored_model_columns
        migration_files.each do |filename|
          add_suggestion(filename: filename, regex: MIGRATION_METHODS_REGEX, comment_text: COMMENT)
        end
      end

      private

      # This method was overwritten to make use of +up_method_lines+.
      # It's necessary to only match lines that are inside the +up+ block in a migration file.
      #
      # @return [Integer, Nil] the line number - only if the line is from within a +up+ method
      def find_line_number(file_lines, searched_line, exclude_indexes: [])
        lines_to_search = up_method_lines(file_lines)

        _, index = file_lines.each_with_index.find do |file_line, index|
          next unless lines_to_search.include?(index)

          file_line == searched_line && !exclude_indexes.include?(index) # rubocop:disable Rails/NegateInclude
        end

        index
      end

      # Return the line numbers from within the up method
      #
      # @example
      #         line 0 def up
      #         line 1   cleanup_conversion_of_integer_to_bigint():my_table, :my_column)
      #         line 2   remove_column(:my_table, :my_column)
      #         line 3   other_method
      #         line 4 end
      #
      #         => [1, 2, 3]
      def up_method_lines(file_lines)
        capture_up_block = false
        up_method_content_lines = []

        file_lines.each_with_index do |content, line_number|
          capture_up_block = false if capture_up_block && END_METHOD_REGEX.match?(content)
          up_method_content_lines << line_number if capture_up_block
          capture_up_block = true if UP_METHOD_REGEX.match?(content)
        end

        up_method_content_lines
      end

      def migration_files
        helper.all_changed_files.grep(MIGRATION_FILES_REGEX)
      end
    end
  end
end