judges 0.60.2 → 0.60.4
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/Gemfile +5 -4
- data/Gemfile.lock +64 -61
- data/README.md +57 -3
- data/Rakefile +1 -1
- data/features/step_definitions/steps.rb +6 -6
- data/features/test.feature +2 -2
- data/fixtures/repeat/repeat.rb +0 -2
- data/judges.gemspec +20 -20
- data/lib/judges/ascii_loog.rb +1 -2
- data/lib/judges/commands/download.rb +5 -6
- data/lib/judges/commands/eval.rb +5 -6
- data/lib/judges/commands/import.rb +6 -6
- data/lib/judges/commands/inspect.rb +2 -2
- data/lib/judges/commands/join.rb +3 -3
- data/lib/judges/commands/print.rb +19 -19
- data/lib/judges/commands/pull.rb +16 -14
- data/lib/judges/commands/push.rb +5 -5
- data/lib/judges/commands/test.rb +115 -83
- data/lib/judges/commands/trim.rb +5 -5
- data/lib/judges/commands/update.rb +102 -74
- data/lib/judges/commands/upload.rb +8 -8
- data/lib/judges/impex.rb +6 -6
- data/lib/judges/judge.rb +14 -12
- data/lib/judges/judges.rb +30 -25
- data/lib/judges/options.rb +32 -41
- data/lib/judges/pretty_exception.rb +1 -1
- data/lib/judges/statistics.rb +5 -8
- data/lib/judges.rb +1 -1
- data/package-lock.json +110 -301
- data/package.json +2 -2
- 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: 8713c9bc8dbf041fd7c451cfabc5cb8af4f9c9b0b0a267eec76b69b388f279a3
|
|
4
|
+
data.tar.gz: 8354129d0ed9db6da51bb68ad194c458f9d0f18a1956e41f417bf6677da68fa6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7a4ff1a0889fc324cfad12044de49a9d22c215737c5070863290c940d8e2e0de6da0e21a5fb615ffcff2d668f193e019e0282eb92730d709c251700488b2c432
|
|
7
|
+
data.tar.gz: cae9f5c7e70893f7d60228d1a625932e0d16594894505a8b96f8f1f25d2bb1cf61838d92a7c3827750eb1a284a5239b3a96155039f831760bb74efbf956c1c3d
|
data/Gemfile
CHANGED
|
@@ -7,8 +7,8 @@ source 'https://rubygems.org'
|
|
|
7
7
|
gemspec
|
|
8
8
|
|
|
9
9
|
gem 'base64', '~>0.3'
|
|
10
|
-
gem 'cucumber', '~>
|
|
11
|
-
gem 'diff-lcs', '1.6.2', require: false
|
|
10
|
+
gem 'cucumber', '~>11.0', require: false
|
|
11
|
+
gem 'diff-lcs', '1.6.2', require: false
|
|
12
12
|
gem 'minitest', '~>6.0', require: false
|
|
13
13
|
gem 'minitest-mock', '~>5.27', require: false
|
|
14
14
|
gem 'minitest-reporters', '~>1.7', require: false
|
|
@@ -18,8 +18,9 @@ gem 'os', '~>1.1', require: false
|
|
|
18
18
|
gem 'qbash', '~>0.4', require: false
|
|
19
19
|
gem 'rake', '~>13.2', require: false
|
|
20
20
|
gem 'random-port', '~>0.7', require: false
|
|
21
|
-
gem 'rdoc', '7.2.0', require: false
|
|
21
|
+
gem 'rdoc', '7.2.0', require: false
|
|
22
22
|
gem 'rubocop', '~>1.74', require: false
|
|
23
|
+
gem 'rubocop-elegant', '~>0.5', require: false
|
|
23
24
|
gem 'rubocop-minitest', '~>0.38', require: false
|
|
24
25
|
gem 'rubocop-performance', '~>1.25', require: false
|
|
25
26
|
gem 'rubocop-rake', '~>0.7', require: false
|
|
@@ -27,4 +28,4 @@ gem 'simplecov', '~>0.22', require: false
|
|
|
27
28
|
gem 'simplecov-cobertura', '~>3.0', require: false
|
|
28
29
|
gem 'w3c_validators', '~>1.3', require: false
|
|
29
30
|
gem 'webmock', '~>3.25', require: false
|
|
30
|
-
gem 'yard', '0.9.38', require: false
|
|
31
|
+
gem 'yard', '0.9.38', require: false
|
data/Gemfile.lock
CHANGED
|
@@ -24,13 +24,13 @@ PATH
|
|
|
24
24
|
GEM
|
|
25
25
|
remote: https://rubygems.org/
|
|
26
26
|
specs:
|
|
27
|
-
addressable (2.
|
|
27
|
+
addressable (2.9.0)
|
|
28
28
|
public_suffix (>= 2.0.2, < 8.0)
|
|
29
|
-
ansi (1.
|
|
29
|
+
ansi (1.6.0)
|
|
30
30
|
ast (2.4.3)
|
|
31
31
|
backtrace (0.4.1)
|
|
32
32
|
base64 (0.3.0)
|
|
33
|
-
baza.rb (0.14.
|
|
33
|
+
baza.rb (0.14.4)
|
|
34
34
|
backtrace (~> 0.4)
|
|
35
35
|
elapsed (~> 0.2)
|
|
36
36
|
faraday (~> 2.13)
|
|
@@ -42,36 +42,36 @@ GEM
|
|
|
42
42
|
retries (~> 0.0)
|
|
43
43
|
tago (~> 0.2)
|
|
44
44
|
typhoeus (~> 1.4)
|
|
45
|
-
bigdecimal (4.
|
|
45
|
+
bigdecimal (4.1.2)
|
|
46
46
|
builder (3.3.0)
|
|
47
47
|
concurrent-ruby (1.3.6)
|
|
48
48
|
crack (1.0.1)
|
|
49
49
|
bigdecimal
|
|
50
50
|
rexml
|
|
51
|
-
cucumber (
|
|
51
|
+
cucumber (11.1.0)
|
|
52
52
|
base64 (~> 0.2)
|
|
53
53
|
builder (~> 3.2)
|
|
54
54
|
cucumber-ci-environment (> 9, < 12)
|
|
55
|
-
cucumber-core (
|
|
55
|
+
cucumber-core (>= 16.2.0, < 17)
|
|
56
56
|
cucumber-cucumber-expressions (> 17, < 20)
|
|
57
|
-
cucumber-html-formatter (> 21, <
|
|
57
|
+
cucumber-html-formatter (> 21, < 24)
|
|
58
58
|
diff-lcs (~> 1.5)
|
|
59
59
|
logger (~> 1.6)
|
|
60
60
|
mini_mime (~> 1.1)
|
|
61
61
|
multi_test (~> 1.1)
|
|
62
|
-
sys-uname (~> 1.
|
|
62
|
+
sys-uname (~> 1.5)
|
|
63
63
|
cucumber-ci-environment (11.0.0)
|
|
64
64
|
cucumber-core (16.2.0)
|
|
65
65
|
cucumber-gherkin (> 36, < 40)
|
|
66
66
|
cucumber-messages (> 31, < 33)
|
|
67
67
|
cucumber-tag-expressions (> 6, < 9)
|
|
68
|
-
cucumber-cucumber-expressions (19.0.
|
|
68
|
+
cucumber-cucumber-expressions (19.0.1)
|
|
69
69
|
bigdecimal
|
|
70
|
-
cucumber-gherkin (39.
|
|
70
|
+
cucumber-gherkin (39.1.0)
|
|
71
71
|
cucumber-messages (>= 31, < 33)
|
|
72
|
-
cucumber-html-formatter (
|
|
72
|
+
cucumber-html-formatter (23.1.0)
|
|
73
73
|
cucumber-messages (> 23, < 33)
|
|
74
|
-
cucumber-messages (32.
|
|
74
|
+
cucumber-messages (32.3.1)
|
|
75
75
|
cucumber-tag-expressions (8.1.0)
|
|
76
76
|
date (3.5.1)
|
|
77
77
|
decoor (0.1.0)
|
|
@@ -82,11 +82,11 @@ GEM
|
|
|
82
82
|
loog (~> 0.6)
|
|
83
83
|
tago (~> 0.1)
|
|
84
84
|
ellipsized (0.3.0)
|
|
85
|
-
erb (6.0.
|
|
85
|
+
erb (6.0.4)
|
|
86
86
|
ethon (0.18.0)
|
|
87
87
|
ffi (>= 1.15.0)
|
|
88
88
|
logger
|
|
89
|
-
factbase (0.19.
|
|
89
|
+
factbase (0.19.10)
|
|
90
90
|
backtrace (~> 0.4)
|
|
91
91
|
decoor (~> 0.1)
|
|
92
92
|
ellipsized (~> 0.3)
|
|
@@ -97,53 +97,48 @@ GEM
|
|
|
97
97
|
others (~> 0.1)
|
|
98
98
|
tago (~> 0.1)
|
|
99
99
|
yaml (~> 0.3)
|
|
100
|
-
faraday (2.14.
|
|
100
|
+
faraday (2.14.2)
|
|
101
101
|
faraday-net_http (>= 2.0, < 3.5)
|
|
102
102
|
json
|
|
103
103
|
logger
|
|
104
|
-
faraday-http-cache (2.
|
|
104
|
+
faraday-http-cache (2.7.0)
|
|
105
105
|
faraday (>= 0.8)
|
|
106
106
|
faraday-multipart (1.2.0)
|
|
107
107
|
multipart-post (~> 2.0)
|
|
108
|
-
faraday-net_http (3.4.
|
|
108
|
+
faraday-net_http (3.4.3)
|
|
109
109
|
net-http (~> 0.5)
|
|
110
110
|
faraday-retry (2.4.0)
|
|
111
111
|
faraday (~> 2.0)
|
|
112
|
-
ffi (1.17.
|
|
113
|
-
ffi (1.17.
|
|
114
|
-
ffi (1.17.
|
|
115
|
-
ffi (1.17.
|
|
116
|
-
ffi (1.17.
|
|
117
|
-
ffi (1.17.
|
|
118
|
-
ffi (1.17.
|
|
119
|
-
ffi (1.17.
|
|
120
|
-
ffi (1.17.
|
|
112
|
+
ffi (1.17.4-aarch64-linux-gnu)
|
|
113
|
+
ffi (1.17.4-aarch64-linux-musl)
|
|
114
|
+
ffi (1.17.4-arm-linux-gnu)
|
|
115
|
+
ffi (1.17.4-arm-linux-musl)
|
|
116
|
+
ffi (1.17.4-arm64-darwin)
|
|
117
|
+
ffi (1.17.4-x64-mingw-ucrt)
|
|
118
|
+
ffi (1.17.4-x86_64-darwin)
|
|
119
|
+
ffi (1.17.4-x86_64-linux-gnu)
|
|
120
|
+
ffi (1.17.4-x86_64-linux-musl)
|
|
121
121
|
gli (2.22.2)
|
|
122
122
|
ostruct
|
|
123
123
|
hashdiff (1.2.1)
|
|
124
124
|
iri (0.11.8)
|
|
125
|
-
json (2.
|
|
126
|
-
json-schema (6.1.0)
|
|
127
|
-
addressable (~> 2.8)
|
|
128
|
-
bigdecimal (>= 3.1, < 5)
|
|
125
|
+
json (2.19.7)
|
|
129
126
|
language_server-protocol (3.17.0.5)
|
|
130
127
|
lint_roller (1.1.0)
|
|
131
128
|
logger (1.7.0)
|
|
132
129
|
loog (0.8.0)
|
|
133
130
|
ellipsized
|
|
134
131
|
logger (~> 1.0)
|
|
135
|
-
mcp (0.7.1)
|
|
136
|
-
json-schema (>= 4.1)
|
|
137
132
|
memoist3 (1.0.0)
|
|
138
133
|
mini_mime (1.1.5)
|
|
139
|
-
minitest (6.0.
|
|
134
|
+
minitest (6.0.6)
|
|
140
135
|
drb (~> 2.0)
|
|
141
136
|
prism (~> 1.5)
|
|
142
137
|
minitest-mock (5.27.0)
|
|
143
|
-
minitest-reporters (1.
|
|
138
|
+
minitest-reporters (1.8.0)
|
|
144
139
|
ansi
|
|
145
140
|
builder
|
|
146
|
-
minitest (>= 5.0)
|
|
141
|
+
minitest (>= 5.0, < 7)
|
|
147
142
|
ruby-progressbar
|
|
148
143
|
minitest-retry (0.3.1)
|
|
149
144
|
minitest (>= 5.0)
|
|
@@ -152,23 +147,23 @@ GEM
|
|
|
152
147
|
multipart-post (2.4.1)
|
|
153
148
|
net-http (0.9.1)
|
|
154
149
|
uri (>= 0.11.1)
|
|
155
|
-
nokogiri (1.19.
|
|
150
|
+
nokogiri (1.19.3-aarch64-linux-gnu)
|
|
156
151
|
racc (~> 1.4)
|
|
157
|
-
nokogiri (1.19.
|
|
152
|
+
nokogiri (1.19.3-aarch64-linux-musl)
|
|
158
153
|
racc (~> 1.4)
|
|
159
|
-
nokogiri (1.19.
|
|
154
|
+
nokogiri (1.19.3-arm-linux-gnu)
|
|
160
155
|
racc (~> 1.4)
|
|
161
|
-
nokogiri (1.19.
|
|
156
|
+
nokogiri (1.19.3-arm-linux-musl)
|
|
162
157
|
racc (~> 1.4)
|
|
163
|
-
nokogiri (1.19.
|
|
158
|
+
nokogiri (1.19.3-arm64-darwin)
|
|
164
159
|
racc (~> 1.4)
|
|
165
|
-
nokogiri (1.19.
|
|
160
|
+
nokogiri (1.19.3-x64-mingw-ucrt)
|
|
166
161
|
racc (~> 1.4)
|
|
167
|
-
nokogiri (1.19.
|
|
162
|
+
nokogiri (1.19.3-x86_64-darwin)
|
|
168
163
|
racc (~> 1.4)
|
|
169
|
-
nokogiri (1.19.
|
|
164
|
+
nokogiri (1.19.3-x86_64-linux-gnu)
|
|
170
165
|
racc (~> 1.4)
|
|
171
|
-
nokogiri (1.19.
|
|
166
|
+
nokogiri (1.19.3-x86_64-linux-musl)
|
|
172
167
|
racc (~> 1.4)
|
|
173
168
|
octokit (10.0.0)
|
|
174
169
|
faraday (>= 1, < 3)
|
|
@@ -176,51 +171,53 @@ GEM
|
|
|
176
171
|
online (0.3.0)
|
|
177
172
|
openssl (>= 3)
|
|
178
173
|
timeout (~> 0.4)
|
|
179
|
-
openssl (4.0.
|
|
174
|
+
openssl (4.0.2)
|
|
180
175
|
os (1.1.4)
|
|
181
176
|
ostruct (0.6.3)
|
|
182
177
|
others (0.1.1)
|
|
183
|
-
parallel (1.
|
|
184
|
-
parser (3.3.
|
|
178
|
+
parallel (2.1.0)
|
|
179
|
+
parser (3.3.11.1)
|
|
185
180
|
ast (~> 2.4.1)
|
|
186
181
|
racc
|
|
187
182
|
prism (1.9.0)
|
|
188
183
|
psych (5.3.1)
|
|
189
184
|
date
|
|
190
185
|
stringio
|
|
191
|
-
public_suffix (7.0.
|
|
192
|
-
qbash (0.8.
|
|
186
|
+
public_suffix (7.0.5)
|
|
187
|
+
qbash (0.8.4)
|
|
193
188
|
backtrace (> 0)
|
|
194
189
|
elapsed (> 0)
|
|
195
190
|
loog (> 0)
|
|
196
191
|
tago (> 0)
|
|
197
192
|
racc (1.8.1)
|
|
198
193
|
rainbow (3.1.1)
|
|
199
|
-
rake (13.
|
|
194
|
+
rake (13.4.2)
|
|
200
195
|
random-port (0.8.2)
|
|
201
196
|
tago (~> 0.0)
|
|
202
197
|
rdoc (7.2.0)
|
|
203
198
|
erb
|
|
204
199
|
psych (>= 4.0.0)
|
|
205
200
|
tsort
|
|
206
|
-
regexp_parser (2.
|
|
201
|
+
regexp_parser (2.12.0)
|
|
207
202
|
retries (0.0.5)
|
|
208
203
|
rexml (3.4.4)
|
|
209
|
-
rubocop (1.
|
|
204
|
+
rubocop (1.87.0)
|
|
210
205
|
json (~> 2.3)
|
|
211
206
|
language_server-protocol (~> 3.17.0.2)
|
|
212
207
|
lint_roller (~> 1.1.0)
|
|
213
|
-
|
|
214
|
-
parallel (~> 1.10)
|
|
208
|
+
parallel (>= 1.10)
|
|
215
209
|
parser (>= 3.3.0.2)
|
|
216
210
|
rainbow (>= 2.2.2, < 4.0)
|
|
217
211
|
regexp_parser (>= 2.9.3, < 3.0)
|
|
218
212
|
rubocop-ast (>= 1.49.0, < 2.0)
|
|
219
213
|
ruby-progressbar (~> 1.7)
|
|
220
214
|
unicode-display_width (>= 2.4.0, < 4.0)
|
|
221
|
-
rubocop-ast (1.49.
|
|
215
|
+
rubocop-ast (1.49.1)
|
|
222
216
|
parser (>= 3.3.7.2)
|
|
223
217
|
prism (~> 1.7)
|
|
218
|
+
rubocop-elegant (0.5.1)
|
|
219
|
+
lint_roller (~> 1.1)
|
|
220
|
+
rubocop (~> 1.75)
|
|
224
221
|
rubocop-minitest (0.39.1)
|
|
225
222
|
lint_roller (~> 1.1)
|
|
226
223
|
rubocop (>= 1.75.0, < 2.0)
|
|
@@ -246,15 +243,19 @@ GEM
|
|
|
246
243
|
simplecov-html (0.13.2)
|
|
247
244
|
simplecov_json_formatter (0.1.4)
|
|
248
245
|
stringio (3.2.0)
|
|
249
|
-
sys-uname (1.5.
|
|
246
|
+
sys-uname (1.5.1)
|
|
247
|
+
ffi (~> 1.1)
|
|
248
|
+
memoist3 (~> 1.0.0)
|
|
249
|
+
sys-uname (1.5.1-universal-mingw32)
|
|
250
250
|
ffi (~> 1.1)
|
|
251
251
|
memoist3 (~> 1.0.0)
|
|
252
|
+
win32ole
|
|
252
253
|
tago (0.7.0)
|
|
253
|
-
timeout (0.6.
|
|
254
|
+
timeout (0.6.1)
|
|
254
255
|
total (0.4.2)
|
|
255
256
|
tsort (0.2.0)
|
|
256
|
-
typhoeus (1.
|
|
257
|
-
ethon (>= 0.
|
|
257
|
+
typhoeus (1.6.0)
|
|
258
|
+
ethon (>= 0.18.0)
|
|
258
259
|
unicode-display_width (3.2.0)
|
|
259
260
|
unicode-emoji (~> 4.1)
|
|
260
261
|
unicode-emoji (4.2.0)
|
|
@@ -263,10 +264,11 @@ GEM
|
|
|
263
264
|
json (>= 1.8)
|
|
264
265
|
nokogiri (~> 1.6)
|
|
265
266
|
rexml (~> 3.2)
|
|
266
|
-
webmock (3.26.
|
|
267
|
+
webmock (3.26.2)
|
|
267
268
|
addressable (>= 2.8.0)
|
|
268
269
|
crack (>= 0.3.2)
|
|
269
270
|
hashdiff (>= 0.4.0, < 2.0.0)
|
|
271
|
+
win32ole (1.9.3)
|
|
270
272
|
yaml (0.4.0)
|
|
271
273
|
yard (0.9.38)
|
|
272
274
|
|
|
@@ -283,7 +285,7 @@ PLATFORMS
|
|
|
283
285
|
|
|
284
286
|
DEPENDENCIES
|
|
285
287
|
base64 (~> 0.3)
|
|
286
|
-
cucumber (~>
|
|
288
|
+
cucumber (~> 11.0)
|
|
287
289
|
diff-lcs (= 1.6.2)
|
|
288
290
|
judges!
|
|
289
291
|
minitest (~> 6.0)
|
|
@@ -297,6 +299,7 @@ DEPENDENCIES
|
|
|
297
299
|
random-port (~> 0.7)
|
|
298
300
|
rdoc (= 7.2.0)
|
|
299
301
|
rubocop (~> 1.74)
|
|
302
|
+
rubocop-elegant (~> 0.5)
|
|
300
303
|
rubocop-minitest (~> 0.38)
|
|
301
304
|
rubocop-performance (~> 1.25)
|
|
302
305
|
rubocop-rake (~> 0.7)
|
data/README.md
CHANGED
|
@@ -30,9 +30,9 @@ global variables available to it:
|
|
|
30
30
|
* `$local` — a hash map that is cleaned up when the execution of
|
|
31
31
|
a judge is finished;
|
|
32
32
|
* `$global` — a hash map that is never cleaned up;
|
|
33
|
-
* `$judge` — the basename of the directory, where the `.rb` script is located
|
|
34
|
-
* `$epoch` — the time moment when plugin was started
|
|
35
|
-
* `$kickoff` — the time moment when a judge was started
|
|
33
|
+
* `$judge` — the basename of the directory, where the `.rb` script is located;
|
|
34
|
+
* `$epoch` — the time moment when the plugin was started;
|
|
35
|
+
* `$kickoff` — the time moment when a judge was started.
|
|
36
36
|
|
|
37
37
|
Every `.yml` file must be formatted as such:
|
|
38
38
|
|
|
@@ -84,6 +84,60 @@ of Ruby scripts that are executed after the judge
|
|
|
84
84
|
The `expected_failure` (default: `[]`) is a list of strings that must
|
|
85
85
|
be present in the message of the exception being raised.
|
|
86
86
|
|
|
87
|
+
## Architecture
|
|
88
|
+
|
|
89
|
+
The core data structure is a
|
|
90
|
+
[Factbase](https://github.com/yegor256/factbase) — a flat, schemaless,
|
|
91
|
+
binary-serialized collection of facts (records with named attributes)
|
|
92
|
+
held in memory during a run. Facts are queried via
|
|
93
|
+
[XPath](https://www.w3.org/TR/xpath/) expressions rather than SQL.
|
|
94
|
+
There is no schema to migrate, no ORM layer, and no database process
|
|
95
|
+
to manage. The factbase binary file is read at the start of each
|
|
96
|
+
`update` run and written back on exit, making state portable and
|
|
97
|
+
inspectable via `judges print`. This differs from tools such as
|
|
98
|
+
[Sidekiq](https://sidekiq.org/) or
|
|
99
|
+
[ActiveJob](https://guides.rubyonrails.org/active_job_basics.html),
|
|
100
|
+
which depend on an external database or message broker.
|
|
101
|
+
|
|
102
|
+
Each judge is a single `.rb` Ruby file in its own directory. It is
|
|
103
|
+
not a class, a module, or a Rake task — it is a plain script loaded
|
|
104
|
+
with Ruby's `load(file, true)`, which wraps it in an anonymous module
|
|
105
|
+
and prevents constants in one judge from leaking into another. All
|
|
106
|
+
context is injected as Ruby global variables: `$fb` (the factbase),
|
|
107
|
+
`$loog` (logging), `$options` (configuration), `$global` (shared
|
|
108
|
+
across all judges in a run), and `$local` (reset after each judge).
|
|
109
|
+
A new judge author needs to know only those variables; there is no
|
|
110
|
+
base class to inherit and no interface contract to satisfy.
|
|
111
|
+
|
|
112
|
+
The `update` command runs all judges in repeated cycles until the
|
|
113
|
+
factbase stops changing (zero churn) or until the `--max-cycles` or
|
|
114
|
+
`--lifetime` limit is reached. This fixed-point convergence model is
|
|
115
|
+
analogous to [Datalog](https://en.wikipedia.org/wiki/Datalog): a
|
|
116
|
+
judge that inserts a fact in one cycle may trigger a different judge
|
|
117
|
+
in the next cycle, without any explicit dependency declaration.
|
|
118
|
+
Pipeline tools such as
|
|
119
|
+
[Apache Airflow](https://airflow.apache.org/) or
|
|
120
|
+
[GitHub Actions](https://docs.github.com/en/actions) require a
|
|
121
|
+
directed acyclic graph defined upfront; judges require none.
|
|
122
|
+
|
|
123
|
+
Every judge directory contains `.yml` test files alongside its `.rb`
|
|
124
|
+
script. A YAML file declares the initial facts (`input`), the count
|
|
125
|
+
of judge executions (`runs`), prerequisite judges (`before`),
|
|
126
|
+
post-condition scripts (`after`), and
|
|
127
|
+
[XPath](https://www.w3.org/TR/xpath/) assertions the factbase must
|
|
128
|
+
satisfy when the judge finishes (`expected`). Running `judges test`
|
|
129
|
+
creates a fresh, in-memory factbase per test case. Co-locating tests
|
|
130
|
+
with the script keeps each judge directory self-contained: one
|
|
131
|
+
directory holds both the deliverable and its verification.
|
|
132
|
+
|
|
133
|
+
The `push` and `pull` commands exchange the binary factbase with a
|
|
134
|
+
remote [Baza](https://github.com/yegor256/baza.rb) server via a
|
|
135
|
+
named-lock protocol. `pull` acquires the lock and downloads the
|
|
136
|
+
file; `push` uploads the modified file and releases the lock. This
|
|
137
|
+
lets distributed CI pipelines share a single evolving factbase
|
|
138
|
+
across multiple jobs without running a database: each job pulls,
|
|
139
|
+
runs `update` locally, and pushes back.
|
|
140
|
+
|
|
87
141
|
## How to contribute
|
|
88
142
|
|
|
89
143
|
Read
|
data/Rakefile
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
|
-
require 'tmpdir'
|
|
7
6
|
require 'English'
|
|
8
7
|
require 'securerandom'
|
|
8
|
+
require 'tmpdir'
|
|
9
9
|
|
|
10
10
|
Before do
|
|
11
11
|
@cwd = Dir.pwd
|
|
@@ -58,21 +58,21 @@ end
|
|
|
58
58
|
|
|
59
59
|
Then(/^([a-z].+) contains "([^"]*)"$/) do |file, txt|
|
|
60
60
|
data = File.read(file)
|
|
61
|
-
raise "The file #{file} doesn't contain '#{txt}':\n#{data}" unless data.include?(txt)
|
|
61
|
+
raise(StandardError, "The file #{file} doesn't contain '#{txt}':\n#{data}") unless data.include?(txt)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
Then(/^Stdout contains "([^"]*)"$/) do |txt|
|
|
65
|
-
raise "STDOUT doesn't contain '#{txt}':\n#{@stdout}" unless @stdout.include?(txt)
|
|
65
|
+
raise(StandardError, "STDOUT doesn't contain '#{txt}':\n#{@stdout}") unless @stdout.include?(txt)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
Then(/^Stdout is empty$/) do
|
|
69
|
-
raise "STDOUT is not empty:\n#{@stdout}" unless @stdout == ''
|
|
69
|
+
raise(StandardError, "STDOUT is not empty:\n#{@stdout}") unless @stdout == ''
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
Then(/^Exit code is zero$/) do
|
|
73
|
-
raise "Non-zero exit #{@exitstatus}:\n#{@stdout}" unless @exitstatus.zero?
|
|
73
|
+
raise(StandardError, "Non-zero exit #{@exitstatus}:\n#{@stdout}") unless @exitstatus.zero?
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
Then(/^Exit code is not zero$/) do
|
|
77
|
-
raise 'Zero exit code' if @exitstatus.zero?
|
|
77
|
+
raise(StandardError, 'Zero exit code') if @exitstatus.zero?
|
|
78
78
|
end
|
data/features/test.feature
CHANGED
|
@@ -16,9 +16,9 @@ Feature: Test
|
|
|
16
16
|
And Exit code is zero
|
|
17
17
|
|
|
18
18
|
Scenario: Factbase version can be set
|
|
19
|
-
When I run bin/judges with "--factbase 0.19.
|
|
19
|
+
When I run bin/judges with "--factbase 0.19.10 --verbose test --judge guess ./fixtures"
|
|
20
20
|
Then Exit code is zero
|
|
21
|
-
And Stdout contains "Factbase version to be used: '0.19.
|
|
21
|
+
And Stdout contains "Factbase version to be used: '0.19.10'"
|
|
22
22
|
|
|
23
23
|
Scenario: Simple test of no judges
|
|
24
24
|
Given I run bin/judges with "test --judge absent_for_sure ./fixtures"
|
data/fixtures/repeat/repeat.rb
CHANGED
data/judges.gemspec
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
require 'English'
|
|
7
7
|
|
|
8
8
|
Gem::Specification.new do |s|
|
|
9
|
-
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to?
|
|
9
|
+
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to?(:required_rubygems_version=)
|
|
10
10
|
s.required_ruby_version = '>=3.2'
|
|
11
11
|
s.name = 'judges'
|
|
12
|
-
s.version = '0.60.
|
|
12
|
+
s.version = '0.60.4'
|
|
13
13
|
s.license = 'MIT'
|
|
14
14
|
s.summary = 'Command-Line Tool for a Factbase'
|
|
15
15
|
s.description =
|
|
@@ -25,23 +25,23 @@ Gem::Specification.new do |s|
|
|
|
25
25
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
26
26
|
s.rdoc_options = ['--charset=UTF-8']
|
|
27
27
|
s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
|
|
28
|
-
s.add_dependency
|
|
29
|
-
s.add_dependency
|
|
30
|
-
s.add_dependency
|
|
31
|
-
s.add_dependency
|
|
32
|
-
s.add_dependency
|
|
33
|
-
s.add_dependency
|
|
34
|
-
s.add_dependency
|
|
35
|
-
s.add_dependency
|
|
36
|
-
s.add_dependency
|
|
37
|
-
s.add_dependency
|
|
38
|
-
s.add_dependency
|
|
39
|
-
s.add_dependency
|
|
40
|
-
s.add_dependency
|
|
41
|
-
s.add_dependency
|
|
42
|
-
s.add_dependency
|
|
43
|
-
s.add_dependency
|
|
44
|
-
s.add_dependency
|
|
45
|
-
s.add_dependency
|
|
28
|
+
s.add_dependency('backtrace', '~>0.4')
|
|
29
|
+
s.add_dependency('baza.rb', '~>0.10')
|
|
30
|
+
s.add_dependency('concurrent-ruby', '~>1.2')
|
|
31
|
+
s.add_dependency('elapsed', '~>0.2')
|
|
32
|
+
s.add_dependency('ellipsized', '~>0.3')
|
|
33
|
+
s.add_dependency('factbase', '~>0.16')
|
|
34
|
+
s.add_dependency('gli', '~>2.21')
|
|
35
|
+
s.add_dependency('iri', '~>0.11')
|
|
36
|
+
s.add_dependency('loog', '~>0.6')
|
|
37
|
+
s.add_dependency('moments', '~>0.3')
|
|
38
|
+
s.add_dependency('nokogiri', '~>1.10')
|
|
39
|
+
s.add_dependency('octokit', '~>10.0')
|
|
40
|
+
s.add_dependency('others', '~>0.1')
|
|
41
|
+
s.add_dependency('retries', '~>0.0')
|
|
42
|
+
s.add_dependency('tago', '~>0.2')
|
|
43
|
+
s.add_dependency('timeout', '~>0.4')
|
|
44
|
+
s.add_dependency('total', '~>0.4')
|
|
45
|
+
s.add_dependency('typhoeus', '~>1.3')
|
|
46
46
|
s.metadata['rubygems_mfa_required'] = 'true'
|
|
47
47
|
end
|
data/lib/judges/ascii_loog.rb
CHANGED
|
@@ -14,7 +14,6 @@ require_relative '../judges'
|
|
|
14
14
|
# Copyright:: Copyright (c) 2024-2026 Yegor Bugayenko
|
|
15
15
|
# License:: MIT
|
|
16
16
|
class Judges::AsciiLoog
|
|
17
|
-
# Unicode to ASCII symbol mapping
|
|
18
17
|
UNICODE_TO_ASCII = {
|
|
19
18
|
'👍' => '+',
|
|
20
19
|
'👎' => '-',
|
|
@@ -78,7 +77,7 @@ class Judges::AsciiLoog
|
|
|
78
77
|
|
|
79
78
|
# Delegate all other methods to the original logger.
|
|
80
79
|
def method_missing(method, *, &)
|
|
81
|
-
@loog.
|
|
80
|
+
@loog.public_send(method, *, &)
|
|
82
81
|
end
|
|
83
82
|
|
|
84
83
|
# Check if the original logger responds to a method.
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
|
-
require 'typhoeus'
|
|
7
|
-
require 'iri'
|
|
8
6
|
require 'baza-rb'
|
|
9
7
|
require 'elapsed'
|
|
8
|
+
require 'iri'
|
|
9
|
+
require 'typhoeus'
|
|
10
10
|
require_relative '../../judges'
|
|
11
11
|
|
|
12
12
|
# The +download+ command.
|
|
13
13
|
#
|
|
14
|
-
# This class is instantiated by the +bin/
|
|
14
|
+
# This class is instantiated by the +bin/judges+ command line interface. You
|
|
15
15
|
# are not supposed to instantiate it yourself.
|
|
16
16
|
#
|
|
17
17
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
@@ -29,7 +29,7 @@ class Judges::Download
|
|
|
29
29
|
# @param [Array] args List of command line arguments
|
|
30
30
|
# @raise [RuntimeError] If not exactly two arguments provided
|
|
31
31
|
def run(opts, args)
|
|
32
|
-
raise 'Exactly two arguments required' unless args.size == 2
|
|
32
|
+
raise(ArgumentError, 'Exactly two arguments required') unless args.size == 2
|
|
33
33
|
jname = args[0]
|
|
34
34
|
path = args[1]
|
|
35
35
|
name = File.basename(path)
|
|
@@ -50,8 +50,7 @@ class Judges::Download
|
|
|
50
50
|
baza.durable_lock(id, opts['owner'] || 'default')
|
|
51
51
|
begin
|
|
52
52
|
baza.durable_load(id, path)
|
|
53
|
-
|
|
54
|
-
throw :"👍 Downloaded durable ##{id} to #{path} (#{size} bytes)"
|
|
53
|
+
throw(:"👍 Downloaded durable ##{id} to #{path} (#{File.size(path)} bytes)")
|
|
55
54
|
ensure
|
|
56
55
|
baza.durable_unlock(id, opts['owner'] || 'default')
|
|
57
56
|
end
|
data/lib/judges/commands/eval.rb
CHANGED
|
@@ -9,7 +9,7 @@ require_relative '../../judges/impex'
|
|
|
9
9
|
|
|
10
10
|
# The +eval+ command.
|
|
11
11
|
#
|
|
12
|
-
# This class is instantiated by the +bin/
|
|
12
|
+
# This class is instantiated by the +bin/judges+ command line interface. You
|
|
13
13
|
# are not supposed to instantiate it yourself.
|
|
14
14
|
#
|
|
15
15
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
@@ -27,20 +27,19 @@ class Judges::Eval
|
|
|
27
27
|
# @param [Array] args List of command line arguments
|
|
28
28
|
# @raise [RuntimeError] If not exactly two arguments provided
|
|
29
29
|
def run(opts, args)
|
|
30
|
-
raise 'Exactly two arguments required' unless args.size == 2
|
|
30
|
+
raise(ArgumentError, 'Exactly two arguments required') unless args.size == 2
|
|
31
31
|
impex = Judges::Impex.new(@loog, args[0])
|
|
32
32
|
elapsed(@loog, level: Logger::INFO) do
|
|
33
33
|
$fb = impex.import(strict: false)
|
|
34
34
|
if opts['log']
|
|
35
|
-
require
|
|
35
|
+
require('factbase/logged')
|
|
36
36
|
$fb = Factbase::Logged.new($fb, @loog)
|
|
37
37
|
end
|
|
38
|
-
expr = args[1]
|
|
39
38
|
# rubocop:disable Security/Eval
|
|
40
|
-
eval(
|
|
39
|
+
eval(args[1])
|
|
41
40
|
# rubocop:enable Security/Eval
|
|
42
41
|
impex.export($fb)
|
|
43
|
-
throw
|
|
42
|
+
throw(:'👍 Evaluated successfully')
|
|
44
43
|
end
|
|
45
44
|
end
|
|
46
45
|
end
|
|
@@ -11,7 +11,7 @@ require_relative '../../judges/to_rel'
|
|
|
11
11
|
|
|
12
12
|
# The +import+ command.
|
|
13
13
|
#
|
|
14
|
-
# This class is instantiated by the +bin/
|
|
14
|
+
# This class is instantiated by the +bin/judges+ command line interface. You
|
|
15
15
|
# are not supposed to instantiate it yourself.
|
|
16
16
|
#
|
|
17
17
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
@@ -29,25 +29,25 @@ class Judges::Import
|
|
|
29
29
|
# @param [Array] args List of command line arguments
|
|
30
30
|
# @raise [RuntimeError] If not exactly two arguments provided or file not found
|
|
31
31
|
def run(opts, args)
|
|
32
|
-
raise 'Exactly two arguments required' unless args.size == 2
|
|
33
|
-
raise "File not found #{args[0].to_rel}" unless File.exist?(args[0])
|
|
32
|
+
raise(ArgumentError, 'Exactly two arguments required') unless args.size == 2
|
|
33
|
+
raise(StandardError, "File not found #{args[0].to_rel}") unless File.exist?(args[0])
|
|
34
34
|
elapsed(@loog, level: Logger::INFO) do
|
|
35
35
|
yaml = YAML.load_file(args[0], permitted_classes: [Time])
|
|
36
36
|
@loog.info("YAML loaded from #{args[0].to_rel} (#{yaml.size} facts)")
|
|
37
37
|
impex = Judges::Impex.new(@loog, args[1])
|
|
38
38
|
fb = impex.import(strict: false)
|
|
39
39
|
if opts['log']
|
|
40
|
-
require
|
|
40
|
+
require('factbase/logged')
|
|
41
41
|
fb = Factbase::Logged.new(fb, @loog)
|
|
42
42
|
end
|
|
43
43
|
yaml.each do |i|
|
|
44
44
|
f = fb.insert
|
|
45
45
|
i.each do |p, v|
|
|
46
|
-
f.
|
|
46
|
+
f.public_send(:"#{p}=", v)
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
impex.export(fb)
|
|
50
|
-
throw
|
|
50
|
+
throw(:"👍 Import of #{yaml.size} facts completed")
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
end
|