diff options
author | Kamil Trzcinski <ayufan@ayufan.eu> | 2017-05-05 00:02:51 +0300 |
---|---|---|
committer | Kamil Trzcinski <ayufan@ayufan.eu> | 2017-06-01 15:39:48 +0300 |
commit | e61f38d79eb85a7c601bd146d5b8e48a8b4418e5 (patch) | |
tree | 08abc6cb3f4ef57de157167fca8189a162298ae1 /db/post_migrate/20170523083112_migrate_old_artifacts.rb | |
parent | c72abcefe79dd906cbbf0088b442a8979e9fc746 (diff) |
Fix data inconsistency issue for old artifacts by moving them to a currently used path
Diffstat (limited to 'db/post_migrate/20170523083112_migrate_old_artifacts.rb')
-rw-r--r-- | db/post_migrate/20170523083112_migrate_old_artifacts.rb | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/db/post_migrate/20170523083112_migrate_old_artifacts.rb b/db/post_migrate/20170523083112_migrate_old_artifacts.rb new file mode 100644 index 00000000000..3067e3d404b --- /dev/null +++ b/db/post_migrate/20170523083112_migrate_old_artifacts.rb @@ -0,0 +1,72 @@ +class MigrateOldArtifacts < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + # This uses special heuristic to find potential candidates for data migration + # Read more about this here: https://gitlab.com/gitlab-org/gitlab-ce/issues/32036#note_30422345 + + def up + builds_with_artifacts.find_each do |build| + build.migrate_artifacts! + end + end + + def down + end + + private + + def builds_with_artifacts + Build.with_artifacts + .joins('JOIN projects ON projects.id = ci_builds.project_id') + .where('ci_builds.id < ?', min_id || 0) + .where('projects.ci_id IS NOT NULL') + .select('id', 'created_at', 'project_id', 'projects.ci_id AS ci_id') + end + + def min_id + Build.joins('JOIN projects ON projects.id = ci_builds.project_id') + .where('projects.ci_id IS NULL') + .pluck('min(ci_builds.id)') + .first + end + + class Build < ActiveRecord::Base + self.table_name = 'ci_builds' + + scope :with_artifacts, ->() { where.not(artifacts_file: [nil, '']) } + + def migrate_artifacts! + return unless File.exists?(source_artifacts_path) + return if File.exists?(target_artifacts_path) + + ensure_target_path + + FileUtils.move(source_artifacts_path, target_artifacts_path) + end + + private + + def source_artifacts_path + @source_artifacts_path ||= + File.join(Gitlab.config.artifacts.path, + created_at.utc.strftime('%Y_%m'), + ci_id.to_s, id.to_s) + end + + def target_artifacts_path + @target_artifacts_path ||= + File.join(Gitlab.config.artifacts.path, + created_at.utc.strftime('%Y_%m'), + project_id.to_s, id.to_s) + end + + def ensure_target_path + directory = File.dirname(target_artifacts_path) + FileUtils.mkdir_p(directory) unless Dir.exist?(directory) + end + end +end |