specwrk 0.5.0 → 0.6.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/specwrk/cli_reporter.rb +16 -10
- data/lib/specwrk/client.rb +2 -2
- data/lib/specwrk/queue.rb +27 -11
- data/lib/specwrk/version.rb +1 -1
- data/lib/specwrk/web/app.rb +2 -4
- data/lib/specwrk/web/endpoints.rb +33 -13
- data/lib/specwrk/web.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: bf78cf2d1c82bc0878e1e89777eb8de0ab04af441e210c64a15c2bad1277c1fa
|
4
|
+
data.tar.gz: 3701d6f676e4c31c3fb787f4ca59a8aaa7aa412118371470b069471da4e6c933
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: debda5ab7128ae03e74652196da8783b4d78ddf3648ccfd2c3e62104fe8a3fb87b98abbc68deb7d66565d66474a504a8d778ca0de44eef311e14188a4258f856
|
7
|
+
data.tar.gz: 1a4089b567a0840f91a133fef5580b6c5bd3c43190eb7cd1156fe3439e042f727b62bdf69ee1624815ac741f738907e43c92559be1f4c4d55268b2db1625b074
|
data/lib/specwrk/cli_reporter.rb
CHANGED
@@ -11,7 +11,10 @@ require "rspec/core/formatters/console_codes"
|
|
11
11
|
module Specwrk
|
12
12
|
class CLIReporter
|
13
13
|
def report
|
14
|
-
|
14
|
+
unless Client.connect?
|
15
|
+
puts colorizer.wrap("\nCannot connect to server to generate report. Assuming failure.", :red)
|
16
|
+
return 1
|
17
|
+
end
|
15
18
|
|
16
19
|
puts "\nFinished in #{total_duration} " \
|
17
20
|
"(total execution time of #{total_run_time})\n"
|
@@ -28,8 +31,11 @@ module Specwrk
|
|
28
31
|
puts colorizer.wrap(totals_line, :green)
|
29
32
|
0
|
30
33
|
end
|
31
|
-
rescue Specwrk::UnhandledResponseError
|
32
|
-
puts colorizer.wrap("
|
34
|
+
rescue Specwrk::UnhandledResponseError => e
|
35
|
+
puts colorizer.wrap("\nCannot report, #{e.message}.", :red)
|
36
|
+
|
37
|
+
client.shutdown
|
38
|
+
|
33
39
|
1
|
34
40
|
end
|
35
41
|
|
@@ -43,28 +49,28 @@ module Specwrk
|
|
43
49
|
summary
|
44
50
|
end
|
45
51
|
|
46
|
-
def
|
47
|
-
@
|
52
|
+
def report_data
|
53
|
+
@report_data ||= client.report
|
48
54
|
end
|
49
55
|
|
50
56
|
def total_duration
|
51
|
-
Time.parse(
|
57
|
+
Time.parse(report_data.dig(:meta, :last_finished_at)) - Time.parse(report_data.dig(:meta, :first_started_at))
|
52
58
|
end
|
53
59
|
|
54
60
|
def total_run_time
|
55
|
-
|
61
|
+
report_data.dig(:meta, :total_run_time)
|
56
62
|
end
|
57
63
|
|
58
64
|
def failure_count
|
59
|
-
|
65
|
+
report_data.dig(:meta, :failures)
|
60
66
|
end
|
61
67
|
|
62
68
|
def pending_count
|
63
|
-
|
69
|
+
report_data.dig(:meta, :pending)
|
64
70
|
end
|
65
71
|
|
66
72
|
def example_count
|
67
|
-
|
73
|
+
report_data.dig(:examples).length
|
68
74
|
end
|
69
75
|
|
70
76
|
def client
|
data/lib/specwrk/client.rb
CHANGED
data/lib/specwrk/queue.rb
CHANGED
@@ -6,7 +6,11 @@ require "json"
|
|
6
6
|
module Specwrk
|
7
7
|
# Thread-safe Hash access
|
8
8
|
class Queue
|
9
|
+
attr_reader :created_at
|
10
|
+
|
9
11
|
def initialize(hash = {})
|
12
|
+
@created_at = Time.now
|
13
|
+
|
10
14
|
if block_given?
|
11
15
|
@mutex = Monitor.new # Reentrant locking is required here
|
12
16
|
# It's possible to enter the proc from two threads, so we need to ||= in case
|
@@ -40,8 +44,6 @@ module Specwrk
|
|
40
44
|
end
|
41
45
|
|
42
46
|
class PendingQueue < Queue
|
43
|
-
attr_reader :previous_run_times
|
44
|
-
|
45
47
|
def shift_bucket
|
46
48
|
return bucket_by_file unless previous_run_times
|
47
49
|
|
@@ -59,17 +61,22 @@ module Specwrk
|
|
59
61
|
previous_run_times.dig(:meta, :average_run_time)
|
60
62
|
end
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
-
return unless path
|
65
|
-
return unless File.exist? path
|
64
|
+
def previous_run_times
|
65
|
+
return unless ENV["SPECWRK_OUT"]
|
66
66
|
|
67
|
-
|
68
|
-
|
67
|
+
@previous_run_times ||= begin
|
68
|
+
return unless previous_run_times_file_path
|
69
|
+
return unless File.exist? previous_run_times_file_path
|
69
70
|
|
70
|
-
|
71
|
+
raw_data = File.open(previous_run_times_file_path, "r") do |file|
|
72
|
+
file.flock(File::LOCK_SH)
|
73
|
+
file.read
|
74
|
+
end
|
71
75
|
|
72
|
-
|
76
|
+
@previous_run_times = JSON.parse(raw_data, symbolize_names: true)
|
77
|
+
rescue JSON::ParserError => e
|
78
|
+
warn "#{e.inspect} in file #{previous_run_times_file_path}"
|
79
|
+
nil
|
73
80
|
end
|
74
81
|
end
|
75
82
|
|
@@ -84,6 +91,15 @@ module Specwrk
|
|
84
91
|
|
85
92
|
private
|
86
93
|
|
94
|
+
# We want the most recently modified run time file
|
95
|
+
# report files are prefixed with a timestamp, and Dir.glob should order
|
96
|
+
# alphanumericly
|
97
|
+
def previous_run_times_file_path
|
98
|
+
return unless ENV["SPECWRK_OUT"]
|
99
|
+
|
100
|
+
@previous_run_times_file_path ||= Dir.glob(File.join(ENV["SPECWRK_OUT"], "*-report-*.json")).last
|
101
|
+
end
|
102
|
+
|
87
103
|
# Take elements from the hash where the file_path is the same
|
88
104
|
def bucket_by_file
|
89
105
|
bucket = []
|
@@ -163,7 +179,7 @@ module Specwrk
|
|
163
179
|
@hash.values.each { |example| calculate(example) }
|
164
180
|
|
165
181
|
@output[:meta][:total_run_time] = @run_times.sum
|
166
|
-
@output[:meta][:average_run_time] = @output[:meta][:total_run_time] / @run_times.length.to_f
|
182
|
+
@output[:meta][:average_run_time] = @output[:meta][:total_run_time] / [@run_times.length, 1].max.to_f
|
167
183
|
@output[:meta][:first_started_at] = @first_started_at.iso8601(6)
|
168
184
|
@output[:meta][:last_finished_at] = @last_finished_at.iso8601(6)
|
169
185
|
|
data/lib/specwrk/version.rb
CHANGED
data/lib/specwrk/web/app.rb
CHANGED
@@ -52,10 +52,8 @@ module Specwrk
|
|
52
52
|
|
53
53
|
def setup!
|
54
54
|
if ENV["SPECWRK_OUT"]
|
55
|
-
|
56
55
|
FileUtils.mkdir_p(ENV["SPECWRK_OUT"])
|
57
56
|
ENV["SPECWRK_SRV_LOG"] ||= Pathname.new(File.join(ENV["SPECWRK_OUT"], "server.log")).to_s unless ENV["SPECWRK_SRV_VERBOSE"]
|
58
|
-
ENV["SPECWRK_SRV_OUTPUT"] ||= Pathname.new(File.join(ENV["SPECWRK_OUT"], "report.json")).expand_path(Dir.pwd).to_s
|
59
57
|
end
|
60
58
|
|
61
59
|
if ENV["SPECWRK_SRV_LOG"]
|
@@ -100,8 +98,8 @@ module Specwrk
|
|
100
98
|
Endpoints::Complete
|
101
99
|
when ["POST", "/seed"]
|
102
100
|
Endpoints::Seed
|
103
|
-
when ["GET", "/
|
104
|
-
Endpoints::
|
101
|
+
when ["GET", "/report"]
|
102
|
+
Endpoints::Report
|
105
103
|
when ["DELETE", "/shutdown"]
|
106
104
|
Endpoints::Shutdown
|
107
105
|
else
|
@@ -38,7 +38,7 @@ module Specwrk
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def pending_queue
|
41
|
-
Web::PENDING_QUEUES[
|
41
|
+
Web::PENDING_QUEUES[run_id]
|
42
42
|
end
|
43
43
|
|
44
44
|
def processing_queue
|
@@ -56,6 +56,14 @@ module Specwrk
|
|
56
56
|
def worker
|
57
57
|
workers[request.get_header("HTTP_X_SPECWRK_ID")]
|
58
58
|
end
|
59
|
+
|
60
|
+
def run_id
|
61
|
+
request.get_header("HTTP_X_SPECWRK_RUN")
|
62
|
+
end
|
63
|
+
|
64
|
+
def run_report_file_path
|
65
|
+
@run_report_file_path ||= File.join(ENV["SPECWRK_OUT"], "#{completed_queue.created_at.strftime("%Y%m%dT%H%M%S")}-report-#{run_id}.json").to_s
|
66
|
+
end
|
59
67
|
end
|
60
68
|
|
61
69
|
# Base default response is 404
|
@@ -98,8 +106,8 @@ module Specwrk
|
|
98
106
|
end
|
99
107
|
end
|
100
108
|
|
101
|
-
if pending_queue.length.zero? && processing_queue.length.zero? && completed_queue.length.positive? && ENV["
|
102
|
-
completed_queue.dump_and_write(
|
109
|
+
if pending_queue.length.zero? && processing_queue.length.zero? && completed_queue.length.positive? && ENV["SPECWRK_OUT"]
|
110
|
+
completed_queue.dump_and_write(run_report_file_path)
|
103
111
|
end
|
104
112
|
|
105
113
|
ok
|
@@ -128,20 +136,32 @@ module Specwrk
|
|
128
136
|
end
|
129
137
|
end
|
130
138
|
|
131
|
-
class
|
139
|
+
class Report < Base
|
132
140
|
def response
|
133
|
-
data
|
134
|
-
|
135
|
-
processing: {count: processing_queue.length},
|
136
|
-
completed: completed_queue.dump
|
137
|
-
}
|
138
|
-
|
139
|
-
if data.dig(:completed, :examples).length.positive?
|
140
|
-
[200, {"Content-Type" => "application/json"}, [JSON.generate(data)]]
|
141
|
+
if data
|
142
|
+
[200, {"Content-Type" => "application/json"}, [data]]
|
141
143
|
else
|
142
|
-
|
144
|
+
[404, {"Content-Type" => "text/plain"}, ["Unable to report on run #{run_id}; no file matching #{"*-report-#{run_id}.json"}"]]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
def data
|
151
|
+
return @data if defined? @data
|
152
|
+
|
153
|
+
return unless most_recent_run_report_file
|
154
|
+
return unless File.exist?(most_recent_run_report_file)
|
155
|
+
|
156
|
+
@data = File.open(most_recent_run_report_file, "r") do |file|
|
157
|
+
file.flock(File::LOCK_SH)
|
158
|
+
file.read
|
143
159
|
end
|
144
160
|
end
|
161
|
+
|
162
|
+
def most_recent_run_report_file
|
163
|
+
@most_recent_run_report_file ||= Dir.glob(File.join(ENV["SPECWRK_OUT"], "*-report-#{run_id}.json")).last
|
164
|
+
end
|
145
165
|
end
|
146
166
|
|
147
167
|
class Shutdown < Base
|
data/lib/specwrk/web.rb
CHANGED
@@ -4,7 +4,7 @@ require "specwrk/queue"
|
|
4
4
|
|
5
5
|
module Specwrk
|
6
6
|
class Web
|
7
|
-
PENDING_QUEUES = Queue.new { |h, key| h[key] = PendingQueue.new
|
7
|
+
PENDING_QUEUES = Queue.new { |h, key| h[key] = PendingQueue.new }
|
8
8
|
PROCESSING_QUEUES = Queue.new { |h, key| h[key] = Queue.new }
|
9
9
|
COMPLETED_QUEUES = Queue.new { |h, key| h[key] = CompletedQueue.new }
|
10
10
|
WORKERS = Hash.new { |h, key| h[key] = Hash.new { |h, key| h[key] = {} } }
|