FIX: migrations-tooling CLI didn't work anymore (#29777)
The previous approach of splitting Thor commands into multiple files caused problems when the same method name was used in multiple commands. This also loads the Rails environment only for commands that need it. That makes the CLI boot faster for most commands or when the help should be shown. That's also why we can't use `Rails.root` in the CLI.
This commit is contained in:
parent
a8ca82b11f
commit
75f4a14568
|
@ -1,23 +1,49 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "thor"
|
|
||||||
require_relative "../lib/migrations"
|
require_relative "../lib/migrations"
|
||||||
|
|
||||||
|
require "colored2"
|
||||||
|
require "thor"
|
||||||
|
|
||||||
module Migrations
|
module Migrations
|
||||||
load_rails_environment
|
|
||||||
configure_zeitwerk
|
configure_zeitwerk
|
||||||
enable_i18n
|
enable_i18n
|
||||||
|
|
||||||
class CommandLineInterface < Thor
|
module CLI
|
||||||
include ::Migrations::CLI::ConvertCommand
|
class Application < Thor
|
||||||
include ::Migrations::CLI::ImportCommand
|
desc "convert [FROM]", "Convert a file"
|
||||||
include ::Migrations::CLI::UploadCommand
|
option :settings, type: :string, desc: "Path of settings file", banner: "path"
|
||||||
|
option :reset, type: :boolean, desc: "Reset database before converting data"
|
||||||
|
def convert(converter_type)
|
||||||
|
::Migrations::CLI::ConvertCommand.new(converter_type, options).execute
|
||||||
|
end
|
||||||
|
|
||||||
def self.exit_on_failure?
|
desc "import", "Import a file"
|
||||||
true
|
def import
|
||||||
|
::Migrations::CLI::ImportCommand.new(options).execute
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "upload", "Upload media uploads"
|
||||||
|
option :settings,
|
||||||
|
type: :string,
|
||||||
|
desc: "Uploads settings file path",
|
||||||
|
default: "./migrations/config/upload.yml",
|
||||||
|
aliases: "-s",
|
||||||
|
banner: "path"
|
||||||
|
option :fix_missing, type: :boolean, desc: "Fix missing uploads"
|
||||||
|
option :optimize, type: :boolean, desc: "Optimize uploads"
|
||||||
|
def upload
|
||||||
|
::Migrations::CLI::UploadCommand.new(options).execute
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.exit_on_failure?
|
||||||
|
true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Dir.chdir(Rails.root) { CommandLineInterface.start } # rubocop:disable Discourse/NoChdir
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# rubocop:disable Discourse/NoChdir
|
||||||
|
Dir.chdir(File.expand_path("../..", __dir__)) { ::Migrations::CLI::Application.start }
|
||||||
|
# rubocop:enable Discourse/NoChdir
|
||||||
|
|
|
@ -1,52 +1,48 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Migrations::CLI::ConvertCommand
|
module Migrations::CLI
|
||||||
def self.included(thor)
|
class ConvertCommand
|
||||||
thor.class_eval do
|
def initialize(converter_type, options)
|
||||||
desc "convert [FROM]", "Convert a file"
|
@converter_type = converter_type.downcase
|
||||||
option :settings, type: :string, desc: "Path of settings file", banner: "path"
|
@options = options
|
||||||
option :reset, type: :boolean, desc: "Reset database before converting data"
|
end
|
||||||
def convert(converter_type)
|
|
||||||
converter_type = converter_type.downcase
|
|
||||||
validate_converter_type!(converter_type)
|
|
||||||
|
|
||||||
settings = load_settings(converter_type)
|
def execute
|
||||||
|
validate_converter_type!
|
||||||
|
settings = load_settings
|
||||||
|
|
||||||
::Migrations::Database.reset!(settings[:intermediate_db][:path]) if options[:reset]
|
::Migrations::Database.reset!(settings[:intermediate_db][:path]) if @options[:reset]
|
||||||
|
|
||||||
converter = "migrations/converters/#{converter_type}/converter".camelize.constantize
|
converter = "migrations/converters/#{@converter_type}/converter".camelize.constantize
|
||||||
converter.new(settings).run
|
converter.new(settings).run
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def validate_converter_type!(type)
|
def validate_converter_type!
|
||||||
converter_names = ::Migrations::Converters.names
|
converter_names = ::Migrations::Converters.names
|
||||||
|
|
||||||
raise Thor::Error, <<~MSG if !converter_names.include?(type)
|
raise Thor::Error, <<~MSG if !converter_names.include?(@converter_type)
|
||||||
Unknown converter name: #{type}
|
Unknown converter name: #{@converter_type}
|
||||||
Valid names are: #{converter_names.join(", ")}
|
Valid names are: #{converter_names.join(", ")}
|
||||||
MSG
|
MSG
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_settings_path!(settings_path)
|
def validate_settings_path!(settings_path)
|
||||||
if !File.exist?(settings_path)
|
raise Thor::Error, "Settings file not found: #{settings_path}" if !File.exist?(settings_path)
|
||||||
raise Thor::Error, "Settings file not found: #{settings_path}"
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def load_settings(converter_type)
|
def load_settings
|
||||||
settings_path = calculate_settings_path(converter_type)
|
settings_path = calculate_settings_path
|
||||||
validate_settings_path!(settings_path)
|
validate_settings_path!(settings_path)
|
||||||
|
|
||||||
YAML.safe_load(File.read(settings_path), symbolize_names: true)
|
YAML.safe_load(File.read(settings_path), symbolize_names: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def calculate_settings_path(converter_type)
|
def calculate_settings_path
|
||||||
settings_path =
|
settings_path =
|
||||||
options[:settings] || ::Migrations::Converters.default_settings_path(converter_type)
|
@options[:settings] || ::Migrations::Converters.default_settings_path(@converter_type)
|
||||||
File.expand_path(settings_path, Dir.pwd)
|
File.expand_path(settings_path, Dir.pwd)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Migrations::CLI::ImportCommand
|
require "extralite"
|
||||||
def self.included(thor)
|
|
||||||
thor.class_eval do
|
|
||||||
desc "import", "Import a file"
|
|
||||||
def import
|
|
||||||
require "extralite"
|
|
||||||
|
|
||||||
puts "Importing into Discourse #{Discourse::VERSION::STRING}"
|
module Migrations::CLI
|
||||||
puts "Extralite SQLite version: #{Extralite.sqlite3_version}"
|
class ImportCommand
|
||||||
end
|
def initialize(options)
|
||||||
|
@options = options
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute
|
||||||
|
::Migrations.load_rails_environment
|
||||||
|
|
||||||
|
puts "Importing into Discourse #{Discourse::VERSION::STRING}"
|
||||||
|
puts "Extralite SQLite version: #{Extralite.sqlite3_version}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,49 +1,40 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Migrations::CLI::UploadCommand
|
module Migrations::CLI
|
||||||
def self.included(thor)
|
class UploadCommand
|
||||||
thor.class_eval do
|
def initialize(options)
|
||||||
desc "upload", "Upload media uploads"
|
@options = options
|
||||||
option :settings,
|
end
|
||||||
type: :string,
|
|
||||||
desc: "Uploads settings file path",
|
|
||||||
default: "./migrations/config/upload.yml",
|
|
||||||
aliases: "-s",
|
|
||||||
banner: "path"
|
|
||||||
option :fix_missing, type: :boolean, desc: "Fix missing uploads"
|
|
||||||
option :optimize, type: :boolean, desc: "Optimize uploads"
|
|
||||||
def upload
|
|
||||||
puts "Starting uploads..."
|
|
||||||
|
|
||||||
validate_settings_file!
|
def execute
|
||||||
settings = load_settings
|
puts "Starting uploads..."
|
||||||
|
|
||||||
::Migrations::Uploader::Uploads.perform!(settings)
|
validate_settings_file!
|
||||||
|
settings = load_settings
|
||||||
|
|
||||||
puts ""
|
::Migrations::Uploader::Uploads.perform!(settings)
|
||||||
end
|
|
||||||
|
|
||||||
private
|
puts ""
|
||||||
|
end
|
||||||
|
|
||||||
def load_settings
|
private
|
||||||
settings = ::Migrations::SettingsParser.parse!(options.settings)
|
|
||||||
merge_settings_from_cli_args!(settings)
|
|
||||||
|
|
||||||
settings
|
def load_settings
|
||||||
end
|
settings = ::Migrations::SettingsParser.parse!(@options.settings)
|
||||||
|
merge_settings_from_cli_args!(@options, settings)
|
||||||
|
|
||||||
def merge_settings_from_cli_args!(settings)
|
settings
|
||||||
settings[:fix_missing] = options.fix_missing if options.fix_missing.present?
|
end
|
||||||
settings[:create_optimized_images] = options.optimize if options.optimize.present?
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate_settings_file!
|
def merge_settings_from_cli_args!(settings)
|
||||||
path = options.settings
|
settings[:fix_missing] = options.fix_missing if @options.fix_missing.present?
|
||||||
|
settings[:create_optimized_images] = options.optimize if @options.optimize.present?
|
||||||
|
end
|
||||||
|
|
||||||
if !File.exist?(path)
|
def validate_settings_file!
|
||||||
raise ::Migrations::NoSettingsFound, "Settings file not found: #{path}"
|
path = @options.settings
|
||||||
end
|
|
||||||
end
|
raise ::Migrations::NoSettingsFound, "Settings file not found: #{path}" if !File.exist?(path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,7 +19,7 @@ module Migrations
|
||||||
|
|
||||||
def self.load_rails_environment(quiet: false)
|
def self.load_rails_environment(quiet: false)
|
||||||
message = "Loading Rails environment ..."
|
message = "Loading Rails environment ..."
|
||||||
print message unless quiet
|
print message if !quiet
|
||||||
|
|
||||||
rails_root = File.expand_path("../..", __dir__)
|
rails_root = File.expand_path("../..", __dir__)
|
||||||
# rubocop:disable Discourse/NoChdir
|
# rubocop:disable Discourse/NoChdir
|
||||||
|
@ -33,9 +33,11 @@ module Migrations
|
||||||
end
|
end
|
||||||
# rubocop:enable Discourse/NoChdir
|
# rubocop:enable Discourse/NoChdir
|
||||||
|
|
||||||
print "\r"
|
if !quiet
|
||||||
print " " * message.length
|
print "\r"
|
||||||
print "\r"
|
print " " * message.length
|
||||||
|
print "\r"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.configure_zeitwerk
|
def self.configure_zeitwerk
|
||||||
|
@ -49,7 +51,7 @@ module Migrations
|
||||||
loader.push_dir(File.join(::Migrations.root_path, "lib"), namespace: ::Migrations)
|
loader.push_dir(File.join(::Migrations.root_path, "lib"), namespace: ::Migrations)
|
||||||
loader.push_dir(File.join(::Migrations.root_path, "lib", "common"), namespace: ::Migrations)
|
loader.push_dir(File.join(::Migrations.root_path, "lib", "common"), namespace: ::Migrations)
|
||||||
|
|
||||||
# All sub-directories of a converter should have the same namespace.
|
# All subdirectories of a converter should have the same namespace.
|
||||||
# Unfortunately `loader.collapse` doesn't work recursively.
|
# Unfortunately `loader.collapse` doesn't work recursively.
|
||||||
Converters.all.each do |name, converter_path|
|
Converters.all.each do |name, converter_path|
|
||||||
module_name = name.camelize.to_sym
|
module_name = name.camelize.to_sym
|
||||||
|
|
Loading…
Reference in New Issue