ree_spec 0.0.4 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/ree_spec/packages/ree_spec_cli/package/ree_spec_cli/run_command.rb +3 -3
- data/lib/ree_spec/packages/ree_spec_cli/package/ree_spec_cli/services/command_builder.rb +16 -17
- data/lib/ree_spec/packages/ree_spec_cli/package/ree_spec_cli/services/run_specs.rb +133 -29
- data/lib/ree_spec/packages/ree_spec_cli/package/ree_spec_cli.rb +4 -0
- data/lib/ree_spec/packages/ree_spec_cli/spec/ree_spec_cli/run_command_spec.rb +2 -0
- data/lib/ree_spec/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 971f1556635ff273e2a921facab36b08918b9d3cddfa236146e054ee59114bbb
|
4
|
+
data.tar.gz: 44d05a565bd7cd4683274361594d90bae3cbdd0d443044b71276cd8a7f77bb38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e366fe6c67b093aef3a47bf71edb74fb283a1d9d098c51f3cbab46f2b190bf644e17645cca216192eccac4d7e47a25982be14c4da3f85c9dfbb9826341fdd74b
|
7
|
+
data.tar.gz: b74d0c9e98c680445835ac9d366e6e4e6f8a6cbc76fa8526cd4001f6d20cf804f68394a053bd3a03f52f1a3b9eaec0f821dcb869987965f8986387d551ff8da4
|
data/Gemfile.lock
CHANGED
@@ -9,10 +9,10 @@ class ReeSpecCli::RunCommand
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def call
|
12
|
-
action_proc = Proc.new do |package_names, spec_matcher, tag, files, run_all, project_path, process_count
|
12
|
+
action_proc = Proc.new do |package_names, spec_matcher, tag, files, run_all, only_failed, project_path, process_count|
|
13
13
|
run_specs(
|
14
|
-
package_names, spec_matcher, tag, files, run_all,
|
15
|
-
project_path, process_count
|
14
|
+
package_names, spec_matcher, tag, files, run_all, only_failed,
|
15
|
+
project_path, process_count
|
16
16
|
)
|
17
17
|
end
|
18
18
|
|
@@ -2,14 +2,12 @@ class ReeSpecCli::CommandBuilder
|
|
2
2
|
include Commander::Methods
|
3
3
|
|
4
4
|
DEFAULT_PROCESS_COUNT = 1
|
5
|
-
DEFAULT_SPECS_PER_PROCESS_COUNT = 5
|
6
5
|
|
7
6
|
def build(&action_proc)
|
8
7
|
files = []
|
9
8
|
package_names = []
|
10
9
|
run_all = false
|
11
10
|
process_count = DEFAULT_PROCESS_COUNT
|
12
|
-
specs_per_process = DEFAULT_SPECS_PER_PROCESS_COUNT
|
13
11
|
|
14
12
|
program :name, "Ree Spec"
|
15
13
|
program :version, "1.0"
|
@@ -25,7 +23,8 @@ class ReeSpecCli::CommandBuilder
|
|
25
23
|
c.example "ree spec --tag wip", "Run specs for packages which have \"wip\" tag"
|
26
24
|
c.option "--project_path [ROOT_DIR]", String, "Root project dir path"
|
27
25
|
c.option "--tag TAG_NAME", String, "Run specs for packages with specified tag"
|
28
|
-
c.option "--parallel
|
26
|
+
c.option "--parallel PROCESS_COUNT", String, "Run specs in parallel processes (e.g. --parallel 15, 15 processes)"
|
27
|
+
c.option "--only-failed", "Run only failed specs from previous run"
|
29
28
|
|
30
29
|
c.option "-f SPEC_FILE", "--fule SPEC_FILE", String, "List of spec files" do |f|
|
31
30
|
files ||= []
|
@@ -39,11 +38,16 @@ class ReeSpecCli::CommandBuilder
|
|
39
38
|
c.action do |args, options|
|
40
39
|
package_name = args[0]&.to_sym
|
41
40
|
spec_matcher = args[1]
|
42
|
-
options_hash = options.__hash__
|
43
|
-
options_hash.delete(:trace)
|
44
41
|
|
45
|
-
if
|
46
|
-
|
42
|
+
if options.project_path
|
43
|
+
path = File.expand_path(options.project_path.to_s)
|
44
|
+
|
45
|
+
if !File.directory?(path)
|
46
|
+
puts("Project path not found: #{options.project_path}")
|
47
|
+
exit 1
|
48
|
+
end
|
49
|
+
|
50
|
+
options.project_path = File.expand_path(options.project_path.to_s)
|
47
51
|
end
|
48
52
|
|
49
53
|
if package_name
|
@@ -54,13 +58,8 @@ class ReeSpecCli::CommandBuilder
|
|
54
58
|
run_all = true
|
55
59
|
end
|
56
60
|
|
57
|
-
if
|
58
|
-
|
59
|
-
process_count = Integer(parallel.first)
|
60
|
-
|
61
|
-
if parallel.size > 1
|
62
|
-
specs_per_process = Integer(parallel.last)
|
63
|
-
end
|
61
|
+
if options.parallel
|
62
|
+
process_count = Integer(options.parallel)
|
64
63
|
end
|
65
64
|
|
66
65
|
if package_names.size > 1
|
@@ -68,9 +67,9 @@ class ReeSpecCli::CommandBuilder
|
|
68
67
|
end
|
69
68
|
|
70
69
|
action_proc.call(
|
71
|
-
package_names, spec_matcher,
|
72
|
-
run_all,
|
73
|
-
process_count
|
70
|
+
package_names, spec_matcher, options.tag, files,
|
71
|
+
run_all, !!options.only_failed, options.project_path || File.expand_path(Dir.pwd),
|
72
|
+
process_count
|
74
73
|
)
|
75
74
|
end
|
76
75
|
end
|
@@ -2,21 +2,23 @@ class ReeSpecCli::RunSpecs
|
|
2
2
|
include Ree::FnDSL
|
3
3
|
|
4
4
|
fn :run_specs do
|
5
|
-
link :in_groups_of, from: :ree_array
|
6
5
|
link :run_package_specs
|
6
|
+
link :from_json, from: :ree_json
|
7
|
+
link :symbolize_keys, from: :ree_hash
|
8
|
+
link :group_by, from: :ree_array
|
9
|
+
link :index_by, from: :ree_array
|
10
|
+
link :to_hash, from: :ree_object
|
11
|
+
link :to_json, from: :ree_json
|
7
12
|
end
|
8
13
|
|
9
|
-
|
14
|
+
SPEC_META_FILENAME = "ree_spec_meta.json"
|
10
15
|
|
11
|
-
contract ArrayOf[Symbol], Nilor[String], Nilor[String], ArrayOf[String], Bool,
|
12
|
-
def call(package_names, spec_matcher, tag, files, run_all, project_path,
|
13
|
-
process_count, specs_per_process)
|
16
|
+
contract ArrayOf[Symbol], Nilor[String], Nilor[String], ArrayOf[String], Bool, Bool, String, Integer => nil
|
17
|
+
def call(package_names, spec_matcher, tag, files, run_all, only_failed, project_path, process_count)
|
14
18
|
init_ree_project(project_path)
|
15
19
|
|
16
20
|
packages = filter_packages_to_run(package_names, tag, run_all)
|
17
|
-
|
18
|
-
jobs = get_jobs(packages, specs_per_process, spec_matcher, files)
|
19
|
-
|
21
|
+
jobs, meta_index = get_jobs(packages, spec_matcher, files, only_failed)
|
20
22
|
processes = build_processes(process_count)
|
21
23
|
error_files = []
|
22
24
|
success_files = []
|
@@ -29,9 +31,35 @@ class ReeSpecCli::RunSpecs
|
|
29
31
|
|
30
32
|
processes[number] = Process.fork do
|
31
33
|
print_start_message(job)
|
32
|
-
result = run_package_specs(job.package, job.files, number)
|
33
34
|
|
34
|
-
|
35
|
+
prev_meta = meta_index[job.abs_path]
|
36
|
+
start_time = Time.now
|
37
|
+
|
38
|
+
result = run_package_specs(job.package, [job.abs_path], number)
|
39
|
+
|
40
|
+
end_time = Time.now
|
41
|
+
exec_time = end_time - start_time
|
42
|
+
is_success = result.status.exitstatus == 0
|
43
|
+
|
44
|
+
duration = if is_success
|
45
|
+
exec_time
|
46
|
+
elsif prev_meta
|
47
|
+
prev_meta.duration
|
48
|
+
else
|
49
|
+
exec_time
|
50
|
+
end
|
51
|
+
|
52
|
+
update_scan_metadata(
|
53
|
+
SpecMeta.new(
|
54
|
+
package: job.package.name.to_s,
|
55
|
+
abs_path: job.abs_path,
|
56
|
+
duration: duration,
|
57
|
+
last_scan_at: Time.now,
|
58
|
+
success: is_success
|
59
|
+
)
|
60
|
+
)
|
61
|
+
|
62
|
+
if !is_success
|
35
63
|
error_file.write(result.out)
|
36
64
|
error_file.rewind
|
37
65
|
puts(result.out)
|
@@ -83,7 +111,7 @@ class ReeSpecCli::RunSpecs
|
|
83
111
|
end
|
84
112
|
|
85
113
|
def print_start_message(job)
|
86
|
-
puts("
|
114
|
+
puts("Running spec for :#{job.package.name}:\n#{job.abs_path}")
|
87
115
|
end
|
88
116
|
|
89
117
|
def print_messages(error_files, success_files)
|
@@ -114,28 +142,58 @@ class ReeSpecCli::RunSpecs
|
|
114
142
|
end
|
115
143
|
|
116
144
|
pid = Process.wait
|
117
|
-
number = processes.find { |_, v| v == pid }
|
145
|
+
number = processes.find { |_, v| v == pid }.first
|
118
146
|
processes[number] = nil
|
119
147
|
number
|
120
148
|
end
|
121
149
|
|
122
|
-
class Job
|
150
|
+
class Job
|
151
|
+
include ReeDto::DSL
|
152
|
+
|
153
|
+
build_dto do
|
154
|
+
field :package, Ree::Package
|
155
|
+
field :abs_path, String
|
156
|
+
end
|
157
|
+
end
|
123
158
|
|
124
|
-
def get_jobs(package_names,
|
159
|
+
def get_jobs(package_names, spec_matcher, files, only_failed)
|
160
|
+
prev_scan_meta = read_prev_scan_metadata
|
125
161
|
result = []
|
126
162
|
packages = package_names.map { packages_facade.get_package(_1) }
|
163
|
+
scan_index = index_by(prev_scan_meta) { _1.abs_path }
|
127
164
|
|
128
165
|
packages.each do |package|
|
129
|
-
dir = Ree::PathHelper.abs_package_module_dir(package)
|
130
|
-
|
131
166
|
spec_files = get_spec_files(package, spec_matcher, files)
|
132
167
|
|
133
|
-
|
134
|
-
result << Job.new(package
|
168
|
+
spec_files.each do |abs_path|
|
169
|
+
result << Job.new(package:, abs_path:)
|
135
170
|
end
|
136
171
|
end
|
137
172
|
|
138
|
-
|
173
|
+
if only_failed
|
174
|
+
result = result.select do |item|
|
175
|
+
if scan_index[item.abs_path]
|
176
|
+
!scan_index[item.abs_path].success
|
177
|
+
else
|
178
|
+
false
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
cur_min_duration = prev_scan_meta.min { _1.duration }&.duration || 0
|
184
|
+
|
185
|
+
result.sort_by do |item|
|
186
|
+
dur = if el = scan_index[item.abs_path]
|
187
|
+
el.duration
|
188
|
+
else
|
189
|
+
cur_min_duration -= 1
|
190
|
+
cur_min_duration
|
191
|
+
end
|
192
|
+
|
193
|
+
-dur
|
194
|
+
end
|
195
|
+
|
196
|
+
[result, scan_index]
|
139
197
|
end
|
140
198
|
|
141
199
|
def get_spec_files(package, spec_matcher, files)
|
@@ -172,21 +230,11 @@ class ReeSpecCli::RunSpecs
|
|
172
230
|
result
|
173
231
|
end
|
174
232
|
end
|
175
|
-
elsif files && files.size > 0
|
176
|
-
files
|
177
233
|
else
|
178
234
|
all_specs
|
179
235
|
end
|
180
236
|
end
|
181
237
|
|
182
|
-
def calculate_specs_per_process(process_count, specs_per_process)
|
183
|
-
if process_count > 1
|
184
|
-
specs_per_process
|
185
|
-
else
|
186
|
-
MAX_SPECS_PER_PROCESS
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
238
|
def filter_packages_to_run(package_names, tag, run_all)
|
191
239
|
packages_to_run = []
|
192
240
|
|
@@ -238,4 +286,60 @@ class ReeSpecCli::RunSpecs
|
|
238
286
|
package.tags.include?(tag)
|
239
287
|
end
|
240
288
|
end
|
289
|
+
|
290
|
+
def spec_meta_file_name
|
291
|
+
dir = Dir.pwd
|
292
|
+
File.join(dir, SPEC_META_FILENAME)
|
293
|
+
end
|
294
|
+
|
295
|
+
def read_prev_scan_metadata
|
296
|
+
path = spec_meta_file_name
|
297
|
+
|
298
|
+
if File.exist?(path)
|
299
|
+
result = begin
|
300
|
+
from_json(File.read(path))
|
301
|
+
rescue
|
302
|
+
[]
|
303
|
+
end
|
304
|
+
|
305
|
+
build_metadata(result)
|
306
|
+
else
|
307
|
+
build_metadata([])
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def update_scan_metadata(spec_meta)
|
312
|
+
meta = read_prev_scan_metadata
|
313
|
+
prev_spec = meta.find { _1.abs_path == spec_meta.abs_path }
|
314
|
+
meta.delete(prev_spec) if prev_spec
|
315
|
+
meta << spec_meta
|
316
|
+
|
317
|
+
result = to_json(meta.map { to_hash(_1) })
|
318
|
+
|
319
|
+
File.open(spec_meta_file_name, "w") do |f|
|
320
|
+
f.flock(File::LOCK_EX)
|
321
|
+
f.write(result)
|
322
|
+
f.flock(File::LOCK_UN)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
class SpecMeta
|
327
|
+
include ReeDto::DSL
|
328
|
+
|
329
|
+
build_dto do
|
330
|
+
field :package, String
|
331
|
+
field :abs_path, String
|
332
|
+
field :duration, Float
|
333
|
+
field :last_scan_at, Time
|
334
|
+
field :success, Bool
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def build_metadata(data)
|
339
|
+
data.map do |d|
|
340
|
+
SpecMeta.new(symbolize_keys(d))
|
341
|
+
end.compact
|
342
|
+
rescue
|
343
|
+
[]
|
344
|
+
end
|
241
345
|
end
|
data/lib/ree_spec/version.rb
CHANGED