diff --git a/script/promote_migrations b/script/promote_migrations new file mode 100755 index 00000000000..a76e751bea4 --- /dev/null +++ b/script/promote_migrations @@ -0,0 +1,97 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# This script will promote post_migrate files +# which have existed for more than one Discourse +# stable version cycle. +# +# Renames will be staged in git, but not committed +# +# Usage: +# script/promote_migrations [--dry-run] [--plugins] + +require 'open3' +require 'fileutils' + +VERSION_REGEX = %r{\/(\d+)_} +DRY_RUN = ARGV.include? '--dry-run' +PLUGINS = ARGV.include? '--plugins' + +def run(*args, capture: true) + out, s = Open3.capture2(*args) + if s.exitstatus != 0 + STDERR.puts "Command failed: '#{args.join(' ')}'" + exit 1 + end + out.strip +end + +current_version = run 'git describe --abbrev=0 --match "v*"' +puts "Current version is #{current_version}" + +run 'git fetch' +current_stable_version = + run 'git describe --abbrev=0 --match "v*" origin/stable' +puts "Current stable version is #{current_stable_version}" + +minor = current_stable_version[/^(v\d+\.\d+)\./, 1] + +previous_stable_version = + run "git describe --abbrev=0 --match 'v*' --exclude '#{minor}*' origin/stable" +puts "Previous stable version is #{previous_stable_version}" + +stable_post_migrate_filenames = + run( + 'git', + 'ls-tree', + '--name-only', + '-r', + previous_stable_version, + 'db/post_migrate' + ).split("\n") + +stable_post_migrate_filenames.sort! +latest_stable_post_migration = stable_post_migrate_filenames.last + +puts "The latest core post_migrate file in #{previous_stable_version} is #{latest_stable_post_migration}" +puts 'Promoting this, and all earlier post_migrates, to regular migrations' + +promote_threshold = latest_stable_post_migration[VERSION_REGEX, 1].to_i +current_post_migrations = + if PLUGINS + puts 'Looking in plugins...' + Dir.glob('plugins/*/db/post_migrate/*') + else + Dir.glob('db/post_migrate/*') + end + +if current_post_migrations.length == 0 + puts 'No post_migrate files found. All done' +end + +current_post_migrations.each do |path| + version = path[VERSION_REGEX, 1].to_i + file = File.basename(path) + dir = File.dirname(path) + + if version <= promote_threshold + print "Promoting #{path}..." + if DRY_RUN + puts ' (dry run)' + else + run 'mkdir', '-p', "#{dir}/../migrate" + run 'git', '-C', dir, 'mv', file, "../migrate/#{file}" + puts ' (done)' + end + end +end + +puts 'Done! File moves are staged and ready for commit.' +puts 'Suggested commit message:' +puts '-' * 20 +puts <<~MESSAGE +DEV: Promote historic post_deploy migrations + +This commit promotes all post_deploy migrations which existed in Discourse #{previous_stable_version} (timestamp <= #{promote_threshold}) +MESSAGE +puts '-' * 20