specwrk 0.10.0 → 0.10.2
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/docker/Dockerfile.server +7 -11
- data/docker/entrypoint.server.sh +2 -2
- data/docker/pitchfork.conf +5 -0
- data/lib/specwrk/store/file_adapter.rb +17 -13
- data/lib/specwrk/store.rb +17 -49
- data/lib/specwrk/version.rb +1 -1
- data/lib/specwrk/web/auth.rb +1 -1
- data/lib/specwrk/web/endpoints.rb +12 -12
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4570e3aaeb01c00647b8671803076848bf28dee5068ec0cde66c88effea85bbe
|
4
|
+
data.tar.gz: 1d6709fc4b518ca5dcbad15e59820ba855adebb5dc6830ec26cc7f92d59f597d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3868e891fc3c14a8ce281b747d8e5b0c271e55f946f1fe1d23aa4d88d940ee40ea966fbf32bce5711ca1597c7870a8a4b1aa1bac610f117a9695888015eee6db
|
7
|
+
data.tar.gz: 385faa8d85c751eca15e1203ab626ec8d9abe3584e79265550dc52b18c81327f6a837535827dd63d56bc5fb0671fe11c8bd91698a96dc0d9a82d36a23edc7430
|
data/docker/Dockerfile.server
CHANGED
@@ -1,11 +1,6 @@
|
|
1
1
|
FROM ruby:3.4-alpine
|
2
2
|
|
3
|
-
RUN apk add --no-cache
|
4
|
-
build-base \
|
5
|
-
ruby-dev \
|
6
|
-
linux-headers \
|
7
|
-
zlib-dev \
|
8
|
-
libffi-dev
|
3
|
+
RUN apk add --no-cache build-base
|
9
4
|
|
10
5
|
WORKDIR /app
|
11
6
|
|
@@ -13,14 +8,15 @@ RUN mkdir .specwrk/
|
|
13
8
|
|
14
9
|
ARG SPECWRK_SRV_PORT=5138
|
15
10
|
ARG SPECWRK_VERSION=latest
|
16
|
-
ARG
|
11
|
+
ARG GEM_FILE=specwrk-$SPECWRK_VERSION.gem
|
17
12
|
|
18
|
-
COPY $
|
19
|
-
RUN gem install ./$
|
20
|
-
RUN rm ./$
|
13
|
+
COPY $GEM_FILE ./
|
14
|
+
RUN gem install ./$GEM_FILE --no-document
|
15
|
+
RUN rm ./$GEM_FILE
|
21
16
|
|
22
|
-
RUN gem install
|
17
|
+
RUN gem install pitchfork thruster
|
23
18
|
COPY config.ru ./
|
19
|
+
COPY docker/pitchfork.conf ./
|
24
20
|
|
25
21
|
COPY docker/entrypoint.server.sh /usr/local/bin/entrypoint
|
26
22
|
RUN chmod +x /usr/local/bin/entrypoint
|
data/docker/entrypoint.server.sh
CHANGED
@@ -2,6 +2,6 @@
|
|
2
2
|
|
3
3
|
export THRUSTER_HTTP_PORT=${PORT:-5138}
|
4
4
|
export THRUSTER_TARGET_PORT=3000
|
5
|
-
export THRUSTER_HTTP_IDLE_TIMEOUT=${IDLE_TIMEOUT:-
|
5
|
+
export THRUSTER_HTTP_IDLE_TIMEOUT=${IDLE_TIMEOUT:-300}
|
6
6
|
|
7
|
-
exec thrust
|
7
|
+
exec thrust pitchfork -c pitchfork.conf
|
@@ -10,20 +10,24 @@ module Specwrk
|
|
10
10
|
class FileAdapter
|
11
11
|
EXT = ".wrk.json"
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
@work_queue = Queue.new
|
14
|
+
@threads = []
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
16
|
+
class << self
|
17
|
+
def schedule_work(&blk)
|
18
|
+
start_threads!
|
19
|
+
@work_queue.push blk
|
22
20
|
end
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
def start_threads!
|
23
|
+
return if @threads.length.positive?
|
24
|
+
|
25
|
+
Array.new(ENV.fetch("SPECWRK_THREAD_COUNT", "4").to_i) do
|
26
|
+
@threads << Thread.new do
|
27
|
+
loop do
|
28
|
+
@work_queue.pop.call
|
29
|
+
end
|
30
|
+
end
|
27
31
|
end
|
28
32
|
end
|
29
33
|
end
|
@@ -80,7 +84,7 @@ module Specwrk
|
|
80
84
|
result_queue = Queue.new
|
81
85
|
|
82
86
|
read_keys.each do |key|
|
83
|
-
|
87
|
+
self.class.schedule_work do
|
84
88
|
result_queue.push([key.to_s, read(key)])
|
85
89
|
end
|
86
90
|
end
|
@@ -107,7 +111,7 @@ module Specwrk
|
|
107
111
|
hash_with_filenames.each do |key, (filename, value)|
|
108
112
|
content = JSON.generate(value)
|
109
113
|
|
110
|
-
|
114
|
+
self.class.schedule_work do
|
111
115
|
result_queue << write(filename, content)
|
112
116
|
end
|
113
117
|
end
|
data/lib/specwrk/store.rb
CHANGED
@@ -7,40 +7,24 @@ require "specwrk/store/file_adapter"
|
|
7
7
|
|
8
8
|
module Specwrk
|
9
9
|
class Store
|
10
|
-
|
11
|
-
MUTEXES_MUTEX = Mutex.new # 🐢🐢🐢🐢
|
12
|
-
|
13
|
-
class << self
|
14
|
-
def mutex_for(path)
|
15
|
-
MUTEXES_MUTEX.synchronize do
|
16
|
-
MUTEXES[path] ||= Mutex.new
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def initialize(path, thread_safe_reads: true)
|
10
|
+
def initialize(path)
|
22
11
|
@path = path
|
23
|
-
@thread_safe_reads = thread_safe_reads
|
24
12
|
end
|
25
13
|
|
26
14
|
def [](key)
|
27
|
-
|
15
|
+
adapter[key.to_s]
|
28
16
|
end
|
29
17
|
|
30
18
|
def multi_read(*keys)
|
31
|
-
|
19
|
+
adapter.multi_read(*keys)
|
32
20
|
end
|
33
21
|
|
34
22
|
def []=(key, value)
|
35
|
-
|
36
|
-
adapter[key.to_s] = value
|
37
|
-
end
|
23
|
+
adapter[key.to_s] = value
|
38
24
|
end
|
39
25
|
|
40
26
|
def keys
|
41
|
-
all_keys =
|
42
|
-
adapter.keys
|
43
|
-
end
|
27
|
+
all_keys = adapter.keys
|
44
28
|
|
45
29
|
all_keys.reject { |k| k.start_with? "____" }
|
46
30
|
end
|
@@ -54,28 +38,24 @@ module Specwrk
|
|
54
38
|
end
|
55
39
|
|
56
40
|
def empty?
|
57
|
-
|
58
|
-
adapter.empty?
|
59
|
-
end
|
41
|
+
adapter.empty?
|
60
42
|
end
|
61
43
|
|
62
44
|
def delete(*keys)
|
63
|
-
|
45
|
+
adapter.delete(*keys)
|
64
46
|
end
|
65
47
|
|
66
48
|
def merge!(h2)
|
67
49
|
h2.transform_keys!(&:to_s)
|
68
|
-
|
50
|
+
adapter.merge!(h2)
|
69
51
|
end
|
70
52
|
|
71
53
|
def clear
|
72
|
-
|
54
|
+
adapter.clear
|
73
55
|
end
|
74
56
|
|
75
57
|
def to_h
|
76
|
-
|
77
|
-
adapter.multi_read(*keys).transform_keys!(&:to_sym)
|
78
|
-
end
|
58
|
+
adapter.multi_read(*keys).transform_keys!(&:to_sym)
|
79
59
|
end
|
80
60
|
|
81
61
|
def inspect
|
@@ -92,16 +72,6 @@ module Specwrk
|
|
92
72
|
|
93
73
|
private
|
94
74
|
|
95
|
-
attr_reader :thread_safe_reads
|
96
|
-
|
97
|
-
def sync(thread_safe: true)
|
98
|
-
if !thread_safe || mutex.owned?
|
99
|
-
yield
|
100
|
-
else
|
101
|
-
mutex.synchronize { yield }
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
75
|
def adapter
|
106
76
|
@adapter ||= FileAdapter.new(@path)
|
107
77
|
end
|
@@ -123,15 +93,13 @@ module Specwrk
|
|
123
93
|
end
|
124
94
|
|
125
95
|
def shift_bucket
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
bucket_by_timings
|
134
|
-
end
|
96
|
+
return bucket_by_file unless run_time_bucket_maximum&.positive?
|
97
|
+
|
98
|
+
case ENV["SPECWRK_SRV_GROUP_BY"]
|
99
|
+
when "file"
|
100
|
+
bucket_by_file
|
101
|
+
else
|
102
|
+
bucket_by_timings
|
135
103
|
end
|
136
104
|
end
|
137
105
|
|
data/lib/specwrk/version.rb
CHANGED
data/lib/specwrk/web/auth.rb
CHANGED
@@ -51,11 +51,11 @@ module Specwrk
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def not_found
|
54
|
-
[404, {"
|
54
|
+
[404, {"content-type" => "text/plain"}, ["This is not the path you're looking for, 'ol chap..."]]
|
55
55
|
end
|
56
56
|
|
57
57
|
def ok
|
58
|
-
[200, {"
|
58
|
+
[200, {"content-type" => "text/plain"}, ["OK, 'ol chap"]]
|
59
59
|
end
|
60
60
|
|
61
61
|
def payload
|
@@ -83,11 +83,11 @@ module Specwrk
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def metadata
|
86
|
-
@metadata ||= Store.new(File.join(datastore_path, "metadata")
|
86
|
+
@metadata ||= Store.new(File.join(datastore_path, "metadata"))
|
87
87
|
end
|
88
88
|
|
89
89
|
def run_times
|
90
|
-
@run_times ||= Store.new(File.join(ENV["SPECWRK_OUT"], "run_times")
|
90
|
+
@run_times ||= Store.new(File.join(ENV["SPECWRK_OUT"], "run_times"))
|
91
91
|
end
|
92
92
|
|
93
93
|
def worker
|
@@ -230,11 +230,11 @@ module Specwrk
|
|
230
230
|
processing.merge!(processing_data)
|
231
231
|
|
232
232
|
if @examples.any?
|
233
|
-
[200, {"
|
233
|
+
[200, {"content-type" => "application/json"}, [JSON.generate(@examples)]]
|
234
234
|
elsif pending.empty? && processing.empty? && completed.empty?
|
235
|
-
[204, {"
|
235
|
+
[204, {"content-type" => "text/plain"}, ["Waiting for sample to be seeded."]]
|
236
236
|
elsif completed.any? && processing.empty?
|
237
|
-
[410, {"
|
237
|
+
[410, {"content-type" => "text/plain"}, ["That's a good lad. Run along now and go home."]]
|
238
238
|
else
|
239
239
|
not_found
|
240
240
|
end
|
@@ -253,11 +253,11 @@ module Specwrk
|
|
253
253
|
processing.merge!(processing_data)
|
254
254
|
|
255
255
|
if @examples.any?
|
256
|
-
[200, {"
|
256
|
+
[200, {"content-type" => "application/json"}, [JSON.generate(@examples)]]
|
257
257
|
elsif pending.empty? && processing.empty? && completed.empty?
|
258
|
-
[204, {"
|
258
|
+
[204, {"content-type" => "text/plain"}, ["Waiting for sample to be seeded."]]
|
259
259
|
elsif completed.any? && processing.empty?
|
260
|
-
[410, {"
|
260
|
+
[410, {"content-type" => "text/plain"}, ["That's a good lad. Run along now and go home."]]
|
261
261
|
else
|
262
262
|
not_found
|
263
263
|
end
|
@@ -288,7 +288,7 @@ module Specwrk
|
|
288
288
|
|
289
289
|
class Report < Base
|
290
290
|
def with_response
|
291
|
-
[200, {"
|
291
|
+
[200, {"content-type" => "application/json"}, [JSON.generate(completed.dump)]]
|
292
292
|
end
|
293
293
|
end
|
294
294
|
|
@@ -299,7 +299,7 @@ module Specwrk
|
|
299
299
|
|
300
300
|
interupt! if ENV["SPECWRK_SRV_SINGLE_RUN"]
|
301
301
|
|
302
|
-
[200, {"
|
302
|
+
[200, {"content-type" => "text/plain"}, ["✌️"]]
|
303
303
|
end
|
304
304
|
|
305
305
|
def interupt!
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: specwrk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Westendorf
|
@@ -180,6 +180,7 @@ files:
|
|
180
180
|
- config.ru
|
181
181
|
- docker/Dockerfile.server
|
182
182
|
- docker/entrypoint.server.sh
|
183
|
+
- docker/pitchfork.conf
|
183
184
|
- examples/circleci/config.yml
|
184
185
|
- examples/github/specwrk-multi-node.yml
|
185
186
|
- examples/github/specwrk-single-node.yml
|