summaryrefslogtreecommitdiff
path: root/lib/gitlab/background_migration/populate_vulnerability_reads.rb
blob: 656c62d9ee5785172f6918f31a0523020292f4b7 (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
# frozen_string_literal: true

module Gitlab
  module BackgroundMigration
    # rubocop:disable Style/Documentation
    class PopulateVulnerabilityReads
      include Gitlab::Database::DynamicModelHelpers

      PAUSE_SECONDS = 0.1

      def perform(start_id, end_id, sub_batch_size)
        vulnerability_model.where(id: start_id..end_id).each_batch(of: sub_batch_size) do |sub_batch|
          first, last = sub_batch.pick(Arel.sql('min(id), max(id)'))
          connection.execute(insert_query(first, last))

          sleep PAUSE_SECONDS
        end

        mark_job_as_succeeded(start_id, end_id, sub_batch_size)
      end

      private

      def vulnerability_model
        define_batchable_model('vulnerabilities', connection: connection)
      end

      def connection
        ApplicationRecord.connection
      end

      def insert_query(start_id, end_id)
        <<~SQL
          INSERT INTO vulnerability_reads (
            vulnerability_id,
            project_id,
            scanner_id,
            report_type,
            severity,
            state,
            has_issues,
            resolved_on_default_branch,
            uuid,
            location_image
          )
          SELECT
            vulnerabilities.id,
            vulnerabilities.project_id,
            vulnerability_scanners.id,
            vulnerabilities.report_type,
            vulnerabilities.severity,
            vulnerabilities.state,
            CASE
              WHEN
                vulnerability_issue_links.vulnerability_id IS NOT NULL
              THEN
                true
              ELSE
                false
            END
            has_issues,
            vulnerabilities.resolved_on_default_branch,
            vulnerability_occurrences.uuid::uuid,
            vulnerability_occurrences.location ->> 'image'
          FROM
            vulnerabilities
          INNER JOIN vulnerability_occurrences ON vulnerability_occurrences.vulnerability_id = vulnerabilities.id
          INNER JOIN vulnerability_scanners ON vulnerability_scanners.id = vulnerability_occurrences.scanner_id
          LEFT JOIN vulnerability_issue_links ON vulnerability_issue_links.vulnerability_id = vulnerabilities.id
          WHERE vulnerabilities.id BETWEEN #{start_id} AND #{end_id}
          ON CONFLICT(vulnerability_id) DO NOTHING;
        SQL
      end

      def mark_job_as_succeeded(*arguments)
        Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
          self.class.name.demodulize,
          arguments
        )
      end
    end
    # rubocop:enable Style/Documentation
  end
end