liri 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -2
- data/Gemfile.lock +14 -7
- data/Rakefile +5 -0
- data/lib/agent/agent.rb +74 -41
- data/lib/all_libraries.rb +3 -0
- data/lib/common/benchmarking.rb +2 -8
- data/lib/common/compressor/zip.rb +3 -2
- data/lib/common/duration.rb +28 -0
- data/lib/common/hardware.rb +29 -0
- data/lib/common/log.rb +59 -17
- data/lib/common/progressbar.rb +3 -3
- data/lib/common/source_code.rb +2 -2
- data/lib/common/tests_result.rb +28 -16
- data/lib/common/text_time_parser.rb +6 -2
- data/lib/common/tty_progressbar.rb +70 -0
- data/lib/common/unit_test/rspec_result_parser.rb +10 -0
- data/lib/hash_extend.rb +7 -0
- data/lib/liri.rb +23 -23
- data/lib/manager/credential.rb +14 -0
- data/lib/manager/manager.rb +375 -133
- data/lib/task.rb +1 -1
- data/liri.gemspec +6 -6
- data/template/liri-config.yml +74 -36
- metadata +12 -10
- data/config/locales/to_duration_es.yml +0 -25
data/lib/common/tests_result.rb
CHANGED
@@ -8,7 +8,7 @@ module Liri
|
|
8
8
|
module Common
|
9
9
|
# Esta clase se encarga de guardar y procesar el archivo de resultados
|
10
10
|
class TestsResult
|
11
|
-
attr_reader :examples, :failures, :pending, :passed
|
11
|
+
attr_reader :examples, :failures, :pending, :passed
|
12
12
|
|
13
13
|
def initialize(folder_path)
|
14
14
|
@folder_path = folder_path
|
@@ -18,9 +18,9 @@ module Liri
|
|
18
18
|
@passed = 0
|
19
19
|
@finish_in = 0
|
20
20
|
@files_load = 0
|
21
|
-
@files_processed = 0
|
22
21
|
@failures_list = ''
|
23
22
|
@failed_examples = ''
|
23
|
+
@failed_files = ''
|
24
24
|
end
|
25
25
|
|
26
26
|
def save(file_name, raw_tests_result)
|
@@ -29,34 +29,36 @@ module Liri
|
|
29
29
|
file_path
|
30
30
|
end
|
31
31
|
|
32
|
-
def build_file_name(agent_ip_address,
|
33
|
-
"batch_#{
|
32
|
+
def build_file_name(agent_ip_address, batch_num)
|
33
|
+
"batch_#{batch_num}_agent_#{agent_ip_address}_tests_results"
|
34
34
|
end
|
35
35
|
|
36
36
|
# Procesa el resultado crudo de las pruebas unitarias y lo devuelve en formato hash manejable
|
37
37
|
# Ejemplo del hash retornado:
|
38
38
|
# { examples: 0, failures: 0, pending: 0, passed: 0, finish_in: 0, files_load: 0,
|
39
39
|
# failures_list: '', failed_examples: '' }
|
40
|
-
def process(tests_result_file_name
|
40
|
+
def process(tests_result_file_name)
|
41
41
|
file_path = File.join(@folder_path, '/', tests_result_file_name)
|
42
|
+
# A veces no se encuentra el archivo de resultados, la siguiente condicional es para evitar errores relativos a esto
|
43
|
+
return {} unless File.exist?(file_path)
|
44
|
+
|
42
45
|
result_hash = process_tests_result_file(file_path)
|
43
|
-
result_hash[:files_processed] = files_processed
|
44
46
|
update_partial_result(result_hash)
|
45
47
|
result_hash
|
46
48
|
end
|
47
49
|
|
48
50
|
def print_summary
|
49
|
-
|
51
|
+
Liri.logger.info("\n#{@examples} examples, #{@passed} passed, #{@failures} failures\n", true)
|
50
52
|
end
|
51
53
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
54
|
+
def print_detailed_failures
|
55
|
+
Liri.logger.info("\nFailures: ", true) unless @failures_list.empty?
|
56
|
+
Liri.logger.info(@failures_list, true)
|
55
57
|
end
|
56
58
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
59
|
+
def print_summary_failures
|
60
|
+
Liri.logger.info("\nFailed examples: ", true) unless @failed_examples.empty?
|
61
|
+
Liri.logger.info(@failed_examples, true)
|
60
62
|
end
|
61
63
|
|
62
64
|
private
|
@@ -67,7 +69,7 @@ module Liri
|
|
67
69
|
# {result: '.F', failures: '', examples: 2, failures: 1, failed_examples: ''}
|
68
70
|
def process_tests_result_file(file_path)
|
69
71
|
result_hash = { examples: 0, failures: 0, pending: 0, passed: 0, finish_in: 0, files_load: 0,
|
70
|
-
failures_list: '', failed_examples: '' }
|
72
|
+
failures_list: '', failed_examples: '', failed_files: '' }
|
71
73
|
flag = ''
|
72
74
|
@failures_lists_count = @failures
|
73
75
|
File.foreach(file_path) do |line|
|
@@ -106,7 +108,10 @@ module Liri
|
|
106
108
|
result_hash[:pending] = values[:pending]
|
107
109
|
flag = ''
|
108
110
|
when 'Failed'
|
109
|
-
|
111
|
+
if line.strip.start_with?('rspec')
|
112
|
+
result_hash[:failed_examples] << line
|
113
|
+
result_hash[:failed_files] << "#{failed_example(line)}\n"
|
114
|
+
end
|
110
115
|
end
|
111
116
|
end
|
112
117
|
|
@@ -118,9 +123,9 @@ module Liri
|
|
118
123
|
@failures += hash_result[:failures]
|
119
124
|
@pending += hash_result[:pending]
|
120
125
|
@passed += hash_result[:passed]
|
121
|
-
@files_processed += hash_result[:files_processed]
|
122
126
|
@failures_list << hash_result[:failures_list]
|
123
127
|
@failed_examples << hash_result[:failed_examples]
|
128
|
+
@failed_files << hash_result[:failed_files]
|
124
129
|
end
|
125
130
|
|
126
131
|
def finish_in_values(line)
|
@@ -131,6 +136,13 @@ module Liri
|
|
131
136
|
UnitTest::RspecResultParser.finished_summary_values(line)
|
132
137
|
end
|
133
138
|
|
139
|
+
def failed_example(line)
|
140
|
+
# get string like this "/spec/failed_spec.rb:4"
|
141
|
+
failed_example = UnitTest::RspecResultParser.failed_example(line)
|
142
|
+
# return "failed_spec.rb:4"
|
143
|
+
failed_example.split("/").last
|
144
|
+
end
|
145
|
+
|
134
146
|
def fix_failure_number(line)
|
135
147
|
line_number_regex = /(\d+\))/
|
136
148
|
if line.strip.start_with?(line_number_regex)
|
@@ -38,8 +38,12 @@ module Liri
|
|
38
38
|
when 'minute', 'minutes' then time * 60
|
39
39
|
when 'hour', 'hours' then time * 3600
|
40
40
|
when 'day', 'days' then time * 86_400
|
41
|
-
|
42
|
-
|
41
|
+
end
|
42
|
+
|
43
|
+
# time in seconds puede contener valores BigDecimal como este 0.744e2 que al hacerle to_f devuelve 74.4
|
44
|
+
# Aún así conviene mantener el valor en BigDecimal para las operaciones matematicas y solo cuando se va a mostrar
|
45
|
+
# los datos en pantalla se debe hacer el to_f
|
46
|
+
time_in_seconds
|
43
47
|
end
|
44
48
|
end
|
45
49
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# = tty_progressbar.rb
|
2
|
+
#
|
3
|
+
# @author Rodrigo Fernández
|
4
|
+
#
|
5
|
+
# == Módulo TtyProgressbar
|
6
|
+
require "tty-progressbar"
|
7
|
+
|
8
|
+
module Liri
|
9
|
+
module Common
|
10
|
+
# Este módulo se encarga de mostrar una barra de progreso
|
11
|
+
module TtyProgressbar
|
12
|
+
ANIMATION = [
|
13
|
+
"■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□",
|
14
|
+
"□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■",
|
15
|
+
"□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□",
|
16
|
+
"□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□□■□□",
|
17
|
+
]
|
18
|
+
|
19
|
+
ANIMATION2 = [
|
20
|
+
"■□□□■□□□■□□□■□□□■□□",
|
21
|
+
"□■□□□■□□□■□□□■□□□■□",
|
22
|
+
"□□■□□□■□□□■□□□■□□□■",
|
23
|
+
"□□□■□□□■□□□■□□□■□□□",
|
24
|
+
]
|
25
|
+
class << self
|
26
|
+
# Example:
|
27
|
+
# Common::TtyProgressbar.start("Compressing source code |:bar| Time: :elapsed", total: nil, width: 80) do
|
28
|
+
# ...code
|
29
|
+
# end
|
30
|
+
def start(format, params = {})
|
31
|
+
params[:unknown] = ANIMATION[0]
|
32
|
+
progressbar = TTY::ProgressBar.new(format, params)
|
33
|
+
# Es importante iniciar la barra porque TimeFormatter.call accede a su start_time y si no se inició la barra
|
34
|
+
# entonces ocurre un error
|
35
|
+
progressbar.start
|
36
|
+
progressbar.use(Common::TtyProgressbar::TimeFormatter)
|
37
|
+
|
38
|
+
Thread.new do
|
39
|
+
animation_count = 0
|
40
|
+
while !progressbar.stopped?
|
41
|
+
progressbar.advance
|
42
|
+
|
43
|
+
progressbar.update(unknown: ANIMATION[animation_count])
|
44
|
+
animation_count += 1
|
45
|
+
animation_count = 0 if animation_count == 3
|
46
|
+
|
47
|
+
sleep(0.1)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
yield
|
51
|
+
progressbar.update(total: 1) # Esto hace que la barra cambie a al estilo completado con un porcentaje del 100%
|
52
|
+
progressbar.stop
|
53
|
+
rescue TypeError
|
54
|
+
# Se captura la excepción solo para evitar un error en start_time mas abajo
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# From
|
59
|
+
class TimeFormatter
|
60
|
+
include TTY::ProgressBar::Formatter[/:time/i]
|
61
|
+
|
62
|
+
def call(value) # specify how display string is formatted
|
63
|
+
# access current progress bar instance to read start time
|
64
|
+
elapsed = Duration.humanize(Time.now - progress.start_time, times_round: Liri.times_round, times_round_type: Liri.times_round_type)
|
65
|
+
value.gsub(matcher, elapsed) # replace :time token with a value
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -25,6 +25,16 @@ module Liri
|
|
25
25
|
{ examples: examples.to_i, failures: failures.to_i, pending: pending.to_i }
|
26
26
|
end
|
27
27
|
|
28
|
+
# Received string like this "rspec ./spec/failed_spec.rb:4 # Liri debería fallar a propósito" and
|
29
|
+
# return string like this "/spec/failed_spec.rb:4"
|
30
|
+
# or for "rspec ./spec/system/management/budget_investments_spec.rb[1:3:1:3] # Budget Investments behaves like mappable At new_management_budget_investment_path Should create budget_investment with map"
|
31
|
+
# return "/spec/system/management/budget_investments_spec.rb[1:3:1:3]"
|
32
|
+
def failed_example(failed_example_line)
|
33
|
+
values = failed_example_line.to_s.match(/(\/.+.rb:\d+)/)
|
34
|
+
values ||= failed_example_line.to_s.match(/(\/.+.rb.*\])/)
|
35
|
+
values[1] # failed_example
|
36
|
+
end
|
37
|
+
|
28
38
|
private
|
29
39
|
|
30
40
|
def text_value_to_seconds(text)
|
data/lib/hash_extend.rb
CHANGED
@@ -56,4 +56,11 @@ class Hash
|
|
56
56
|
keys.flatten.each { |key| delete(key) }
|
57
57
|
self
|
58
58
|
end
|
59
|
+
|
60
|
+
# Retorna un nuevo hash con los elementos borrados según las claves indicadas
|
61
|
+
def remove(*keys)
|
62
|
+
cloned_hash = self.clone
|
63
|
+
keys.flatten.each { |key| cloned_hash.delete(key) }
|
64
|
+
cloned_hash
|
65
|
+
end
|
59
66
|
end
|
data/lib/liri.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Este modulo contiene datos del programa que son reutilizados en otras partes de la aplicacion
|
4
4
|
module Liri
|
5
5
|
NAME = 'liri' # El gemspec requiere que el nombre este en minusculas
|
6
|
-
VERSION = '0.
|
6
|
+
VERSION = '0.4.0'
|
7
7
|
|
8
8
|
class << self
|
9
9
|
def set_setup(destination_folder_path, program, manager_tests_results_folder_time: nil)
|
@@ -44,16 +44,13 @@ module Liri
|
|
44
44
|
@setup_manager ? @setup_manager.delete_setup_folder : false
|
45
45
|
end
|
46
46
|
|
47
|
-
def init_exit(stop, threads
|
47
|
+
def init_exit(stop, threads)
|
48
48
|
threads = threads.compact
|
49
49
|
kill(threads) if stop
|
50
50
|
|
51
51
|
# Con la siguiente línea se asegura que los hilos no mueran antes de que finalize el programa principal
|
52
52
|
# Fuente: https://underc0de.org/foro/ruby/hilos-en-ruby/
|
53
53
|
threads.each{|thread| thread.join}
|
54
|
-
#rescue SignalException => e
|
55
|
-
#puts "\nEjecución del #{program} terminada manualmente\n"
|
56
|
-
#kill(threads)
|
57
54
|
end
|
58
55
|
|
59
56
|
def kill(threads)
|
@@ -66,39 +63,35 @@ module Liri
|
|
66
63
|
end
|
67
64
|
|
68
65
|
def compression_class
|
69
|
-
"Liri::Common::Compressor::#{setup.library.compression}"
|
66
|
+
"Liri::Common::Compressor::#{setup.general.library.compression}"
|
70
67
|
end
|
71
68
|
|
72
69
|
def unit_test_class
|
73
|
-
"Liri::Common::UnitTest::#{setup.library.unit_test}"
|
70
|
+
"Liri::Common::UnitTest::#{setup.general.library.unit_test}"
|
74
71
|
end
|
75
72
|
|
76
73
|
def udp_port
|
77
|
-
setup.ports.udp
|
74
|
+
setup.general.ports.udp
|
78
75
|
end
|
79
76
|
|
80
77
|
def tcp_port
|
81
|
-
setup.ports.tcp
|
78
|
+
setup.general.ports.tcp
|
82
79
|
end
|
83
80
|
|
84
|
-
def
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
def print_failed_examples
|
89
|
-
setup.print_failed_examples
|
81
|
+
def current_folder_ruby_and_gemset
|
82
|
+
"#{File.read('.ruby-version').strip}@#{File.read('.ruby-gemset').strip}"
|
90
83
|
end
|
91
84
|
|
92
|
-
def
|
93
|
-
setup.
|
85
|
+
def ignored_folders_in_compress
|
86
|
+
setup.general.ignored_folders_in_compress
|
94
87
|
end
|
95
88
|
|
96
|
-
def
|
97
|
-
setup.
|
89
|
+
def times_round
|
90
|
+
setup.general.times_round
|
98
91
|
end
|
99
92
|
|
100
|
-
def
|
101
|
-
|
93
|
+
def times_round_type
|
94
|
+
setup.general.times_round_type.to_sym
|
102
95
|
end
|
103
96
|
|
104
97
|
private
|
@@ -113,7 +106,7 @@ module Liri
|
|
113
106
|
|
114
107
|
# Inicializa y configura la librería encargada de loguear
|
115
108
|
def load_logger(folder_path = nil, file_name = nil)
|
116
|
-
log = Liri::Common::Log.new('daily', folder_path: folder_path, file_name: file_name, stdout: setup.log.stdout.show)
|
109
|
+
log = Liri::Common::Log.new('daily', folder_path: folder_path, file_name: file_name, stdout: setup.general.log.stdout.show)
|
117
110
|
log
|
118
111
|
end
|
119
112
|
end
|
@@ -121,7 +114,14 @@ module Liri
|
|
121
114
|
# EXCEPTIONS
|
122
115
|
class FileNotFoundError < StandardError
|
123
116
|
def initialize(file_path)
|
124
|
-
msg = "
|
117
|
+
msg = "File not found #{file_path}"
|
118
|
+
super(msg)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class InxiCommandNotFoundError < StandardError
|
123
|
+
def initialize
|
124
|
+
msg = "Inxi command not found"
|
125
125
|
super(msg)
|
126
126
|
end
|
127
127
|
end
|
data/lib/manager/credential.rb
CHANGED
@@ -31,6 +31,11 @@ module Liri
|
|
31
31
|
else
|
32
32
|
return nil, nil
|
33
33
|
end
|
34
|
+
rescue Psych::SyntaxError
|
35
|
+
# Este error ocurre cuando se guardan caracteres raros en el archivo liri-credentials.yml
|
36
|
+
# en este caso se borra el archivo y se pide de nuevo la contraseña
|
37
|
+
delete_credentials
|
38
|
+
return nil, nil
|
34
39
|
end
|
35
40
|
|
36
41
|
def ask_credentials
|
@@ -42,6 +47,15 @@ module Liri
|
|
42
47
|
def save_credentials(user, password)
|
43
48
|
File.write(@file_path, "user: #{user}\npassword: #{password}")
|
44
49
|
end
|
50
|
+
|
51
|
+
def delete_credentials
|
52
|
+
if File.exist?(@file_path)
|
53
|
+
File.delete(@file_path)
|
54
|
+
File.exist?(@file_path) ? false : true
|
55
|
+
else
|
56
|
+
false
|
57
|
+
end
|
58
|
+
end
|
45
59
|
end
|
46
60
|
end
|
47
61
|
end
|