specbandit 0.11.0 → 0.12.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/lib/specbandit/rspec_adapter.rb +2 -2
- data/lib/specbandit/version.rb +1 -1
- data/lib/specbandit/worker.rb +16 -104
- 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: 82b0e7cfc34d8564657fc313dc9f0e4432a8c7c88795690670da3f86a21acd64
|
|
4
|
+
data.tar.gz: 321f4437b8a265664b72f30cd38f03cdd5b03f5f7814d00f608096a6fa47b19c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f3e05b5368da44a918d66432edd5985cfb461f9505f1a47ba56b4d7e599cdae48395a9e5b8da5bbd015c9d1540a567ea97d719ef40004fe36238c5afe013adc9
|
|
7
|
+
data.tar.gz: a5cc4f6d8844a31f9f98eb6caf5928424cccf2d4fa662d06f7a853a095ff6c8a1ef155169eaea659fb7c2e57a38d1e2c76f67dd9723260fca0bc6b410ea27eb3
|
|
@@ -65,10 +65,10 @@ module Specbandit
|
|
|
65
65
|
ensure
|
|
66
66
|
# Print RSpec output through our output stream
|
|
67
67
|
rspec_output = out&.string
|
|
68
|
-
output.print(rspec_output) if
|
|
68
|
+
output.print(rspec_output) if rspec_output && !rspec_output.empty?
|
|
69
69
|
|
|
70
70
|
rspec_err = err&.string
|
|
71
|
-
output.print(rspec_err) if
|
|
71
|
+
output.print(rspec_err) if rspec_err && !rspec_err.empty?
|
|
72
72
|
|
|
73
73
|
# Don't unlink the tempfile here — the Worker needs to read it.
|
|
74
74
|
# The Worker is responsible for cleanup after accumulation.
|
data/lib/specbandit/version.rb
CHANGED
data/lib/specbandit/worker.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'stringio'
|
|
4
3
|
require 'json'
|
|
5
4
|
|
|
6
5
|
module Specbandit
|
|
@@ -67,8 +66,6 @@ module Specbandit
|
|
|
67
66
|
|
|
68
67
|
print_summary if @batch_results.any?
|
|
69
68
|
merge_json_results
|
|
70
|
-
write_github_step_summary if ENV['GITHUB_STEP_SUMMARY']
|
|
71
|
-
|
|
72
69
|
exit_code
|
|
73
70
|
ensure
|
|
74
71
|
adapter.teardown
|
|
@@ -80,29 +77,31 @@ module Specbandit
|
|
|
80
77
|
# Used when re-running a failed CI job -- the rerun key already
|
|
81
78
|
# contains the exact files this runner executed previously.
|
|
82
79
|
def run_replay(files)
|
|
83
|
-
output.puts "[specbandit] Replay mode: found #{files.size} files in rerun key '#{key_rerun}'."
|
|
84
|
-
output.puts '[specbandit] Running previously recorded files (not touching shared queue).'
|
|
80
|
+
output.puts "[specbandit] Replay mode: found #{files.size} files in rerun key '#{key_rerun}'." if verbose
|
|
81
|
+
output.puts '[specbandit] Running previously recorded files (not touching shared queue).' if verbose
|
|
85
82
|
|
|
86
83
|
failed = false
|
|
87
84
|
batch_num = 0
|
|
88
85
|
|
|
89
86
|
files.each_slice(batch_size) do |batch|
|
|
90
87
|
batch_num += 1
|
|
91
|
-
output.puts "[specbandit] Batch ##{batch_num}: running #{batch.size} files"
|
|
88
|
+
output.puts "[specbandit] Batch ##{batch_num}: running #{batch.size} files" if verbose
|
|
92
89
|
batch.each { |f| output.puts " #{f}" } if verbose
|
|
93
90
|
|
|
94
91
|
result = adapter.run_batch(batch, batch_num)
|
|
95
92
|
process_batch_result(result)
|
|
96
93
|
|
|
97
94
|
if result.exit_code != 0
|
|
98
|
-
output.puts "[specbandit] Batch ##{batch_num} FAILED (exit code: #{result.exit_code})"
|
|
95
|
+
output.puts "[specbandit] Batch ##{batch_num} FAILED (exit code: #{result.exit_code})" if verbose
|
|
99
96
|
failed = true
|
|
100
|
-
|
|
97
|
+
elsif verbose
|
|
101
98
|
output.puts "[specbandit] Batch ##{batch_num} passed."
|
|
102
99
|
end
|
|
103
100
|
end
|
|
104
101
|
|
|
105
|
-
|
|
102
|
+
if verbose
|
|
103
|
+
output.puts "[specbandit] Replay finished: #{batch_num} batches. #{failed ? 'SOME FAILED' : 'All passed.'}"
|
|
104
|
+
end
|
|
106
105
|
failed ? 1 : 0
|
|
107
106
|
end
|
|
108
107
|
|
|
@@ -111,8 +110,8 @@ module Specbandit
|
|
|
111
110
|
# rerun key so this runner can replay them on a re-run.
|
|
112
111
|
def run_steal(record:)
|
|
113
112
|
mode_label = record ? 'Record' : 'Steal'
|
|
114
|
-
output.puts "[specbandit] #{mode_label} mode: stealing batches from '#{key}'."
|
|
115
|
-
output.puts "[specbandit] Recording stolen files to rerun key '#{key_rerun}'." if record
|
|
113
|
+
output.puts "[specbandit] #{mode_label} mode: stealing batches from '#{key}'." if verbose
|
|
114
|
+
output.puts "[specbandit] Recording stolen files to rerun key '#{key_rerun}'." if verbose && record
|
|
116
115
|
|
|
117
116
|
failed = false
|
|
118
117
|
batch_num = 0
|
|
@@ -121,7 +120,7 @@ module Specbandit
|
|
|
121
120
|
files = queue.steal(key, batch_size)
|
|
122
121
|
|
|
123
122
|
if files.empty?
|
|
124
|
-
output.puts '[specbandit] Queue exhausted. No more files to run.'
|
|
123
|
+
output.puts '[specbandit] Queue exhausted. No more files to run.' if verbose
|
|
125
124
|
break
|
|
126
125
|
end
|
|
127
126
|
|
|
@@ -129,23 +128,23 @@ module Specbandit
|
|
|
129
128
|
queue.push(key_rerun, files, ttl: key_rerun_ttl) if record
|
|
130
129
|
|
|
131
130
|
batch_num += 1
|
|
132
|
-
output.puts "[specbandit] Batch ##{batch_num}: running #{files.size} files"
|
|
131
|
+
output.puts "[specbandit] Batch ##{batch_num}: running #{files.size} files" if verbose
|
|
133
132
|
files.each { |f| output.puts " #{f}" } if verbose
|
|
134
133
|
|
|
135
134
|
result = adapter.run_batch(files, batch_num)
|
|
136
135
|
process_batch_result(result)
|
|
137
136
|
|
|
138
137
|
if result.exit_code != 0
|
|
139
|
-
output.puts "[specbandit] Batch ##{batch_num} FAILED (exit code: #{result.exit_code})"
|
|
138
|
+
output.puts "[specbandit] Batch ##{batch_num} FAILED (exit code: #{result.exit_code})" if verbose
|
|
140
139
|
failed = true
|
|
141
|
-
|
|
140
|
+
elsif verbose
|
|
142
141
|
output.puts "[specbandit] Batch ##{batch_num} passed."
|
|
143
142
|
end
|
|
144
143
|
end
|
|
145
144
|
|
|
146
145
|
if batch_num.zero?
|
|
147
|
-
output.puts '[specbandit] Nothing to do (queue was empty).'
|
|
148
|
-
|
|
146
|
+
output.puts '[specbandit] Nothing to do (queue was empty).' if verbose
|
|
147
|
+
elsif verbose
|
|
149
148
|
output.puts "[specbandit] Finished #{batch_num} batches. #{failed ? 'SOME FAILED' : 'All passed.'}"
|
|
150
149
|
end
|
|
151
150
|
|
|
@@ -310,92 +309,5 @@ module Specbandit
|
|
|
310
309
|
parts << "#{@accumulated_summary[:pending_count]} pending" if @accumulated_summary[:pending_count] > 0
|
|
311
310
|
parts.join(', ')
|
|
312
311
|
end
|
|
313
|
-
|
|
314
|
-
# Write a markdown summary to $GITHUB_STEP_SUMMARY for GitHub Actions.
|
|
315
|
-
def write_github_step_summary
|
|
316
|
-
path = ENV['GITHUB_STEP_SUMMARY']
|
|
317
|
-
return unless path
|
|
318
|
-
|
|
319
|
-
md = StringIO.new
|
|
320
|
-
|
|
321
|
-
if has_rspec_results?
|
|
322
|
-
write_rspec_github_summary(md)
|
|
323
|
-
else
|
|
324
|
-
write_generic_github_summary(md)
|
|
325
|
-
end
|
|
326
|
-
|
|
327
|
-
File.open(path, 'a') { |f| f.write(md.string) }
|
|
328
|
-
rescue StandardError
|
|
329
|
-
# Never fail the build because of summary writing
|
|
330
|
-
nil
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
def write_rspec_github_summary(md)
|
|
334
|
-
md.puts '### Specbandit Results'
|
|
335
|
-
md.puts ''
|
|
336
|
-
md.puts '| Metric | Value |'
|
|
337
|
-
md.puts '|--------|-------|'
|
|
338
|
-
md.puts "| Batches | #{batch_durations.size} |"
|
|
339
|
-
md.puts "| Examples | #{@accumulated_summary[:example_count]} |"
|
|
340
|
-
md.puts "| Failures | #{@accumulated_summary[:failure_count]} |"
|
|
341
|
-
md.puts "| Pending | #{@accumulated_summary[:pending_count]} |"
|
|
342
|
-
|
|
343
|
-
md.puts format('| Batch time (min) | %.1fs |', batch_durations.min || 0)
|
|
344
|
-
md.puts format('| Batch time (avg) | %.1fs |',
|
|
345
|
-
batch_durations.empty? ? 0 : batch_durations.sum / batch_durations.size)
|
|
346
|
-
md.puts format('| Batch time (max) | %.1fs |', batch_durations.max || 0)
|
|
347
|
-
md.puts ''
|
|
348
|
-
|
|
349
|
-
failed_examples = @accumulated_examples.select { |e| e['status'] == 'failed' }
|
|
350
|
-
return unless failed_examples.any?
|
|
351
|
-
|
|
352
|
-
md.puts "<details><summary>#{failed_examples.size} failed specs</summary>"
|
|
353
|
-
md.puts ''
|
|
354
|
-
md.puts '| Location | Description | Error |'
|
|
355
|
-
md.puts '|----------|-------------|-------|'
|
|
356
|
-
failed_examples.each do |ex|
|
|
357
|
-
location = ex['file_path'] || 'unknown'
|
|
358
|
-
line = ex['line_number']
|
|
359
|
-
location = "#{location}:#{line}" if line
|
|
360
|
-
desc = (ex['full_description'] || ex['description'] || '').gsub('|', '\\|')
|
|
361
|
-
message = (ex.dig('exception', 'message') || '').gsub('|', '\\|').gsub("\n", ' ')
|
|
362
|
-
message = "#{message[0, 100]}..." if message.length > 100
|
|
363
|
-
md.puts "| `#{location}` | #{desc} | #{message} |"
|
|
364
|
-
end
|
|
365
|
-
md.puts ''
|
|
366
|
-
md.puts '</details>'
|
|
367
|
-
end
|
|
368
|
-
|
|
369
|
-
def write_generic_github_summary(md)
|
|
370
|
-
total_files = @batch_results.sum { |r| r.files.size }
|
|
371
|
-
failed_batch_results = @batch_results.select { |r| r.exit_code != 0 }
|
|
372
|
-
|
|
373
|
-
md.puts '### Specbandit Results'
|
|
374
|
-
md.puts ''
|
|
375
|
-
md.puts '| Metric | Value |'
|
|
376
|
-
md.puts '|--------|-------|'
|
|
377
|
-
md.puts "| Batches | #{batch_durations.size} |"
|
|
378
|
-
md.puts "| Files | #{total_files} |"
|
|
379
|
-
md.puts "| Failed batches | #{failed_batch_results.size} |"
|
|
380
|
-
|
|
381
|
-
md.puts format('| Batch time (min) | %.1fs |', batch_durations.min || 0)
|
|
382
|
-
md.puts format('| Batch time (avg) | %.1fs |',
|
|
383
|
-
batch_durations.empty? ? 0 : batch_durations.sum / batch_durations.size)
|
|
384
|
-
md.puts format('| Batch time (max) | %.1fs |', batch_durations.max || 0)
|
|
385
|
-
md.puts ''
|
|
386
|
-
|
|
387
|
-
return unless failed_batch_results.any?
|
|
388
|
-
|
|
389
|
-
md.puts "<details><summary>#{failed_batch_results.size} failed batches</summary>"
|
|
390
|
-
md.puts ''
|
|
391
|
-
md.puts '| Batch | Exit Code | Files |'
|
|
392
|
-
md.puts '|-------|-----------|-------|'
|
|
393
|
-
failed_batch_results.each do |r|
|
|
394
|
-
files_str = r.files.map { |f| "`#{f}`" }.join(', ')
|
|
395
|
-
md.puts "| ##{r.batch_num} | #{r.exit_code} | #{files_str} |"
|
|
396
|
-
end
|
|
397
|
-
md.puts ''
|
|
398
|
-
md.puts '</details>'
|
|
399
|
-
end
|
|
400
312
|
end
|
|
401
313
|
end
|