169 lines
4.1 KiB
Ruby
Executable File
169 lines
4.1 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
|
# frozen_string_literal: true
|
|
|
|
# Generate an Elastic migration file, spec and dictionary record with the current timestamp.
|
|
|
|
require 'yaml'
|
|
require 'fileutils'
|
|
require 'uri'
|
|
require 'readline'
|
|
require 'active_support'
|
|
require 'active_support/core_ext/string'
|
|
|
|
class ElasticMigrationCreator
|
|
attr_reader :options
|
|
|
|
Options = Struct.new(
|
|
:name,
|
|
:description,
|
|
:group,
|
|
:introduced_by_url,
|
|
:milestone,
|
|
:obsolete,
|
|
:marked_obsolete_by_url,
|
|
:marked_obsolete_in_milestone
|
|
)
|
|
|
|
def initialize
|
|
@options = Options.new
|
|
end
|
|
|
|
def execute
|
|
options.name = read_name
|
|
options.description = read_description
|
|
options.group = read_group
|
|
options.introduced_by_url = read_introduced_by_url
|
|
options.milestone = read_milestone
|
|
|
|
$stdout.puts "\e[32mcreated\e[0m #{file_path}"
|
|
$stdout.puts "\e[32mcreated\e[0m #{spec_file_path}"
|
|
$stdout.puts "\e[32mcreated\e[0m #{dictionary_file_path}"
|
|
|
|
write
|
|
$stdout.puts "\n=> Please consult the documentation for Advanced Search Migrations: #{documentation_reference}"
|
|
end
|
|
|
|
private
|
|
|
|
def read_name
|
|
read_variable('name', 'Name of the migration in CamelCase').camelize
|
|
end
|
|
|
|
def read_description
|
|
read_variable('description', 'Description of what the migration does')
|
|
end
|
|
|
|
def read_group
|
|
read_variable('group', 'The group introducing a feature flag, like: `global search`')
|
|
end
|
|
|
|
def read_milestone
|
|
milestone = File.read('VERSION')
|
|
milestone.gsub(/^(\d+\.\d+).*$/, '\1').chomp
|
|
end
|
|
|
|
def read_variable(name, description)
|
|
$stdout.puts "\n>> #{description}:"
|
|
|
|
loop do
|
|
variable = Readline.readline('?> ', false)&.strip
|
|
return variable unless variable.empty?
|
|
|
|
warn "Error: #{name} is required."
|
|
end
|
|
end
|
|
|
|
def read_introduced_by_url
|
|
$stdout.puts
|
|
$stdout.puts ">> URL of the MR introducing the migration (enter to skip):"
|
|
|
|
loop do
|
|
introduced_by_url = Readline.readline('?> ', false)&.strip
|
|
introduced_by_url = nil if introduced_by_url.empty?
|
|
return introduced_by_url if introduced_by_url.nil? || introduced_by_url.start_with?('https://')
|
|
|
|
warn 'Error: URL needs to start with https://'
|
|
end
|
|
end
|
|
|
|
def write
|
|
# create migration file
|
|
FileUtils.mkdir_p(File.dirname(file_path))
|
|
File.write(file_path, file_contents)
|
|
|
|
# create spec
|
|
FileUtils.mkdir_p(File.dirname(spec_file_path))
|
|
File.write(spec_file_path, spec_contents)
|
|
|
|
# create dictionary file
|
|
FileUtils.mkdir_p(File.dirname(dictionary_file_path))
|
|
File.write(dictionary_file_path, dictionary_contents)
|
|
end
|
|
|
|
def timestamp
|
|
@timestamp ||= Time.now.strftime('%Y%m%d%H%M%S')
|
|
end
|
|
|
|
def file_name
|
|
@file_name ||= "#{timestamp}_#{options.name.dup.underscore}"
|
|
end
|
|
|
|
def file_path
|
|
"ee/elastic/migrate/#{file_name}.rb"
|
|
end
|
|
|
|
def spec_file_path
|
|
"ee/spec/elastic/migrate/#{file_name}_spec.rb"
|
|
end
|
|
|
|
def dictionary_file_path
|
|
"ee/elastic/docs/#{file_name}.yml"
|
|
end
|
|
|
|
def file_contents
|
|
"# frozen_string_literal: true
|
|
|
|
class #{options.name} < Elastic::Migration
|
|
end
|
|
"
|
|
end
|
|
|
|
def spec_contents
|
|
"# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
require File.expand_path('#{file_path}')
|
|
|
|
# See https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#elasticsearch-specs
|
|
# for more information on how to write search migration specs for GitLab.
|
|
RSpec.describe #{options.name}, feature_category: :#{options.group.parameterize.underscore} do
|
|
let(:version) { #{timestamp} }
|
|
end
|
|
"
|
|
end
|
|
|
|
def dictionary_contents
|
|
dictionary_config_hash.to_yaml
|
|
end
|
|
|
|
def dictionary_config_hash
|
|
{
|
|
'name' => options.name,
|
|
'version' => timestamp,
|
|
'description' => options.description,
|
|
'group' => "group::#{options.group}",
|
|
'milestone' => options.milestone.to_s,
|
|
'introduced_by_url' => options.introduced_by_url,
|
|
'obsolete' => false,
|
|
'marked_obsolete_by_url' => nil,
|
|
'marked_obsolete_in_milestone' => nil
|
|
}
|
|
end
|
|
|
|
def documentation_reference
|
|
'https://docs.gitlab.com/ee/development/search/advanced_search_migration_styleguide.html'
|
|
end
|
|
end
|
|
|
|
ElasticMigrationCreator.new.execute if $PROGRAM_NAME == __FILE__
|