Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions emerge_cli.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Gem::Specification.new do |spec|
spec.add_dependency 'colorize', '~> 1.1.0'
spec.add_dependency 'dry-cli', '~> 1.2.0'
spec.add_dependency 'open3', '~> 0.2.1'
spec.add_dependency 'tty-prompt', '~> 0.23.1'
spec.add_dependency 'tty-table', '~> 0.12.0'

spec.add_development_dependency 'minitest', '~> 5.25.1'
spec.add_development_dependency 'minitest-reporters', '~> 1.7.1'
Expand Down
238 changes: 238 additions & 0 deletions lib/commands/config/snapshots/snapshots.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
require 'dry/cli'
require 'json'
require 'uri'
require 'chunky_png'
require 'async'
require 'async/barrier'
require 'async/semaphore'
require 'async/http/internet/instance'
require 'yaml'

require 'tty-prompt'
require 'tty-table'

module EmergeCLI
module Commands
module Config
class Snapshots < EmergeCLI::Commands::GlobalOptions
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be SnapshotsIOS so we can potentially support Android in the future.

desc 'Configure snapshot testing for iOS'

# Optional options
option :interactive, type: :boolean, required: false,
desc: 'Run interactively'
option :clear, type: :boolean, required: false, desc: 'Clear existing configuration'
option :os_version, type: :string, required: true, desc: 'OS version'
option :launch_arguments, type: :array, required: false, desc: 'Launch arguments to set'
option :env_variables, type: :array, required: false, desc: 'Environment variables to set'
option :exact_match_excluded_previews, type: :array, required: false, desc: 'Exact match excluded previews'
option :regex_excluded_previews, type: :array, required: false, desc: 'Regex excluded previews'

# Constants
EXCLUDED_PREVIEW_PROMPT = 'Do you want to exclude any previews by exact match?'.freeze
EXCLUDED_PREVIEW_FINISH_PROMPT = 'Enter the previews you want to exclude (leave blank to finish)'.freeze
EXCLUDED_REGEX_PREVIEW_PROMPT = 'Do you want to exclude any previews by regex?'.freeze
EXCLUDED_REGEX_PREVIEW_FINISH_PROMPT = 'Enter the previews you want to exclude (leave blank to finish)'.freeze
ARGUMENTS_PROMPT = 'Do you want to set any arguments?'.freeze
ARGUMENTS_FINISH_PROMPT = 'Enter the argument you want to set (leave blank to finish)'.freeze
ENV_VARIABLES_PROMPT = 'Do you want to set any environment variables?'.freeze
ENV_VARIABLES_FINISH_PROMPT = "Enter the environment variable you want to set (leave blank to finish) with \
format KEY=VALUE".freeze

def initialize; end

def call(**options)
@options = options
before(options)

begin
Sync do
validate_options

run_interactive_mode if @options[:interactive]

run_non_interactive_mode if !@options[:interactive]

Logger.warn 'Remember to copy `emerge_config.yml` to your project XCArchive before uploading it!'
end
rescue StandardError => e
Logger.error "CLI Error: #{e.message}"
end
end

private

def validate_options
if @options[:interactive] && (!@options[:os_version].nil? || !@options[:launch_arguments].nil? ||
!@options[:env_variables].nil? || !@options[:exact_match_excluded_previews].nil? ||
!@options[:regex_excluded_previews].nil?)
Logger.warn 'All options are ignored when using interactive mode'
end
end

def run_interactive_mode
prompt = TTY::Prompt.new

override_config = false
if File.exist?('emerge_config.yml')
Logger.warn 'There is already a emerge_config.yml file.'
prompt.yes?('Do you want to overwrite it?', default: false) do |answer|
override_config = true if answer
end
end

if !override_config && File.exist?('emerge_config.yml')
config = YAML.load_file('emerge_config.yml')
config['snapshots']['ios']['runSettings'] = []
else
config = {
'version' => 2.0,
'snapshots' => {
'ios' => {
'runSettings' => []
}
}
}
end

Logger.info 'Creating a new config file'

end_config = false
loop do
os_version = get_os_version(prompt)

excluded_previews = get_array_from_user(prompt, EXCLUDED_PREVIEW_PROMPT, EXCLUDED_PREVIEW_FINISH_PROMPT)
excluded_regex_previews = get_array_from_user(prompt, EXCLUDED_REGEX_PREVIEW_PROMPT,
EXCLUDED_REGEX_PREVIEW_FINISH_PROMPT)
arguments_array = get_array_from_user(prompt, ARGUMENTS_PROMPT, ARGUMENTS_FINISH_PROMPT)
env_variables_array = get_array_from_user(prompt, ENV_VARIABLES_PROMPT, ENV_VARIABLES_FINISH_PROMPT)

