Files
gitlab-foss/scripts/refresh-migrations-timestamps
2024-09-18 09:11:15 +00:00

125 lines
2.9 KiB
Ruby
Executable File

#!/usr/bin/env ruby
# frozen_string_literal: true
ENV['RAILS_ENV'] = 'test'
require 'optparse'
require 'open3'
require 'fileutils'
require 'uri'
require 'gitlab-chronic'
class MigrationsTimestampRefresher
##
# Directories where migrations are stored
MIGRATION_DIRS = %w[db/migrate db/post_migrate].join(' ').freeze
def initialize(options)
@options = options
end
def execute
Dir.chdir(File.expand_path('..', __dir__)) do
refresh_migrations
regenerate_schema
end
end
private
attr_reader :options
def refresh_migrations
migrations = untracked_schema_migrations + committed_schema_migrations
migrations = migrations.sort_by { |file| file.slice(/\d{14}/) }
migrations.each do |file|
new_file = file.gsub(/\d{14}/, next_migration_number)
puts "\e[32m$ mv #{file} #{new_file}\e[37m"
FileUtils.mv(file, new_file)
end
end
def regenerate_schema
run('./scripts/regenerate-schema')
end
def next_migration_number
@next_migration_number ||= seed_migration_number.to_i
@next_migration_number += rand(2..5)
@next_migration_number.to_s
end
def seed_migration_number
Chronic
.parse(options.fetch(:after, 'now'))
.utc.strftime("%Y%m%d%H%M%S")
end
def untracked_schema_migrations
git_command = "git ls-files --others --exclude-standard -- #{MIGRATION_DIRS}"
run(git_command).chomp.split("\n")
end
def committed_schema_migrations
git_command = "git diff --name-only --diff-filter=A #{merge_base} -- #{MIGRATION_DIRS}"
run(git_command).chomp.split("\n")
end
##
# Run the given +cmd+.
#
# The command is colored green, and the output of the command is
# colored gray.
# When the command failed an exception is raised.
def run(cmd)
puts "\e[32m$ #{cmd}\e[37m"
stdout_str, stderr_str, status = Open3.capture3(cmd)
puts "#{stdout_str}#{stderr_str}\e[0m"
raise("Command failed: #{stderr_str}") unless status.success?
stdout_str
end
##
# Return the base commit between source and target branch.
def merge_base
@merge_base ||= run("git merge-base #{target_branch} #{source_ref}").chomp
end
##
# Return the name of the target branch
#
# Get source ref from CI environment variable, or read the +TARGET+
# environment+ variable, or default to +HEAD+.
def target_branch
ENV['CI_MERGE_REQUEST_TARGET_BRANCH_NAME'] || ENV['TARGET'] || ENV['CI_DEFAULT_BRANCH'] || 'master'
end
##
# Return the source ref
#
# Get source ref from CI environment variable, or default to +HEAD+.
def source_ref
ENV['CI_COMMIT_SHA'] || 'HEAD'
end
end
if $PROGRAM_NAME == __FILE__
options = {}
OptionParser.new do |opts|
opts.on("-a", "--after VALUE", String, "Start value for the timestamp") do |value|
options[:after] = value
end
opts.on("-h", "--help", "Prints this help") do
puts opts
exit
end
end.parse!
MigrationsTimestampRefresher.new(options).execute
end