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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-08-20 21:42:06 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-08-20 21:42:06 +0300
commit6e4e1050d9dba2b7b2523fdd1768823ab85feef4 (patch)
tree78be5963ec075d80116a932011d695dd33910b4e /lib/gitlab/background_migration
parent1ce776de4ae122aba3f349c02c17cebeaa8ecf07 (diff)
Add latest changes from gitlab-org/gitlab@13-3-stable-ee
Diffstat (limited to 'lib/gitlab/background_migration')
-rw-r--r--lib/gitlab/background_migration/archive_legacy_traces.rb21
-rw-r--r--lib/gitlab/background_migration/backfill_designs_relative_position.rb15
-rw-r--r--lib/gitlab/background_migration/backfill_hashed_project_repositories.rb15
-rw-r--r--lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config.rb213
-rw-r--r--lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb25
-rw-r--r--lib/gitlab/background_migration/fill_file_store_job_artifact.rb19
-rw-r--r--lib/gitlab/background_migration/fill_file_store_lfs_object.rb19
-rw-r--r--lib/gitlab/background_migration/fill_store_upload.rb20
-rw-r--r--lib/gitlab/background_migration/fix_cross_project_label_links.rb140
-rw-r--r--lib/gitlab/background_migration/migrate_build_stage.rb48
-rw-r--r--lib/gitlab/background_migration/migrate_build_stage_id_reference.rb22
-rw-r--r--lib/gitlab/background_migration/migrate_stage_index.rb35
-rw-r--r--lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table.rb82
-rw-r--r--lib/gitlab/background_migration/populate_personal_snippet_statistics.rb49
-rw-r--r--lib/gitlab/background_migration/populate_untracked_uploads.rb111
-rw-r--r--lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb190
-rw-r--r--lib/gitlab/background_migration/prepare_untracked_uploads.rb173
-rw-r--r--lib/gitlab/background_migration/remove_restricted_todos.rb158
-rw-r--r--lib/gitlab/background_migration/set_confidential_note_events_on_services.rb26
-rw-r--r--lib/gitlab/background_migration/set_confidential_note_events_on_webhooks.rb26
-rw-r--r--lib/gitlab/background_migration/set_merge_request_diff_files_count.rb28
-rw-r--r--lib/gitlab/background_migration/set_null_external_diff_store_to_local_value.rb24
-rw-r--r--lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb24
-rw-r--r--lib/gitlab/background_migration/user_mentions/create_resource_user_mention.rb12
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/commit.rb1
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/design_management/design.rb1
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/epic.rb1
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/merge_request.rb1
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/note.rb1
29 files changed, 174 insertions, 1326 deletions
diff --git a/lib/gitlab/background_migration/archive_legacy_traces.rb b/lib/gitlab/background_migration/archive_legacy_traces.rb
deleted file mode 100644
index 79f38aed9f1..00000000000
--- a/lib/gitlab/background_migration/archive_legacy_traces.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class ArchiveLegacyTraces
- def perform(start_id, stop_id)
- # This background migration directly refers to ::Ci::Build model which is defined in application code.
- # In general, migration code should be isolated as much as possible in order to be idempotent.
- # However, `archive!` method is too complicated to be replicated by coping its subsequent code.
- # So we chose a way to use ::Ci::Build directly and we don't change the `archive!` method until 11.1
- ::Ci::Build.finished.without_archived_trace
- .where(id: start_id..stop_id).find_each do |build|
- build.trace.archive!
- rescue => e
- Rails.logger.error "Failed to archive live trace. id: #{build.id} message: #{e.message}" # rubocop:disable Gitlab/RailsLogger
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_designs_relative_position.rb b/lib/gitlab/background_migration/backfill_designs_relative_position.rb
new file mode 100644
index 00000000000..efbb1b950ad
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_designs_relative_position.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This migration is not needed anymore and was disabled, because we're now
+ # also backfilling design positions immediately before moving a design.
+ #
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39555
+ class BackfillDesignsRelativePosition
+ def perform(issue_ids)
+ # no-op
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/backfill_hashed_project_repositories.rb b/lib/gitlab/background_migration/backfill_hashed_project_repositories.rb
deleted file mode 100644
index a6194616663..00000000000
--- a/lib/gitlab/background_migration/backfill_hashed_project_repositories.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Class that will fill the project_repositories table for projects that
- # are on hashed storage and an entry is is missing in this table.
- class BackfillHashedProjectRepositories < BackfillProjectRepositories
- private
-
- def projects
- Project.on_hashed_storage
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config.rb b/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config.rb
deleted file mode 100644
index 2a079060380..00000000000
--- a/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config.rb
+++ /dev/null
@@ -1,213 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This module is used to write the full path of all projects to
- # the git repository config file.
- # Storing the full project path in the git config allows admins to
- # easily identify a project when it is using hashed storage.
- module BackfillProjectFullpathInRepoConfig
- OrphanedNamespaceError = Class.new(StandardError)
-
- module Storage
- # Class that returns the disk path for a project using hashed storage
- class Hashed
- attr_accessor :project
-
- ROOT_PATH_PREFIX = '@hashed'
-
- def initialize(project)
- @project = project
- end
-
- def disk_path
- "#{ROOT_PATH_PREFIX}/#{disk_hash[0..1]}/#{disk_hash[2..3]}/#{disk_hash}"
- end
-
- def disk_hash
- @disk_hash ||= Digest::SHA2.hexdigest(project.id.to_s) if project.id
- end
- end
-
- # Class that returns the disk path for a project using legacy storage
- class LegacyProject
- attr_accessor :project
-
- def initialize(project)
- @project = project
- end
-
- def disk_path
- project.full_path
- end
- end
- end
-
- # Concern used by Project and Namespace to determine the full
- # route to the project
- module Routable
- extend ActiveSupport::Concern
-
- def full_path
- @full_path ||= build_full_path
- end
-
- def build_full_path
- return path unless has_parent?
-
- raise OrphanedNamespaceError if parent.nil?
-
- parent.full_path + '/' + path
- end
-
- def has_parent?
- read_attribute(association(:parent).reflection.foreign_key)
- end
- end
-
- # Class used to interact with repository using Gitaly
- class Repository
- attr_reader :storage
-
- def initialize(storage, relative_path)
- @storage = storage
- @relative_path = relative_path
- end
-
- def gitaly_repository
- Gitaly::Repository.new(storage_name: @storage, relative_path: @relative_path)
- end
- end
-
- # Namespace can be a user or group. It can be the root or a
- # child of another namespace.
- class Namespace < ActiveRecord::Base
- self.table_name = 'namespaces'
- self.inheritance_column = nil
-
- include Routable
-
- belongs_to :parent, class_name: 'Namespace', inverse_of: 'namespaces'
- has_many :projects, inverse_of: :parent
- has_many :namespaces, inverse_of: :parent
- end
-
- # Project is where the repository (etc.) is stored
- class Project < ActiveRecord::Base
- self.table_name = 'projects'
-
- include Routable
- include EachBatch
-
- FULLPATH_CONFIG_KEY = 'gitlab.fullpath'
-
- belongs_to :parent, class_name: 'Namespace', foreign_key: :namespace_id, inverse_of: 'projects'
- delegate :disk_path, to: :storage
-
- def add_fullpath_config
- entries = { FULLPATH_CONFIG_KEY => full_path }
-
- repository_service.set_config(entries)
- end
-
- def remove_fullpath_config
- repository_service.delete_config([FULLPATH_CONFIG_KEY])
- end
-
- def cleanup_repository
- repository_service.cleanup
- end
-
- def storage
- @storage ||=
- if hashed_storage?
- Storage::Hashed.new(self)
- else
- Storage::LegacyProject.new(self)
- end
- end
-
- def hashed_storage?
- self.storage_version && self.storage_version >= 1
- end
-
- def repository
- @repository ||= Repository.new(repository_storage, disk_path + '.git')
- end
-
- def repository_service
- @repository_service ||= Gitlab::GitalyClient::RepositoryService.new(repository)
- end
- end
-
- # Base class for Up and Down migration classes
- class BackfillFullpathMigration
- RETRY_DELAY = 15.minutes
- MAX_RETRIES = 2
-
- # Base class for retrying one project
- class BaseRetryOne
- def perform(project_id, retry_count)
- project = Project.find(project_id)
-
- return unless project
-
- migration_class.new.safe_perform_one(project, retry_count)
- end
- end
-
- def perform(start_id, end_id)
- Project.includes(:parent).where(id: start_id..end_id).each do |project|
- safe_perform_one(project)
- end
- end
-
- def safe_perform_one(project, retry_count = 0)
- perform_one(project)
- rescue GRPC::NotFound, GRPC::InvalidArgument, OrphanedNamespaceError
- nil
- rescue GRPC::BadStatus
- schedule_retry(project, retry_count + 1) if retry_count < MAX_RETRIES
- end
-
- def schedule_retry(project, retry_count)
- # Constants provided to BackgroundMigrationWorker must be within the
- # scope of Gitlab::BackgroundMigration
- retry_class_name = self.class::RetryOne.name.sub('Gitlab::BackgroundMigration::', '')
-
- BackgroundMigrationWorker.perform_in(RETRY_DELAY, retry_class_name, [project.id, retry_count])
- end
- end
-
- # Class to add the fullpath to the git repo config
- class Up < BackfillFullpathMigration
- # Class used to retry
- class RetryOne < BaseRetryOne
- def migration_class
- Up
- end
- end
-
- def perform_one(project)
- project.cleanup_repository
- project.add_fullpath_config
- end
- end
-
- # Class to rollback adding the fullpath to the git repo config
- class Down < BackfillFullpathMigration
- # Class used to retry
- class RetryOne < BaseRetryOne
- def migration_class
- Down
- end
- end
-
- def perform_one(project)
- project.cleanup_repository
- project.remove_fullpath_config
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb b/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb
new file mode 100644
index 00000000000..6014ccc12eb
--- /dev/null
+++ b/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+# rubocop:disable Style/Documentation
+
+module Gitlab
+ module BackgroundMigration
+ class CopyMergeRequestTargetProjectToMergeRequestMetrics
+ extend ::Gitlab::Utils::Override
+
+ def perform(start_id, stop_id)
+ ActiveRecord::Base.connection.execute <<~SQL
+ WITH merge_requests_batch AS (
+ SELECT id, target_project_id
+ FROM merge_requests WHERE id BETWEEN #{Integer(start_id)} AND #{Integer(stop_id)}
+ )
+ UPDATE
+ merge_request_metrics
+ SET
+ target_project_id = merge_requests_batch.target_project_id
+ FROM merge_requests_batch
+ WHERE merge_request_metrics.merge_request_id=merge_requests_batch.id
+ SQL
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/fill_file_store_job_artifact.rb b/lib/gitlab/background_migration/fill_file_store_job_artifact.rb
deleted file mode 100644
index 103bd98af14..00000000000
--- a/lib/gitlab/background_migration/fill_file_store_job_artifact.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class FillFileStoreJobArtifact
- class JobArtifact < ActiveRecord::Base
- self.table_name = 'ci_job_artifacts'
- end
-
- def perform(start_id, stop_id)
- FillFileStoreJobArtifact::JobArtifact
- .where(file_store: nil)
- .where(id: (start_id..stop_id))
- .update_all(file_store: 1)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/fill_file_store_lfs_object.rb b/lib/gitlab/background_migration/fill_file_store_lfs_object.rb
deleted file mode 100644
index 77c1f1ffaf0..00000000000
--- a/lib/gitlab/background_migration/fill_file_store_lfs_object.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class FillFileStoreLfsObject
- class LfsObject < ActiveRecord::Base
- self.table_name = 'lfs_objects'
- end
-
- def perform(start_id, stop_id)
- FillFileStoreLfsObject::LfsObject
- .where(file_store: nil)
- .where(id: (start_id..stop_id))
- .update_all(file_store: 1)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/fill_store_upload.rb b/lib/gitlab/background_migration/fill_store_upload.rb
deleted file mode 100644
index cba3e21cea6..00000000000
--- a/lib/gitlab/background_migration/fill_store_upload.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class FillStoreUpload
- class Upload < ActiveRecord::Base
- self.table_name = 'uploads'
- self.inheritance_column = :_type_disabled
- end
-
- def perform(start_id, stop_id)
- FillStoreUpload::Upload
- .where(store: nil)
- .where(id: (start_id..stop_id))
- .update_all(store: 1)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/fix_cross_project_label_links.rb b/lib/gitlab/background_migration/fix_cross_project_label_links.rb
deleted file mode 100644
index 20a98c8e141..00000000000
--- a/lib/gitlab/background_migration/fix_cross_project_label_links.rb
+++ /dev/null
@@ -1,140 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class FixCrossProjectLabelLinks
- GROUP_NESTED_LEVEL = 10.freeze
-
- class Project < ActiveRecord::Base
- self.table_name = 'projects'
- end
-
- class Label < ActiveRecord::Base
- self.inheritance_column = :_type_disabled
- self.table_name = 'labels'
- end
-
- class LabelLink < ActiveRecord::Base
- self.table_name = 'label_links'
- end
-
- class Issue < ActiveRecord::Base
- self.table_name = 'issues'
- end
-
- class MergeRequest < ActiveRecord::Base
- self.table_name = 'merge_requests'
- end
-
- class Namespace < ActiveRecord::Base
- self.inheritance_column = :_type_disabled
- self.table_name = 'namespaces'
-
- def self.groups_with_descendants_ids(start_id, stop_id)
- # To isolate migration code, we avoid usage of
- # Gitlab::GroupHierarchy#base_and_descendants which already
- # does this job better
- ids = Namespace.where(type: 'Group', id: Label.where(type: 'GroupLabel').select('distinct group_id')).where(id: start_id..stop_id).pluck(:id)
- group_ids = ids
-
- GROUP_NESTED_LEVEL.times do
- ids = Namespace.where(type: 'Group', parent_id: ids).pluck(:id)
- break if ids.empty?
-
- group_ids += ids
- end
-
- group_ids.uniq
- end
- end
-
- def perform(start_id, stop_id)
- group_ids = Namespace.groups_with_descendants_ids(start_id, stop_id)
- project_ids = Project.where(namespace_id: group_ids).select(:id)
-
- fix_issues(project_ids)
- fix_merge_requests(project_ids)
- end
-
- private
-
- # select IDs of issues which reference a label which is:
- # a) a project label of a different project, or
- # b) a group label of a different group than issue's project group
- def fix_issues(project_ids)
- issue_ids = Label
- .joins('INNER JOIN label_links ON label_links.label_id = labels.id AND label_links.target_type = \'Issue\'
- INNER JOIN issues ON issues.id = label_links.target_id
- INNER JOIN projects ON projects.id = issues.project_id')
- .where('issues.project_id in (?)', project_ids)
- .where('(labels.project_id is not null and labels.project_id != issues.project_id) '\
- 'or (labels.group_id is not null and labels.group_id != projects.namespace_id)')
- .select('distinct issues.id')
-
- Issue.where(id: issue_ids).find_each { |issue| check_resource_labels(issue, issue.project_id) }
- end
-
- # select IDs of MRs which reference a label which is:
- # a) a project label of a different project, or
- # b) a group label of a different group than MR's project group
- def fix_merge_requests(project_ids)
- mr_ids = Label
- .joins('INNER JOIN label_links ON label_links.label_id = labels.id AND label_links.target_type = \'MergeRequest\'
- INNER JOIN merge_requests ON merge_requests.id = label_links.target_id
- INNER JOIN projects ON projects.id = merge_requests.target_project_id')
- .where('merge_requests.target_project_id in (?)', project_ids)
- .where('(labels.project_id is not null and labels.project_id != merge_requests.target_project_id) '\
- 'or (labels.group_id is not null and labels.group_id != projects.namespace_id)')
- .select('distinct merge_requests.id')
-
- MergeRequest.where(id: mr_ids).find_each { |merge_request| check_resource_labels(merge_request, merge_request.target_project_id) }
- end
-
- def check_resource_labels(resource, project_id)
- local_labels = available_labels(project_id)
-
- # get all label links for the given resource (issue/MR)
- # which reference a label not included in available_labels
- # (other than its project labels and labels of ancestor groups)
- cross_labels = LabelLink
- .select('label_id, labels.title as title, labels.color as color, label_links.id as label_link_id')
- .joins('INNER JOIN labels ON labels.id = label_links.label_id')
- .where(target_type: resource.class.name.demodulize, target_id: resource.id)
- .where('labels.id not in (?)', local_labels.select(:id))
-
- cross_labels.each do |label|
- matching_label = local_labels.find {|l| l.title == label.title && l.color == label.color}
-
- next unless matching_label
-
- Rails.logger.info "#{resource.class.name.demodulize} #{resource.id}: replacing #{label.label_id} with #{matching_label.id}" # rubocop:disable Gitlab/RailsLogger
- LabelLink.update(label.label_link_id, label_id: matching_label.id)
- end
- end
-
- # get all labels available for the project (including
- # group labels of ancestor groups)
- def available_labels(project_id)
- @labels ||= {}
- @labels[project_id] ||= Label
- .where("(type = 'GroupLabel' and group_id in (?)) or (type = 'ProjectLabel' and id = ?)",
- project_group_ids(project_id),
- project_id)
- end
-
- def project_group_ids(project_id)
- ids = [Project.find(project_id).namespace_id]
-
- GROUP_NESTED_LEVEL.times do
- group = Namespace.find(ids.last)
- break unless group.parent_id
-
- ids << group.parent_id
- end
-
- ids
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/migrate_build_stage.rb b/lib/gitlab/background_migration/migrate_build_stage.rb
deleted file mode 100644
index 268c6083d3c..00000000000
--- a/lib/gitlab/background_migration/migrate_build_stage.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class MigrateBuildStage
- module Migratable
- class Stage < ActiveRecord::Base
- self.table_name = 'ci_stages'
- end
-
- class Build < ActiveRecord::Base
- self.table_name = 'ci_builds'
- self.inheritance_column = :_type_disabled
-
- def ensure_stage!(attempts: 2)
- find_stage || create_stage!
- rescue ActiveRecord::RecordNotUnique
- retry if (attempts -= 1) > 0
- raise
- end
-
- def find_stage
- Stage.find_by(name: self.stage || 'test',
- pipeline_id: self.commit_id,
- project_id: self.project_id)
- end
-
- def create_stage!
- Stage.create!(name: self.stage || 'test',
- pipeline_id: self.commit_id,
- project_id: self.project_id)
- end
- end
- end
-
- def perform(start_id, stop_id)
- stages = Migratable::Build.where('stage_id IS NULL')
- .where('id BETWEEN ? AND ?', start_id, stop_id)
- .map { |build| build.ensure_stage! }
- .compact.map(&:id)
-
- MigrateBuildStageIdReference.new.perform(start_id, stop_id)
- MigrateStageStatus.new.perform(stages.min, stages.max)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/migrate_build_stage_id_reference.rb b/lib/gitlab/background_migration/migrate_build_stage_id_reference.rb
deleted file mode 100644
index 0a8a4313cd5..00000000000
--- a/lib/gitlab/background_migration/migrate_build_stage_id_reference.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class MigrateBuildStageIdReference
- def perform(start_id, stop_id)
- sql = <<-SQL.strip_heredoc
- UPDATE ci_builds
- SET stage_id =
- (SELECT id FROM ci_stages
- WHERE ci_stages.pipeline_id = ci_builds.commit_id
- AND ci_stages.name = ci_builds.stage)
- WHERE ci_builds.id BETWEEN #{start_id.to_i} AND #{stop_id.to_i}
- AND ci_builds.stage_id IS NULL
- SQL
-
- ActiveRecord::Base.connection.execute(sql)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/migrate_stage_index.rb b/lib/gitlab/background_migration/migrate_stage_index.rb
deleted file mode 100644
index 55608529cee..00000000000
--- a/lib/gitlab/background_migration/migrate_stage_index.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class MigrateStageIndex
- def perform(start_id, stop_id)
- migrate_stage_index_sql(start_id.to_i, stop_id.to_i).tap do |sql|
- ActiveRecord::Base.connection.execute(sql)
- end
- end
-
- private
-
- def migrate_stage_index_sql(start_id, stop_id)
- <<~SQL
- WITH freqs AS (
- SELECT stage_id, stage_idx, COUNT(*) AS freq FROM ci_builds
- WHERE stage_id BETWEEN #{start_id} AND #{stop_id}
- AND stage_idx IS NOT NULL
- GROUP BY stage_id, stage_idx
- ), indexes AS (
- SELECT DISTINCT stage_id, first_value(stage_idx)
- OVER (PARTITION BY stage_id ORDER BY freq DESC) AS index
- FROM freqs
- )
-
- UPDATE ci_stages SET position = indexes.index
- FROM indexes WHERE indexes.stage_id = ci_stages.id
- AND ci_stages.position IS NULL;
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table.rb b/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table.rb
deleted file mode 100644
index fcbcaacb2d6..00000000000
--- a/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: true
-#
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class PopulateClusterKubernetesNamespaceTable
- include Gitlab::Database::MigrationHelpers
-
- BATCH_SIZE = 1_000
-
- module Migratable
- class KubernetesNamespace < ActiveRecord::Base
- self.table_name = 'clusters_kubernetes_namespaces'
- end
-
- class ClusterProject < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'cluster_projects'
-
- belongs_to :project
-
- def self.with_no_kubernetes_namespace
- where.not(id: Migratable::KubernetesNamespace.select(:cluster_project_id))
- end
-
- def namespace
- slug = "#{project.path}-#{project.id}".downcase
- slug.gsub(/[^-a-z0-9]/, '-').gsub(/^-+/, '')
- end
-
- def service_account
- "#{namespace}-service-account"
- end
- end
-
- class Project < ActiveRecord::Base
- self.table_name = 'projects'
- end
- end
-
- def perform
- cluster_projects_with_no_kubernetes_namespace.each_batch(of: BATCH_SIZE) do |cluster_projects_batch, index|
- sql_values = sql_values_for(cluster_projects_batch)
-
- insert_into_cluster_kubernetes_namespace(sql_values)
- end
- end
-
- private
-
- def cluster_projects_with_no_kubernetes_namespace
- Migratable::ClusterProject.with_no_kubernetes_namespace
- end
-
- def sql_values_for(cluster_projects)
- cluster_projects.map do |cluster_project|
- values_for_cluster_project(cluster_project)
- end
- end
-
- def values_for_cluster_project(cluster_project)
- {
- cluster_project_id: cluster_project.id,
- cluster_id: cluster_project.cluster_id,
- project_id: cluster_project.project_id,
- namespace: cluster_project.namespace,
- service_account_name: cluster_project.service_account,
- created_at: 'NOW()',
- updated_at: 'NOW()'
- }
- end
-
- def insert_into_cluster_kubernetes_namespace(rows)
- Gitlab::Database.bulk_insert(Migratable::KubernetesNamespace.table_name, # rubocop:disable Gitlab/BulkInsert
- rows,
- disable_quote: [:created_at, :updated_at])
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_personal_snippet_statistics.rb b/lib/gitlab/background_migration/populate_personal_snippet_statistics.rb
new file mode 100644
index 00000000000..e8f436b183e
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_personal_snippet_statistics.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This class creates/updates those personal snippets statistics
+ # that haven't been created nor initialized.
+ # It also updates the related root storage namespace stats
+ class PopulatePersonalSnippetStatistics
+ def perform(snippet_ids)
+ personal_snippets(snippet_ids).group_by(&:author).each do |author, author_snippets|
+ upsert_snippet_statistics(author_snippets)
+ update_namespace_statistics(author.namespace)
+ end
+ end
+
+ private
+
+ def personal_snippets(snippet_ids)
+ PersonalSnippet
+ .where(id: snippet_ids)
+ .includes(author: :namespace)
+ .includes(:statistics)
+ .includes(snippet_repository: :shard)
+ end
+
+ def upsert_snippet_statistics(snippets)
+ snippets.each do |snippet|
+ response = Snippets::UpdateStatisticsService.new(snippet).execute
+
+ error_message("#{response.message} snippet: #{snippet.id}") if response.error?
+ end
+ end
+
+ def update_namespace_statistics(namespace)
+ Namespaces::StatisticsRefresherService.new.execute(namespace)
+ rescue => e
+ error_message("Error updating statistics for namespace #{namespace.id}: #{e.message}")
+ end
+
+ def logger
+ @logger ||= Gitlab::BackgroundMigration::Logger.build
+ end
+
+ def error_message(message)
+ logger.error(message: "Snippet Statistics Migration: #{message}")
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/populate_untracked_uploads.rb b/lib/gitlab/background_migration/populate_untracked_uploads.rb
deleted file mode 100644
index 43698b7955f..00000000000
--- a/lib/gitlab/background_migration/populate_untracked_uploads.rb
+++ /dev/null
@@ -1,111 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class processes a batch of rows in `untracked_files_for_uploads` by
- # adding each file to the `uploads` table if it does not exist.
- class PopulateUntrackedUploads
- def perform(start_id, end_id)
- return unless migrate?
-
- files = Gitlab::BackgroundMigration::PopulateUntrackedUploadsDependencies::UntrackedFile.where(id: start_id..end_id)
- processed_files = insert_uploads_if_needed(files)
- processed_files.delete_all
-
- drop_temp_table_if_finished
- end
-
- private
-
- def migrate?
- Gitlab::BackgroundMigration::PopulateUntrackedUploadsDependencies::UntrackedFile.table_exists? &&
- Gitlab::BackgroundMigration::PopulateUntrackedUploadsDependencies::Upload.table_exists?
- end
-
- def insert_uploads_if_needed(files)
- filtered_files, error_files = filter_error_files(files)
- filtered_files = filter_existing_uploads(filtered_files)
- filtered_files = filter_deleted_models(filtered_files)
- insert(filtered_files)
-
- processed_files = files.where.not(id: error_files.map(&:id))
- processed_files
- end
-
- def filter_error_files(files)
- files.partition do |file|
- file.to_h
- true
- rescue => e
- msg = <<~MSG
- Error parsing path "#{file.path}":
- #{e.message}
- #{e.backtrace.join("\n ")}
- MSG
- Rails.logger.error(msg) # rubocop:disable Gitlab/RailsLogger
- false
- end
- end
-
- def filter_existing_uploads(files)
- paths = files.map(&:upload_path)
- existing_paths = Gitlab::BackgroundMigration::PopulateUntrackedUploadsDependencies::Upload.where(path: paths).pluck(:path).to_set
-
- files.reject do |file|
- existing_paths.include?(file.upload_path)
- end
- end
-
- # There are files on disk that are not in the uploads table because their
- # model was deleted, and we don't delete the files on disk.
- def filter_deleted_models(files)
- ids = deleted_model_ids(files)
-
- files.reject do |file|
- ids[file.model_type].include?(file.model_id)
- end
- end
-
- def deleted_model_ids(files)
- ids = {
- 'Appearance' => [],
- 'Namespace' => [],
- 'Note' => [],
- 'Project' => [],
- 'User' => []
- }
-
- # group model IDs by model type
- files.each do |file|
- ids[file.model_type] << file.model_id
- end
-
- ids.each do |model_type, model_ids|
- model_class = "Gitlab::BackgroundMigration::PopulateUntrackedUploadsDependencies::#{model_type}".constantize
- found_ids = model_class.where(id: model_ids.uniq).pluck(:id)
- deleted_ids = ids[model_type] - found_ids
- ids[model_type] = deleted_ids
- end
-
- ids
- end
-
- def insert(files)
- rows = files.map do |file|
- file.to_h.merge(created_at: 'NOW()')
- end
-
- Gitlab::Database.bulk_insert('uploads', # rubocop:disable Gitlab/BulkInsert
- rows,
- disable_quote: :created_at)
- end
-
- def drop_temp_table_if_finished
- if Gitlab::BackgroundMigration::PopulateUntrackedUploadsDependencies::UntrackedFile.all.empty? && !Rails.env.test? # Dropping a table intermittently breaks test cleanup
- Gitlab::BackgroundMigration::PopulateUntrackedUploadsDependencies::UntrackedFile.connection.drop_table(:untracked_files_for_uploads,
- if_exists: true)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb b/lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb
deleted file mode 100644
index 23e8be4a9ab..00000000000
--- a/lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb
+++ /dev/null
@@ -1,190 +0,0 @@
-# frozen_string_literal: true
-module Gitlab
- module BackgroundMigration
- module PopulateUntrackedUploadsDependencies
- # This class is responsible for producing the attributes necessary to
- # track an uploaded file in the `uploads` table.
- class UntrackedFile < ActiveRecord::Base # rubocop:disable Metrics/ClassLength
- self.table_name = 'untracked_files_for_uploads'
-
- # Ends with /:random_hex/:filename
- FILE_UPLOADER_PATH = %r{/\h+/[^/]+\z}.freeze
- FULL_PATH_CAPTURE = /\A(.+)#{FILE_UPLOADER_PATH}/.freeze
-
- # These regex patterns are tested against a relative path, relative to
- # the upload directory.
- # For convenience, if there exists a capture group in the pattern, then
- # it indicates the model_id.
- PATH_PATTERNS = [
- {
- pattern: %r{\A-/system/appearance/logo/(\d+)/},
- uploader: 'AttachmentUploader',
- model_type: 'Appearance'
- },
- {
- pattern: %r{\A-/system/appearance/header_logo/(\d+)/},
- uploader: 'AttachmentUploader',
- model_type: 'Appearance'
- },
- {
- pattern: %r{\A-/system/note/attachment/(\d+)/},
- uploader: 'AttachmentUploader',
- model_type: 'Note'
- },
- {
- pattern: %r{\A-/system/user/avatar/(\d+)/},
- uploader: 'AvatarUploader',
- model_type: 'User'
- },
- {
- pattern: %r{\A-/system/group/avatar/(\d+)/},
- uploader: 'AvatarUploader',
- model_type: 'Namespace'
- },
- {
- pattern: %r{\A-/system/project/avatar/(\d+)/},
- uploader: 'AvatarUploader',
- model_type: 'Project'
- },
- {
- pattern: FILE_UPLOADER_PATH,
- uploader: 'FileUploader',
- model_type: 'Project'
- }
- ].freeze
-
- def to_h
- @upload_hash ||= {
- path: upload_path,
- uploader: uploader,
- model_type: model_type,
- model_id: model_id,
- size: file_size,
- checksum: checksum
- }
- end
-
- def upload_path
- # UntrackedFile#path is absolute, but Upload#path depends on uploader
- @upload_path ||=
- if uploader == 'FileUploader'
- # Path relative to project directory in uploads
- matchd = path_relative_to_upload_dir.match(FILE_UPLOADER_PATH)
- matchd[0].sub(%r{\A/}, '') # remove leading slash
- else
- path
- end
- end
-
- def uploader
- matching_pattern_map[:uploader]
- end
-
- def model_type
- matching_pattern_map[:model_type]
- end
-
- def model_id
- return @model_id if defined?(@model_id)
-
- pattern = matching_pattern_map[:pattern]
- matchd = path_relative_to_upload_dir.match(pattern)
-
- # If something is captured (matchd[1] is not nil), it is a model_id
- # Only the FileUploader pattern will not match an ID
- @model_id = matchd[1] ? matchd[1].to_i : file_uploader_model_id
- end
-
- def file_size
- File.size(absolute_path)
- end
-
- def checksum
- Digest::SHA256.file(absolute_path).hexdigest
- end
-
- private
-
- def matching_pattern_map
- @matching_pattern_map ||= PATH_PATTERNS.find do |path_pattern_map|
- path_relative_to_upload_dir.match(path_pattern_map[:pattern])
- end
-
- unless @matching_pattern_map
- raise "Unknown upload path pattern \"#{path}\""
- end
-
- @matching_pattern_map
- end
-
- def file_uploader_model_id
- matchd = path_relative_to_upload_dir.match(FULL_PATH_CAPTURE)
- not_found_msg = <<~MSG
- Could not capture project full_path from a FileUploader path:
- "#{path_relative_to_upload_dir}"
- MSG
- raise not_found_msg unless matchd
-
- full_path = matchd[1]
- project = Gitlab::BackgroundMigration::PopulateUntrackedUploadsDependencies::Project.find_by_full_path(full_path)
- return unless project
-
- project.id
- end
-
- # Not including a leading slash
- def path_relative_to_upload_dir
- upload_dir = Gitlab::BackgroundMigration::PrepareUntrackedUploads::RELATIVE_UPLOAD_DIR
- base = %r{\A#{Regexp.escape(upload_dir)}/}
- @path_relative_to_upload_dir ||= path.sub(base, '')
- end
-
- def absolute_path
- File.join(Gitlab.config.uploads.storage_path, path)
- end
- end
-
- # Avoid using application code
- class Upload < ActiveRecord::Base
- self.table_name = 'uploads'
- end
-
- # Avoid using application code
- class Appearance < ActiveRecord::Base
- self.table_name = 'appearances'
- end
-
- # Avoid using application code
- class Namespace < ActiveRecord::Base
- self.table_name = 'namespaces'
- end
-
- # Avoid using application code
- class Note < ActiveRecord::Base
- self.table_name = 'notes'
- end
-
- # Avoid using application code
- class User < ActiveRecord::Base
- self.table_name = 'users'
- end
-
- # Since project Markdown upload paths don't contain the project ID, we have to find the
- # project by its full_path. Due to MySQL/PostgreSQL differences, and historical reasons,
- # the logic is somewhat complex, so I've mostly copied it in here.
- class Project < ActiveRecord::Base
- self.table_name = 'projects'
-
- def self.find_by_full_path(path)
- order_sql = Arel.sql("(CASE WHEN routes.path = #{connection.quote(path)} THEN 0 ELSE 1 END)")
- where_full_path_in(path).reorder(order_sql).take
- end
-
- def self.where_full_path_in(path)
- where = "(LOWER(routes.path) = LOWER(#{connection.quote(path)}))"
- joins("INNER JOIN routes ON routes.source_id = projects.id AND routes.source_type = 'Project'").where(where)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/prepare_untracked_uploads.rb b/lib/gitlab/background_migration/prepare_untracked_uploads.rb
deleted file mode 100644
index 3d943205783..00000000000
--- a/lib/gitlab/background_migration/prepare_untracked_uploads.rb
+++ /dev/null
@@ -1,173 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class finds all non-hashed uploaded file paths and saves them to a
- # `untracked_files_for_uploads` table.
- class PrepareUntrackedUploads # rubocop:disable Metrics/ClassLength
- # For bulk_queue_background_migration_jobs_by_range
- include Database::MigrationHelpers
- include ::Gitlab::Utils::StrongMemoize
-
- FIND_BATCH_SIZE = 500
- RELATIVE_UPLOAD_DIR = "uploads"
- ABSOLUTE_UPLOAD_DIR = File.join(
- Gitlab.config.uploads.storage_path,
- RELATIVE_UPLOAD_DIR
- )
- FOLLOW_UP_MIGRATION = 'PopulateUntrackedUploads'
- START_WITH_ROOT_REGEX = %r{\A#{Gitlab.config.uploads.storage_path}/}.freeze
- EXCLUDED_HASHED_UPLOADS_PATH = "#{ABSOLUTE_UPLOAD_DIR}/@hashed/*"
- EXCLUDED_TMP_UPLOADS_PATH = "#{ABSOLUTE_UPLOAD_DIR}/tmp/*"
-
- # This class is used to iterate over batches of
- # `untracked_files_for_uploads` rows.
- class UntrackedFile < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'untracked_files_for_uploads'
- end
-
- def perform
- ensure_temporary_tracking_table_exists
-
- # Since Postgres < 9.5 does not have ON CONFLICT DO NOTHING, and since
- # doing inserts-if-not-exists without ON CONFLICT DO NOTHING would be
- # slow, start with an empty table for Postgres < 9.5.
- # That way we can do bulk inserts at ~30x the speed of individual
- # inserts (~20 minutes worth of inserts at GitLab.com scale instead of
- # ~10 hours).
- # In all other cases, installations will get both bulk inserts and the
- # ability for these jobs to retry without having to clear and reinsert.
- clear_untracked_file_paths unless can_bulk_insert_and_ignore_duplicates?
-
- store_untracked_file_paths
-
- if UntrackedFile.all.empty?
- drop_temp_table
- else
- schedule_populate_untracked_uploads_jobs
- end
- end
-
- private
-
- def ensure_temporary_tracking_table_exists
- table_name = :untracked_files_for_uploads
-
- unless ActiveRecord::Base.connection.table_exists?(table_name)
- UntrackedFile.connection.create_table table_name do |t|
- t.string :path, limit: 600, null: false
- t.index :path, unique: true
- end
- end
- end
-
- def clear_untracked_file_paths
- UntrackedFile.delete_all
- end
-
- def store_untracked_file_paths
- return unless Dir.exist?(ABSOLUTE_UPLOAD_DIR)
-
- each_file_batch(ABSOLUTE_UPLOAD_DIR, FIND_BATCH_SIZE) do |file_paths|
- insert_file_paths(file_paths)
- end
- end
-
- def each_file_batch(search_dir, batch_size, &block)
- cmd = build_find_command(search_dir)
-
- Open3.popen2(*cmd) do |stdin, stdout, status_thread|
- yield_paths_in_batches(stdout, batch_size, &block)
-
- raise "Find command failed" unless status_thread.value.success?
- end
- end
-
- def yield_paths_in_batches(stdout, batch_size, &block)
- paths = []
-
- stdout.each_line("\0") do |line|
- paths << line.chomp("\0").sub(START_WITH_ROOT_REGEX, '')
-
- if paths.size >= batch_size
- yield(paths)
- paths = []
- end
- end
-
- yield(paths) if paths.any?
- end
-
- def build_find_command(search_dir)
- cmd = %W[find -L #{search_dir}
- -type f
- ! ( -path #{EXCLUDED_HASHED_UPLOADS_PATH} -prune )
- ! ( -path #{EXCLUDED_TMP_UPLOADS_PATH} -prune )
- -print0]
-
- ionice = which_ionice
- cmd = %W[#{ionice} -c Idle] + cmd if ionice
-
- log_msg = "PrepareUntrackedUploads find command: \"#{cmd.join(' ')}\""
- Rails.logger.info log_msg # rubocop:disable Gitlab/RailsLogger
-
- cmd
- end
-
- def which_ionice
- Gitlab::Utils.which('ionice')
- rescue StandardError
- # In this case, returning false is relatively safe,
- # even though it isn't very nice
- false
- end
-
- def insert_file_paths(file_paths)
- sql = insert_sql(file_paths)
-
- ActiveRecord::Base.connection.execute(sql)
- end
-
- def insert_sql(file_paths)
- if postgresql_pre_9_5?
- "INSERT INTO #{table_columns_and_values_for_insert(file_paths)};"
- else
- "INSERT INTO #{table_columns_and_values_for_insert(file_paths)}"\
- " ON CONFLICT DO NOTHING;"
- end
- end
-
- def table_columns_and_values_for_insert(file_paths)
- values = file_paths.map do |file_path|
- ActiveRecord::Base.send(:sanitize_sql_array, ['(?)', file_path]) # rubocop:disable GitlabSecurity/PublicSend
- end.join(', ')
-
- "#{UntrackedFile.table_name} (path) VALUES #{values}"
- end
-
- def can_bulk_insert_and_ignore_duplicates?
- !postgresql_pre_9_5?
- end
-
- def postgresql_pre_9_5?
- strong_memoize(:postgresql_pre_9_5) do
- Gitlab::Database.version.to_f < 9.5
- end
- end
-
- def schedule_populate_untracked_uploads_jobs
- bulk_queue_background_migration_jobs_by_range(
- UntrackedFile, FOLLOW_UP_MIGRATION)
- end
-
- def drop_temp_table
- unless Rails.env.test? # Dropping a table intermittently breaks test cleanup
- UntrackedFile.connection.drop_table(:untracked_files_for_uploads,
- if_exists: true)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/remove_restricted_todos.rb b/lib/gitlab/background_migration/remove_restricted_todos.rb
deleted file mode 100644
index 9ef6d8654ae..00000000000
--- a/lib/gitlab/background_migration/remove_restricted_todos.rb
+++ /dev/null
@@ -1,158 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-# rubocop:disable Metrics/ClassLength
-
-module Gitlab
- module BackgroundMigration
- class RemoveRestrictedTodos
- PRIVATE_FEATURE = 10
- PRIVATE_PROJECT = 0
-
- class Project < ActiveRecord::Base
- self.table_name = 'projects'
- end
-
- class ProjectAuthorization < ActiveRecord::Base
- self.table_name = 'project_authorizations'
- end
-
- class ProjectFeature < ActiveRecord::Base
- self.table_name = 'project_features'
- end
-
- class Todo < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'todos'
- end
-
- class Issue < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'issues'
- end
-
- def perform(start_id, stop_id)
- projects = Project.where('EXISTS (SELECT 1 FROM todos WHERE todos.project_id = projects.id)')
- .where(id: start_id..stop_id)
-
- projects.each do |project|
- remove_confidential_issue_todos(project.id)
-
- if project.visibility_level == PRIVATE_PROJECT
- remove_non_members_todos(project.id)
- else
- remove_restricted_features_todos(project.id)
- end
- end
- end
-
- private
-
- def remove_non_members_todos(project_id)
- batch_remove_todos_cte(project_id)
- end
-
- def remove_confidential_issue_todos(project_id)
- # min access level to access a confidential issue is reporter
- min_reporters = authorized_users(project_id)
- .select(:user_id)
- .where('access_level >= ?', 20)
-
- confidential_issues = Issue.select(:id, :author_id).where(confidential: true, project_id: project_id)
- confidential_issues.each_batch(of: 100, order_hint: :confidential) do |batch|
- batch.each do |issue|
- assigned_users = IssueAssignee.select(:user_id).where(issue_id: issue.id)
-
- todos = Todo.where(target_type: 'Issue', target_id: issue.id)
- .where('user_id NOT IN (?)', min_reporters)
- .where('user_id NOT IN (?)', assigned_users)
- todos = todos.where('user_id != ?', issue.author_id) if issue.author_id
-
- todos.delete_all
- end
- end
- end
-
- def remove_restricted_features_todos(project_id)
- ProjectFeature.where(project_id: project_id).each do |project_features|
- target_types = []
- target_types << 'Issue' if private?(project_features.issues_access_level)
- target_types << 'MergeRequest' if private?(project_features.merge_requests_access_level)
- target_types << 'Commit' if private?(project_features.repository_access_level)
-
- next if target_types.empty?
-
- batch_remove_todos_cte(project_id, target_types)
- end
- end
-
- def private?(feature_level)
- feature_level == PRIVATE_FEATURE
- end
-
- def authorized_users(project_id)
- ProjectAuthorization.select(:user_id).where(project_id: project_id)
- end
-
- def unauthorized_project_todos(project_id)
- Todo.where(project_id: project_id)
- .where('user_id NOT IN (?)', authorized_users(project_id))
- end
-
- def batch_remove_todos_cte(project_id, target_types = nil)
- loop do
- count = remove_todos_cte(project_id, target_types)
-
- break if count == 0
- end
- end
-
- def remove_todos_cte(project_id, target_types = nil)
- sql = []
- sql << with_all_todos_sql(project_id, target_types)
- sql << as_deleted_sql
- sql << "SELECT count(*) FROM deleted"
-
- result = Todo.connection.exec_query(sql.join(' '))
- result.rows[0][0].to_i
- end
-
- def with_all_todos_sql(project_id, target_types = nil)
- if target_types
- table = Arel::Table.new(:todos)
- in_target = table[:target_type].in(target_types)
- target_types_sql = " AND #{in_target.to_sql}"
- end
-
- <<-SQL
- WITH all_todos AS (
- SELECT id
- FROM "todos"
- WHERE "todos"."project_id" = #{project_id}
- AND (user_id NOT IN (
- SELECT "project_authorizations"."user_id"
- FROM "project_authorizations"
- WHERE "project_authorizations"."project_id" = #{project_id})
- #{target_types_sql}
- )
- ),
- SQL
- end
-
- def as_deleted_sql
- <<-SQL
- deleted AS (
- DELETE FROM todos
- WHERE id IN (
- SELECT id
- FROM all_todos
- LIMIT 5000
- )
- RETURNING id
- )
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/set_confidential_note_events_on_services.rb b/lib/gitlab/background_migration/set_confidential_note_events_on_services.rb
deleted file mode 100644
index bc434b0cb64..00000000000
--- a/lib/gitlab/background_migration/set_confidential_note_events_on_services.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- # Ensures services which previously received all notes events continue
- # to receive confidential ones.
- class SetConfidentialNoteEventsOnServices
- class Service < ActiveRecord::Base
- self.table_name = 'services'
-
- include ::EachBatch
-
- def self.services_to_update
- where(confidential_note_events: nil, note_events: true)
- end
- end
-
- def perform(start_id, stop_id)
- Service.services_to_update
- .where(id: start_id..stop_id)
- .update_all(confidential_note_events: true)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/set_confidential_note_events_on_webhooks.rb b/lib/gitlab/background_migration/set_confidential_note_events_on_webhooks.rb
deleted file mode 100644
index 28d8d2c640b..00000000000
--- a/lib/gitlab/background_migration/set_confidential_note_events_on_webhooks.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- # Ensures hooks which previously received all notes events continue
- # to receive confidential ones.
- class SetConfidentialNoteEventsOnWebhooks
- class WebHook < ActiveRecord::Base
- self.table_name = 'web_hooks'
-
- include ::EachBatch
-
- def self.hooks_to_update
- where(confidential_note_events: nil, note_events: true)
- end
- end
-
- def perform(start_id, stop_id)
- WebHook.hooks_to_update
- .where(id: start_id..stop_id)
- .update_all(confidential_note_events: true)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/set_merge_request_diff_files_count.rb b/lib/gitlab/background_migration/set_merge_request_diff_files_count.rb
new file mode 100644
index 00000000000..9f765d03d62
--- /dev/null
+++ b/lib/gitlab/background_migration/set_merge_request_diff_files_count.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Sets the MergeRequestDiff#files_count value for old rows
+ class SetMergeRequestDiffFilesCount
+ COUNT_SUBQUERY = <<~SQL
+ files_count = (
+ SELECT count(*)
+ FROM merge_request_diff_files
+ WHERE merge_request_diff_files.merge_request_diff_id = merge_request_diffs.id
+ )
+ SQL
+
+ class MergeRequestDiff < ActiveRecord::Base # rubocop:disable Style/Documentation
+ include EachBatch
+
+ self.table_name = 'merge_request_diffs'
+ end
+
+ def perform(start_id, end_id)
+ MergeRequestDiff.where(id: start_id..end_id).each_batch do |relation|
+ relation.update_all(COUNT_SUBQUERY)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/set_null_external_diff_store_to_local_value.rb b/lib/gitlab/background_migration/set_null_external_diff_store_to_local_value.rb
new file mode 100644
index 00000000000..71f3483987e
--- /dev/null
+++ b/lib/gitlab/background_migration/set_null_external_diff_store_to_local_value.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This class is responsible for migrating a range of merge request diffs
+ # with external_diff_store == NULL to 1.
+ #
+ # The index `index_merge_request_diffs_external_diff_store_is_null` is
+ # expected to be used to find the rows here and in the migration scheduling
+ # the jobs that run this class.
+ class SetNullExternalDiffStoreToLocalValue
+ LOCAL_STORE = 1 # equal to ObjectStorage::Store::LOCAL
+
+ # Temporary AR class for merge request diffs
+ class MergeRequestDiff < ActiveRecord::Base
+ self.table_name = 'merge_request_diffs'
+ end
+
+ def perform(start_id, stop_id)
+ MergeRequestDiff.where(external_diff_store: nil, id: start_id..stop_id).update_all(external_diff_store: LOCAL_STORE)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb b/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb
new file mode 100644
index 00000000000..9ac92aab637
--- /dev/null
+++ b/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This class is responsible for migrating a range of package files
+ # with file_store == NULL to 1.
+ #
+ # The index `index_packages_package_files_file_store_is_null` is
+ # expected to be used to find the rows here and in the migration scheduling
+ # the jobs that run this class.
+ class SetNullPackageFilesFileStoreToLocalValue
+ LOCAL_STORE = 1 # equal to ObjectStorage::Store::LOCAL
+
+ # Temporary AR class for package files
+ class PackageFile < ActiveRecord::Base
+ self.table_name = 'packages_package_files'
+ end
+
+ def perform(start_id, stop_id)
+ Packages::PackageFile.where(file_store: nil, id: start_id..stop_id).update_all(file_store: LOCAL_STORE)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/user_mentions/create_resource_user_mention.rb b/lib/gitlab/background_migration/user_mentions/create_resource_user_mention.rb
index d71a50a0af6..b3876018553 100644
--- a/lib/gitlab/background_migration/user_mentions/create_resource_user_mention.rb
+++ b/lib/gitlab/background_migration/user_mentions/create_resource_user_mention.rb
@@ -12,26 +12,22 @@ module Gitlab
ISOLATION_MODULE = 'Gitlab::BackgroundMigration::UserMentions::Models'
def perform(resource_model, join, conditions, with_notes, start_id, end_id)
+ return unless Feature.enabled?(:migrate_user_mentions, default_enabled: true)
+
resource_model = "#{ISOLATION_MODULE}::#{resource_model}".constantize if resource_model.is_a?(String)
model = with_notes ? Gitlab::BackgroundMigration::UserMentions::Models::Note : resource_model
resource_user_mention_model = resource_model.user_mention_model
records = model.joins(join).where(conditions).where(id: start_id..end_id)
- records.in_groups_of(BULK_INSERT_SIZE, false).each do |records|
+ records.each_batch(of: BULK_INSERT_SIZE) do |records|
mentions = []
records.each do |record|
mention_record = record.build_mention_values(resource_user_mention_model.resource_foreign_key)
mentions << mention_record unless mention_record.blank?
end
- Gitlab::Database.bulk_insert( # rubocop:disable Gitlab/BulkInsert
- resource_user_mention_model.table_name,
- mentions,
- return_ids: true,
- disable_quote: resource_model.no_quote_columns,
- on_conflict: :do_nothing
- )
+ resource_user_mention_model.insert_all(mentions) unless mentions.empty?
end
end
end
diff --git a/lib/gitlab/background_migration/user_mentions/models/commit.rb b/lib/gitlab/background_migration/user_mentions/models/commit.rb
index 279e93dbf0d..65f4a7a25b6 100644
--- a/lib/gitlab/background_migration/user_mentions/models/commit.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/commit.rb
@@ -6,6 +6,7 @@ module Gitlab
module UserMentions
module Models
class Commit
+ include EachBatch
include Concerns::IsolatedMentionable
include Concerns::MentionableMigrationMethods
diff --git a/lib/gitlab/background_migration/user_mentions/models/design_management/design.rb b/lib/gitlab/background_migration/user_mentions/models/design_management/design.rb
index 0cdfc6447c7..bdb90b5d2b9 100644
--- a/lib/gitlab/background_migration/user_mentions/models/design_management/design.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/design_management/design.rb
@@ -7,6 +7,7 @@ module Gitlab
module Models
module DesignManagement
class Design < ActiveRecord::Base
+ include EachBatch
include Concerns::MentionableMigrationMethods
def self.user_mention_model
diff --git a/lib/gitlab/background_migration/user_mentions/models/epic.rb b/lib/gitlab/background_migration/user_mentions/models/epic.rb
index dc2b7819800..61d9244a4c9 100644
--- a/lib/gitlab/background_migration/user_mentions/models/epic.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/epic.rb
@@ -6,6 +6,7 @@ module Gitlab
module UserMentions
module Models
class Epic < ActiveRecord::Base
+ include EachBatch
include Concerns::IsolatedMentionable
include Concerns::MentionableMigrationMethods
include CacheMarkdownField
diff --git a/lib/gitlab/background_migration/user_mentions/models/merge_request.rb b/lib/gitlab/background_migration/user_mentions/models/merge_request.rb
index 655c1db71ae..6b52afea17c 100644
--- a/lib/gitlab/background_migration/user_mentions/models/merge_request.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/merge_request.rb
@@ -6,6 +6,7 @@ module Gitlab
module UserMentions
module Models
class MergeRequest < ActiveRecord::Base
+ include EachBatch
include Concerns::IsolatedMentionable
include CacheMarkdownField
include Concerns::MentionableMigrationMethods
diff --git a/lib/gitlab/background_migration/user_mentions/models/note.rb b/lib/gitlab/background_migration/user_mentions/models/note.rb
index c32292ad704..a3224c8c456 100644
--- a/lib/gitlab/background_migration/user_mentions/models/note.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/note.rb
@@ -6,6 +6,7 @@ module Gitlab
module UserMentions
module Models
class Note < ActiveRecord::Base
+ include EachBatch
include Concerns::IsolatedMentionable
include CacheMarkdownField