teuton 2.1.10 → 2.3.1
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/README.md +15 -12
- data/bin/check_teuton +0 -2
- data/docs/changelog/ideas.md +132 -0
- data/docs/changelog/v2.1.md +14 -122
- data/docs/changelog/v2.2.md +52 -28
- data/docs/changelog/version2.1.md +4 -0
- data/docs/commands/README.md +58 -15
- data/docs/commands/example_check.md +0 -4
- data/docs/commands/example_run.md +0 -4
- data/docs/dsl/README.md +1 -1
- data/docs/dsl/definition/result.md +1 -0
- data/docs/dsl/definition/run_remote.md +12 -6
- data/docs/dsl/definition/target.md +9 -10
- data/docs/dsl/execution/export.md +27 -20
- data/docs/install/README.md +13 -18
- data/docs/install/vagrant_docker.md +1 -1
- data/docs/learn/README.md +8 -8
- data/docs/learn/example-01-target.md +25 -25
- data/docs/learn/example-02-config.md +38 -49
- data/docs/learn/example-03-remote-hosts.md +22 -22
- data/docs/learn/{example-11-first-test.md → example-04-new-test.md} +23 -24
- data/docs/learn/{example-04-use.md → example-05-use.md} +6 -6
- data/docs/learn/{example-05-debug.md → example-06-debug.md} +8 -8
- data/docs/learn/{example-06-log.md → example-07-log.md} +7 -7
- data/docs/learn/example-08-readme.md +59 -0
- data/docs/learn/example-09-preserve.md +41 -0
- data/docs/videos.md +19 -0
- data/lib/teuton/application.rb +22 -3
- data/lib/teuton/case_manager/case/builtin/main.rb +3 -19
- data/lib/teuton/case_manager/case/builtin/package.rb +7 -6
- data/lib/teuton/case_manager/case/builtin/service.rb +9 -8
- data/lib/teuton/case_manager/case/builtin/teuton_file.rb +28 -0
- data/lib/teuton/case_manager/case/builtin/teuton_host.rb +31 -0
- data/lib/teuton/case_manager/case/builtin/user.rb +8 -7
- data/lib/teuton/case_manager/case/case.rb +1 -1
- data/lib/teuton/case_manager/case/dsl/goto.rb +2 -2
- data/lib/teuton/case_manager/case/dsl/log.rb +1 -1
- data/lib/teuton/case_manager/case/dsl/macro.rb +4 -1
- data/lib/teuton/case_manager/case/dsl/send.rb +2 -1
- data/lib/teuton/case_manager/case/play.rb +2 -0
- data/lib/teuton/case_manager/case/result/ext_compare.rb +16 -0
- data/lib/teuton/case_manager/case/result/result.rb +1 -1
- data/lib/teuton/case_manager/case/runner.rb +30 -4
- data/lib/teuton/case_manager/case_manager.rb +1 -1
- data/lib/teuton/case_manager/dsl.rb +10 -0
- data/lib/teuton/case_manager/export_manager.rb +24 -5
- data/lib/teuton/case_manager/utils.rb +1 -1
- data/lib/teuton/{project/laboratory → check}/builtin.rb +0 -0
- data/lib/teuton/{project/laboratory → check}/dsl.rb +40 -28
- data/lib/teuton/{project/laboratory → check}/laboratory.rb +3 -8
- data/lib/teuton/{project/laboratory → check}/show.rb +53 -59
- data/lib/teuton/cli.rb +85 -14
- data/lib/teuton/{project/readme → readme}/dsl.rb +0 -0
- data/lib/teuton/{project/readme → readme}/lang.rb +1 -1
- data/lib/teuton/{project/readme → readme}/readme.rb +22 -18
- data/lib/teuton/report/formatter/array_formatter.rb +13 -1
- data/lib/teuton/report/formatter/base_formatter.rb +18 -5
- data/lib/teuton/{project/skeleton.rb → skeleton.rb} +7 -18
- data/lib/teuton/utils/configfile_reader.rb +121 -0
- data/lib/teuton/{project → utils}/name_file_finder.rb +46 -26
- data/lib/teuton/version.rb +8 -0
- data/lib/teuton.rb +39 -32
- metadata +109 -62
- data/lib/teuton/case_manager/case/dsl/deprecated.rb +0 -14
- data/lib/teuton/cli/check.rb +0 -38
- data/lib/teuton/cli/main.rb +0 -6
- data/lib/teuton/cli/play.rb +0 -38
- data/lib/teuton/cli/readme.rb +0 -26
- data/lib/teuton/cli/version.rb +0 -12
- data/lib/teuton/files/gitignore +0 -2
- data/lib/teuton/project/configfile_reader.rb +0 -49
- data/lib/teuton/project/project.rb +0 -80
@@ -2,25 +2,38 @@
|
|
2
2
|
|
3
3
|
# BaseFormatter class
|
4
4
|
class BaseFormatter
|
5
|
+
##
|
6
|
+
# Initialize class
|
7
|
+
# @param report (Report) Format report data
|
5
8
|
def initialize(report)
|
6
9
|
@head = report.head
|
7
10
|
@lines = report.lines
|
8
11
|
@tail = report.tail
|
9
12
|
end
|
10
13
|
|
14
|
+
##
|
15
|
+
# Execute format action
|
16
|
+
def process
|
17
|
+
raise 'Empty method!'
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Creates new output file
|
22
|
+
# @param filename (String) Path to output file
|
11
23
|
def init(filename)
|
12
24
|
@filename = filename
|
13
25
|
@file = File.open(@filename, 'w')
|
14
26
|
end
|
15
27
|
|
28
|
+
##
|
29
|
+
# Write data into output file
|
30
|
+
# @param text (String) Text data to write into output file
|
16
31
|
def w(text)
|
17
|
-
@file.write text.to_s
|
18
|
-
end
|
19
|
-
|
20
|
-
def process
|
21
|
-
raise 'Empty method!'
|
32
|
+
@file.write text.to_s
|
22
33
|
end
|
23
34
|
|
35
|
+
##
|
36
|
+
# Close open output file
|
24
37
|
def deinit
|
25
38
|
@file.close
|
26
39
|
end
|
@@ -3,13 +3,7 @@
|
|
3
3
|
require 'fileutils'
|
4
4
|
require 'rainbow'
|
5
5
|
|
6
|
-
# Skeleton
|
7
|
-
# * create
|
8
|
-
# * create_main_dir_and_files
|
9
|
-
# * create_assets_dir_and_files
|
10
|
-
# * create_dir
|
11
|
-
# * create_dirs
|
12
|
-
# * copyfile
|
6
|
+
# Skeleton module
|
13
7
|
module Skeleton
|
14
8
|
##
|
15
9
|
# Create teuton project skeleton
|
@@ -17,7 +11,7 @@ module Skeleton
|
|
17
11
|
def self.create(project_dir)
|
18
12
|
project_name = File.basename(project_dir)
|
19
13
|
puts "\n[INFO] Creating #{Rainbow(project_name).bright} project skeleton"
|
20
|
-
source_basedir = File.
|
14
|
+
source_basedir = File.dirname(__FILE__)
|
21
15
|
create_dir project_dir
|
22
16
|
create_main_dir_and_files(project_dir, source_basedir)
|
23
17
|
end
|
@@ -26,7 +20,7 @@ module Skeleton
|
|
26
20
|
# Create main dir and files
|
27
21
|
# @param project_dir (String)
|
28
22
|
# @param source_basedir (String)
|
29
|
-
def self.create_main_dir_and_files(project_dir, source_basedir)
|
23
|
+
private_class_method def self.create_main_dir_and_files(project_dir, source_basedir)
|
30
24
|
# Directory and files: Ruby script, Configfile, gitignore
|
31
25
|
items = [
|
32
26
|
{ source: 'files/config.yaml', target: 'config.yaml' },
|
@@ -42,7 +36,7 @@ module Skeleton
|
|
42
36
|
##
|
43
37
|
# Create dir
|
44
38
|
# @param dirpath (String)
|
45
|
-
def self.create_dir(dirpath)
|
39
|
+
private_class_method def self.create_dir(dirpath)
|
46
40
|
if Dir.exist? dirpath
|
47
41
|
puts "* Exists dir! => #{Rainbow(dirpath).yellow}"
|
48
42
|
else
|
@@ -55,18 +49,12 @@ module Skeleton
|
|
55
49
|
end
|
56
50
|
end
|
57
51
|
|
58
|
-
##
|
59
|
-
# Create dirs
|
60
|
-
# @param args (Array)
|
61
|
-
def self.create_dirs(*args)
|
62
|
-
args.each { |arg| create_dir arg }
|
63
|
-
end
|
64
|
-
|
65
52
|
##
|
66
53
|
# Copy file
|
67
54
|
# @param source (String) Source file
|
68
55
|
# @param dest (String) Dest file
|
69
|
-
|
56
|
+
# rubocop:disable Metrics/MethodLength
|
57
|
+
private_class_method def self.copyfile(source, dest)
|
70
58
|
if File.exist? dest
|
71
59
|
puts "* Exists file! => #{Rainbow(dest).yellow}"
|
72
60
|
else
|
@@ -79,4 +67,5 @@ module Skeleton
|
|
79
67
|
end
|
80
68
|
end
|
81
69
|
end
|
70
|
+
# rubocop:enable Metrics/MethodLength
|
82
71
|
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'json/pure'
|
5
|
+
|
6
|
+
##
|
7
|
+
# Functions that read data from ConfigFile using YAML or JSON formats
|
8
|
+
module ConfigFileReader
|
9
|
+
##
|
10
|
+
# Read config file
|
11
|
+
# @param filepath (String) Path to config file
|
12
|
+
# @return Hash with config data
|
13
|
+
def self.read(filepath)
|
14
|
+
unless File.exist?(filepath)
|
15
|
+
data = {}
|
16
|
+
data[:global] = {}
|
17
|
+
data[:alias] = {}
|
18
|
+
data[:cases] = [{ tt_members: 'anonymous' }]
|
19
|
+
return data
|
20
|
+
end
|
21
|
+
return read_yaml(filepath) if File.extname(filepath) == '.yaml'
|
22
|
+
|
23
|
+
return read_json(filepath) if File.extname(filepath) == '.json'
|
24
|
+
|
25
|
+
raise "[ERROR] ConfigFileReader: #{filepath}"
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Read YAML config file
|
30
|
+
# @param filepath (String) Path to YAML config file
|
31
|
+
# @return Hash with config data
|
32
|
+
# rubocop:disable Metrics/MethodLength
|
33
|
+
# rubocop:disable Metrics/AbcSize
|
34
|
+
# rubocop:disable Security/YAMLLoad
|
35
|
+
def self.read_yaml(filepath)
|
36
|
+
begin
|
37
|
+
data = YAML.load(File.open(filepath))
|
38
|
+
rescue StandardError => e
|
39
|
+
puts "\n" + ('=' * 80)
|
40
|
+
puts "[ERROR] ConfigFileReader#read <#{filepath}>"
|
41
|
+
puts ' I suggest to revise file format!'
|
42
|
+
puts " #{e.message}\n" + ('=' * 80)
|
43
|
+
raise "[ERROR] ConfigFileReader <#{e}>"
|
44
|
+
end
|
45
|
+
data = convert_string_keys_to_symbol(data)
|
46
|
+
data[:global] = data[:global] || {}
|
47
|
+
data[:alias] = data[:alias] || {}
|
48
|
+
data[:cases] = data[:cases] || []
|
49
|
+
read_included_files!(filepath, data)
|
50
|
+
data
|
51
|
+
end
|
52
|
+
# rubocop:enable Metrics/MethodLength
|
53
|
+
# rubocop:enable Metrics/AbcSize
|
54
|
+
# rubocop:enable Security/YAMLLoad
|
55
|
+
|
56
|
+
##
|
57
|
+
# Read JSON config file
|
58
|
+
# @param filepath (String) Path to JSON config file
|
59
|
+
# @return Hash with config data
|
60
|
+
def self.read_json(filepath)
|
61
|
+
data = JSON.parse(File.read(filepath), symbolize_names: true)
|
62
|
+
data = convert_string_keys_to_symbol(data)
|
63
|
+
data[:global] = data[:global] || {}
|
64
|
+
data[:alias] = data[:alias] || {}
|
65
|
+
data[:cases] = data[:cases] || []
|
66
|
+
read_included_files!(filepath, data)
|
67
|
+
data
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Read all configuration files from "filepath" folder.
|
72
|
+
# @param filepath (String) Folder with config files
|
73
|
+
# @param data (Hash) Input configuration
|
74
|
+
# rubocop:disable Security/YAMLLoad
|
75
|
+
private_class_method def self.read_included_files!(filepath, data)
|
76
|
+
return if data[:global][:tt_include].nil?
|
77
|
+
|
78
|
+
include_dir = data[:global][:tt_include]
|
79
|
+
if include_dir == File.absolute_path(include_dir)
|
80
|
+
basedir = include_dir
|
81
|
+
else
|
82
|
+
basedir = File.join(File.dirname(filepath), data[:global][:tt_include])
|
83
|
+
end
|
84
|
+
files = Dir.glob(File.join(basedir, '**/*.yaml'))
|
85
|
+
files += Dir.glob(File.join(basedir, '**/*.yml'))
|
86
|
+
files.each { |file|
|
87
|
+
begin
|
88
|
+
data[:cases] << YAML.load(File.open(file))
|
89
|
+
rescue StandardError => e
|
90
|
+
puts "\n" + ('=' * 80)
|
91
|
+
puts "[ERROR] ConfigFileReader#read <#{file}>"
|
92
|
+
puts ' I suggest to revise file format!'
|
93
|
+
puts " #{e.message}\n" + ('=' * 80)
|
94
|
+
end
|
95
|
+
}
|
96
|
+
end
|
97
|
+
# rubocop:enable Security/YAMLLoad
|
98
|
+
|
99
|
+
# rubocop:disable Metrics/MethodLength
|
100
|
+
# rubocop:disable Metrics/AbcSize
|
101
|
+
private_class_method def self.convert_string_keys_to_symbol(input)
|
102
|
+
return input if input.class != Hash
|
103
|
+
|
104
|
+
output = {}
|
105
|
+
input.each_pair do |key, value|
|
106
|
+
key2 = key
|
107
|
+
key2 = key.to_sym if key.class
|
108
|
+
value2 = value
|
109
|
+
if value.class == Hash
|
110
|
+
value2 = convert_string_keys_to_symbol(value)
|
111
|
+
elsif value.class == Array
|
112
|
+
value2 = []
|
113
|
+
value.each { |i| value2 << convert_string_keys_to_symbol(i) }
|
114
|
+
end
|
115
|
+
output[key2] = value2
|
116
|
+
end
|
117
|
+
output
|
118
|
+
end
|
119
|
+
# rubocop:enable Metrics/MethodLength
|
120
|
+
# rubocop:enable Metrics/AbcSize
|
121
|
+
end
|
@@ -3,8 +3,9 @@
|
|
3
3
|
require 'rainbow'
|
4
4
|
require_relative '../application'
|
5
5
|
|
6
|
-
|
7
|
-
#
|
6
|
+
##
|
7
|
+
# NameFileFinder module
|
8
|
+
# Methods: find_filenames_for, verbose, verboseln
|
8
9
|
module NameFileFinder
|
9
10
|
##
|
10
11
|
# Find project filenames from input project relative path
|
@@ -28,6 +29,8 @@ module NameFileFinder
|
|
28
29
|
##
|
29
30
|
# Find project filenames from input folder path
|
30
31
|
# @param folder_path (String)
|
32
|
+
# rubocop:disable Metrics/AbcSize
|
33
|
+
# rubocop:disable Metrics/MethodLength
|
31
34
|
def self.find_filenames_from_directory(folder_path)
|
32
35
|
# COMPLEX MODE: We use start.rb as main RB file
|
33
36
|
script_path = File.join(folder_path, 'start.rb')
|
@@ -45,15 +48,20 @@ module NameFileFinder
|
|
45
48
|
|
46
49
|
find_configfilename_from_directory(folder_path)
|
47
50
|
end
|
51
|
+
# rubocop:enable Metrics/AbcSize
|
52
|
+
# rubocop:enable Metrics/MethodLength
|
48
53
|
|
49
54
|
##
|
50
55
|
# Find project config filename from input folder path
|
51
56
|
# @param folder_path (String)
|
57
|
+
# rubocop:disable Metrics/AbcSize
|
58
|
+
# rubocop:disable Metrics/MethodLength
|
59
|
+
# rubocop:disable Style/IfUnlessModifier
|
52
60
|
def self.find_configfilename_from_directory(folder_path)
|
53
61
|
# COMPLEX MODE: We use config.yaml by default
|
54
62
|
app = Application.instance
|
55
|
-
|
56
63
|
config_path = ''
|
64
|
+
|
57
65
|
if app.options['cpath'].nil?
|
58
66
|
config_name = 'config'
|
59
67
|
# Config name file is introduced by cname arg option from teuton command
|
@@ -68,7 +76,12 @@ module NameFileFinder
|
|
68
76
|
end
|
69
77
|
app.config_path = config_path
|
70
78
|
end
|
79
|
+
# rubocop:enable Metrics/AbcSize
|
80
|
+
# rubocop:enable Metrics/MethodLength
|
81
|
+
# rubocop:enable Style/IfUnlessModifier
|
71
82
|
|
83
|
+
# rubocop:disable Metrics/AbcSize
|
84
|
+
# rubocop:disable Metrics/MethodLength
|
72
85
|
def self.find_filenames_from_rb(script_path)
|
73
86
|
# SIMPLE MODE: We use script_path as main RB file
|
74
87
|
# This must be fullpath to DSL script file
|
@@ -86,7 +99,12 @@ module NameFileFinder
|
|
86
99
|
|
87
100
|
find_configfilenames_from_rb(script_path)
|
88
101
|
end
|
102
|
+
# rubocop:enable Metrics/AbcSize
|
103
|
+
# rubocop:enable Metrics/MethodLength
|
89
104
|
|
105
|
+
# rubocop:disable Metrics/MethodLength
|
106
|
+
# rubocop:disable Metrics/AbcSize
|
107
|
+
# rubocop:disable Style/IfUnlessModifier
|
90
108
|
def self.find_configfilenames_from_rb(script_path)
|
91
109
|
# SIMPLE MODE: We use script_path as main RB file
|
92
110
|
# This must be fullpath to DSL script file
|
@@ -108,32 +126,33 @@ module NameFileFinder
|
|
108
126
|
end
|
109
127
|
app.config_path = config_path
|
110
128
|
end
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
129
|
+
# rubocop:enable Metrics/MethodLength
|
130
|
+
# rubocop:enable Metrics/AbcSize
|
131
|
+
# rubocop:enable Style/IfUnlessModifier
|
132
|
+
|
133
|
+
# def self.puts_input_info_on_screen
|
134
|
+
# app = Application.instance
|
135
|
+
#
|
136
|
+
# verbose Rainbow('[INFO] ScriptPath => ').blue
|
137
|
+
# verboseln Rainbow(trim(app.script_path)).blue.bright
|
138
|
+
# verbose Rainbow('[INFO] ConfigPath => ').blue
|
139
|
+
# verboseln Rainbow(trim(app.config_path)).blue.bright
|
140
|
+
# verbose Rainbow('[INFO] Pwd => ').blue
|
141
|
+
# verboseln Rainbow(app.running_basedir).blue.bright
|
142
|
+
# verbose Rainbow('[INFO] TestName => ').blue
|
143
|
+
# verboseln Rainbow(trim(app.test_name)).blue.bright
|
144
|
+
# end
|
124
145
|
|
125
146
|
##
|
126
147
|
# Trim string text when is too long
|
127
|
-
#
|
128
|
-
#
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
output = input.
|
133
|
-
|
134
|
-
|
135
|
-
output.to_s
|
136
|
-
end
|
148
|
+
# def self.trim(input)
|
149
|
+
# return input unless input.to_s.start_with? Dir.pwd.to_s
|
150
|
+
#
|
151
|
+
# output = input.to_s
|
152
|
+
# offset = (Dir.pwd).length + 1
|
153
|
+
# output = "#{input[offset, input.size]}"
|
154
|
+
# output.to_s
|
155
|
+
# end
|
137
156
|
|
138
157
|
def self.verboseln(text)
|
139
158
|
verbose(text + "\n")
|
@@ -142,6 +161,7 @@ module NameFileFinder
|
|
142
161
|
def self.verbose(text)
|
143
162
|
return unless Application.instance.verbose
|
144
163
|
return if Application.instance.options['quiet']
|
164
|
+
|
145
165
|
print text
|
146
166
|
end
|
147
167
|
end
|
data/lib/teuton.rb
CHANGED
@@ -1,47 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'teuton/application'
|
2
|
-
require_relative 'teuton/
|
3
|
-
require_relative 'teuton/project/skeleton'
|
4
|
+
require_relative 'teuton/skeleton'
|
4
5
|
|
5
|
-
##
|
6
|
-
# Main Teuton functions
|
7
6
|
module Teuton
|
8
|
-
##
|
9
|
-
# Create new Teuton project
|
10
7
|
def self.create(path_to_new_dir)
|
11
8
|
Skeleton.create(path_to_new_dir)
|
12
9
|
end
|
13
10
|
|
14
|
-
|
15
|
-
#
|
16
|
-
# @param
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
# * :cpath [String]
|
21
|
-
# * :case [String]
|
22
|
-
# * :quiet [Boolean]
|
23
|
-
def self.play(path_to_rb_file, options = {})
|
24
|
-
Project.play(path_to_rb_file, options)
|
11
|
+
# Run test
|
12
|
+
# @param projectpath (String) Path to teuton test
|
13
|
+
# @param options (Array) Array of input options
|
14
|
+
def self.run(projectpath, options = {})
|
15
|
+
Application.instance.add_input_params(projectpath, options)
|
16
|
+
require_dsl_and_script('teuton/case_manager/dsl') # Define DSL keywords
|
25
17
|
end
|
26
18
|
|
27
|
-
|
28
|
-
#
|
29
|
-
# @param
|
30
|
-
def self.readme(
|
31
|
-
|
19
|
+
# Create Readme file for a test
|
20
|
+
# @param projectpath (String) Path to teuton test
|
21
|
+
# @param options (Array) Array of input options
|
22
|
+
def self.readme(projectpath, options = {})
|
23
|
+
Application.instance.add_input_params(projectpath, options)
|
24
|
+
require_dsl_and_script('teuton/readme/readme') # Define DSL keywords
|
25
|
+
|
26
|
+
app = Application.instance
|
27
|
+
readme = Readme.new(app.script_path, app.config_path)
|
28
|
+
readme.show
|
32
29
|
end
|
33
30
|
|
34
|
-
|
35
|
-
#
|
36
|
-
# @param
|
37
|
-
def self.check(
|
38
|
-
|
31
|
+
# Check teuton test syntax
|
32
|
+
# @param projectpath (String) Path to teuton test
|
33
|
+
# @param options (Array) Array of input options
|
34
|
+
def self.check(projectpath, options = {})
|
35
|
+
Application.instance.add_input_params(projectpath, options)
|
36
|
+
require_dsl_and_script('teuton/check/laboratory') # Define DSL keywords
|
37
|
+
|
38
|
+
app = Application.instance
|
39
|
+
lab = Laboratory.new(app.script_path, app.config_path)
|
40
|
+
lab.show unless options[:panelconfig]
|
41
|
+
lab.show_panelconfig if options[:panelconfig]
|
39
42
|
end
|
40
43
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
private_class_method def self.require_dsl_and_script(dslpath)
|
45
|
+
app = Application.instance
|
46
|
+
require_relative dslpath
|
47
|
+
begin
|
48
|
+
require_relative app.script_path
|
49
|
+
rescue SyntaxError => e
|
50
|
+
puts e.to_s
|
51
|
+
puts Rainbow.new("[ FAIL ] SyntaxError into file #{app.script_path}").red
|
52
|
+
end
|
46
53
|
end
|
47
54
|
end
|