excluded = get_parsed_previews(excluded_previews, excluded_regex_previews)
env_variables = get_parsed_env_variables(env_variables_array)

os_settings = {
'osVersion' => os_version,
'excludedPreviews' => excluded,
'envVariables' => env_variables,
'arguments' => arguments_array
}
show_config(os_settings)
save = prompt.yes?('Do you want to save this setting?')
config['snapshots']['ios']['runSettings'].push(os_settings) if save

end_config = !prompt.yes?('Do you want to continue adding more settings?')
break if end_config
end

File.write('emerge_config.yml', config.to_yaml)
Logger.info 'Configuration file created successfully!'
end

def run_non_interactive_mode
config = {}
if File.exist?('emerge_config.yml')
config = YAML.load_file('emerge_config.yml')
if !@options[:clear] && !config['snapshots'].nil? && !config['snapshots']['ios'].nil? &&
!config['snapshots']['ios']['runSettings'].nil?
raise 'There is already a configuration file with settings. Use the --clear flag to overwrite it.'
end

config['snapshots']['ios']['runSettings'] = []

else
config = {
'version' => 2.0,
'snapshots' => {
'ios' => {
'runSettings' => []
}
}
}
end

excluded_previews = get_parsed_previews(@options[:exact_match_excluded_previews] || [],
@options[:regex_excluded_previews] || [])
env_variables = get_parsed_env_variables(@options[:env_variables] || [])

os_version = @options[:os_version]
if os_version.nil?
Logger.warn 'No OS version was provided, defaulting to 17.5'
os_version = '17.5'
end

os_settings = {
'osVersion' => os_version,
'excludedPreviews' => excluded_previews,
'envVariables' => env_variables,
'arguments' => @options[:arguments] || []
}
config['snapshots']['ios']['runSettings'].push(os_settings)
File.write('emerge_config.yml', config.to_yaml)
Logger.info 'Configuration file created successfully!'
show_config(os_settings)
end

def get_os_version(prompt)
os_version = prompt.select('Select the OS version you want to run the tests on') do |answer|
answer.choice '17.2', 17.2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we pull all of our supported OS versions into constants?

answer.choice '17.5', 17.5
answer.choice '18.0', 18.0
answer.choice 'Custom', 'custom'
end
os_version = prompt.ask('Enter the OS version you want to run the tests on') if os_version == 'custom'
os_version
end

def get_array_from_user(prompt, first_prompt_message, second_prompt_message)
continue = prompt.yes?(first_prompt_message)
return [] if !continue
array = []
loop do
item = prompt.ask(second_prompt_message)
if item == '' || item.nil?
continue = false
else
array.push(item)
end
break unless continue
end
array
end

def show_config(config)
table = TTY::Table.new(
header: %w[Key Value],
rows: config.to_a
)
puts table.render(:ascii)
end

def get_parsed_previews(previews_exact, previews_regex)
excluded = []
previews_exact.each do |preview|
excluded.push({
'type' => 'exact',
'value' => preview
})
end
previews_regex.each do |preview|
excluded.push({
'type' => 'regex',
'value' => preview
})
end
excluded
end

def get_parsed_env_variables(env_variables)
env_variables_array_fixed = []
env_variables.each do |env_variable|
key, value = env_variable.split('=')
env_variables_array_fixed.push({
'key' => key, 'value' => value
})
end
end
end
end
end
end
5 changes: 5 additions & 0 deletions lib/emerge_cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require_relative './commands/upload/snapshots/client_libraries/paparazzi'
require_relative './commands/upload/snapshots/client_libraries/default'
require_relative './commands/integrate/fastlane'
require_relative './commands/config/snapshots/snapshots'

require_relative './utils/git_info_provider'
require_relative './utils/git_result'
Expand All @@ -26,6 +27,10 @@ module EmergeCLI
register 'integrate' do |prefix|
prefix.register 'fastlane-ios', Commands::Integrate::Fastlane, aliases: ['i']
end

register 'configure' do |prefix|
prefix.register 'snapshots-ios', Commands::Config::Snapshots, aliases: ['c']
end
end

# By default the log level is INFO, but can be overridden by the --debug flag
Expand Down