summaryrefslogtreecommitdiff
path: root/lib/gitlab/background_migration/migrate_legacy_artifacts.rb
blob: 4377ec2987c3e9f75a9f9b2a6867c5cd787badd8 (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
132
# frozen_string_literal: true
# rubocop:disable Metrics/ClassLength

module Gitlab
  module BackgroundMigration
    ##
    # The class to migrate job artifacts from `ci_builds` to `ci_job_artifacts`
    class MigrateLegacyArtifacts
      FILE_LOCAL_STORE = 1 # equal to ObjectStorage::Store::LOCAL
      ARCHIVE_FILE_TYPE = 1 # equal to Ci::JobArtifact.file_types['archive']
      METADATA_FILE_TYPE = 2 # equal to Ci::JobArtifact.file_types['metadata']
      LEGACY_PATH_FILE_LOCATION = 1 # equal to Ci::JobArtifact.file_location['legacy_path']

      def perform(start_id, stop_id)
        ActiveRecord::Base.transaction do
          insert_archives(start_id, stop_id)
          insert_metadatas(start_id, stop_id)
          delete_legacy_artifacts(start_id, stop_id)
        end
      end

      private

      def insert_archives(start_id, stop_id)
        ActiveRecord::Base.connection.execute <<~SQL
          INSERT INTO
              ci_job_artifacts (
                  project_id,
                  job_id,
                  expire_at,
                  file_location,
                  created_at,
                  updated_at,
                  file,
                  size,
                  file_store,
                  file_type
              )
          SELECT
              project_id,
              id,
              artifacts_expire_at #{add_missing_db_timezone},
              #{LEGACY_PATH_FILE_LOCATION},
              created_at #{add_missing_db_timezone},
              created_at #{add_missing_db_timezone},
              artifacts_file,
              artifacts_size,
              COALESCE(artifacts_file_store, #{FILE_LOCAL_STORE}),
              #{ARCHIVE_FILE_TYPE}
          FROM
              ci_builds
          WHERE
              id BETWEEN #{start_id.to_i} AND #{stop_id.to_i}
              AND artifacts_file <> ''
              AND NOT EXISTS (
                  SELECT
                      1
                  FROM
                      ci_job_artifacts
                  WHERE
                      ci_builds.id = ci_job_artifacts.job_id
                      AND ci_job_artifacts.file_type = #{ARCHIVE_FILE_TYPE})
        SQL
      end

      def insert_metadatas(start_id, stop_id)
        ActiveRecord::Base.connection.execute <<~SQL
          INSERT INTO
              ci_job_artifacts (
                  project_id,
                  job_id,
                  expire_at,
                  file_location,
                  created_at,
                  updated_at,
                  file,
                  size,
                  file_store,
                  file_type
              )
          SELECT
              project_id,
              id,
              artifacts_expire_at #{add_missing_db_timezone},
              #{LEGACY_PATH_FILE_LOCATION},
              created_at #{add_missing_db_timezone},
              created_at #{add_missing_db_timezone},
              artifacts_metadata,
              NULL,
              COALESCE(artifacts_metadata_store, #{FILE_LOCAL_STORE}),
              #{METADATA_FILE_TYPE}
          FROM
              ci_builds
          WHERE
              id BETWEEN #{start_id.to_i} AND #{stop_id.to_i}
              AND artifacts_file <> ''
              AND artifacts_metadata <> ''
              AND NOT EXISTS (
                  SELECT
                      1
                  FROM
                      ci_job_artifacts
                  WHERE
                      ci_builds.id = ci_job_artifacts.job_id
                      AND ci_job_artifacts.file_type = #{METADATA_FILE_TYPE})
        SQL
      end

      def delete_legacy_artifacts(start_id, stop_id)
        ActiveRecord::Base.connection.execute <<~SQL
          UPDATE
              ci_builds
          SET
              artifacts_file = NULL,
              artifacts_file_store = NULL,
              artifacts_size = NULL,
              artifacts_metadata = NULL,
              artifacts_metadata_store = NULL
          WHERE
              id BETWEEN #{start_id.to_i} AND #{stop_id.to_i}
              AND artifacts_file <> ''
        SQL
      end

      def add_missing_db_timezone
        return '' unless Gitlab::Database.postgresql?

        'at time zone \'UTC\''
      end
    end
  end
end