judges 0.21.0 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +18 -18
- data/bin/judges +27 -47
- data/judges.gemspec +1 -1
- data/lib/judges/baza.rb +103 -32
- data/lib/judges/commands/pull.rb +7 -2
- data/lib/judges/commands/push.rb +2 -1
- data/lib/judges/commands/update.rb +12 -11
- data/lib/judges/options.rb +22 -21
- data/lib/judges.rb +1 -1
- data/test/commands/test_pull.rb +29 -0
- data/test/test_baza.rb +56 -32
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17df0b6c88dd19b576bc701737985db26986e9818eb3c87b36180be92fca54f6
|
4
|
+
data.tar.gz: 48ef9ea5656a6bd78264f0b1f7021555ffa92eaf5be71d311d60e59ab0d3c0c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 722ef79a6af057ba1f4cf37860212b6a3c08f7aff838dfb4e8034e7970e27c4efe98e66da9c774e45707999b9e70966eacd19e4a1478a54a798d12b1d03b662b
|
7
|
+
data.tar.gz: c9551f302a6f0f02ef81e4a2ef5631c98bc2ad08a39982563749b29867d0bf06258a5e7a167179f70f899031cf2ffe097a014e9480a0a767192915d68f78479a
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
@@ -30,7 +30,7 @@ gem 'net-ping', '2.0.8', require: false
|
|
30
30
|
gem 'rake', '13.2.1', require: false
|
31
31
|
gem 'random-port', '~>0.0', require: false
|
32
32
|
gem 'rspec-rails', '6.1.3', require: false
|
33
|
-
gem 'rubocop', '1.65.
|
33
|
+
gem 'rubocop', '1.65.1', require: false
|
34
34
|
gem 'rubocop-performance', '1.21.1', require: false
|
35
35
|
gem 'rubocop-rspec', '3.0.3', require: false
|
36
36
|
gem 'simplecov', '0.22.0', require: false
|
data/Gemfile.lock
CHANGED
@@ -71,7 +71,7 @@ GEM
|
|
71
71
|
multi_test (~> 1.1)
|
72
72
|
sys-uname (~> 1.2)
|
73
73
|
cucumber-ci-environment (10.0.1)
|
74
|
-
cucumber-core (13.0.
|
74
|
+
cucumber-core (13.0.3)
|
75
75
|
cucumber-gherkin (>= 27, < 28)
|
76
76
|
cucumber-messages (>= 20, < 23)
|
77
77
|
cucumber-tag-expressions (> 5, < 7)
|
@@ -85,12 +85,12 @@ GEM
|
|
85
85
|
cucumber-tag-expressions (6.1.0)
|
86
86
|
decoor (0.0.1)
|
87
87
|
diff-lcs (1.5.1)
|
88
|
-
docile (1.4.
|
88
|
+
docile (1.4.1)
|
89
89
|
drb (2.2.1)
|
90
90
|
erubi (1.13.0)
|
91
91
|
ethon (0.16.0)
|
92
92
|
ffi (>= 1.15.0)
|
93
|
-
factbase (0.2.
|
93
|
+
factbase (0.2.1)
|
94
94
|
backtrace (> 0)
|
95
95
|
decoor (> 0)
|
96
96
|
json (~> 2.7)
|
@@ -120,7 +120,7 @@ GEM
|
|
120
120
|
loofah (2.22.0)
|
121
121
|
crass (~> 1.0.2)
|
122
122
|
nokogiri (>= 1.12.0)
|
123
|
-
loog (0.5.
|
123
|
+
loog (0.5.3)
|
124
124
|
mini_mime (1.1.5)
|
125
125
|
minitest (5.24.1)
|
126
126
|
minitest-reporters (1.7.1)
|
@@ -132,19 +132,19 @@ GEM
|
|
132
132
|
multi_test (1.1.0)
|
133
133
|
mutex_m (0.2.0)
|
134
134
|
net-ping (2.0.8)
|
135
|
-
nokogiri (1.16.
|
135
|
+
nokogiri (1.16.7-aarch64-linux)
|
136
136
|
racc (~> 1.4)
|
137
|
-
nokogiri (1.16.
|
137
|
+
nokogiri (1.16.7-arm-linux)
|
138
138
|
racc (~> 1.4)
|
139
|
-
nokogiri (1.16.
|
139
|
+
nokogiri (1.16.7-arm64-darwin)
|
140
140
|
racc (~> 1.4)
|
141
|
-
nokogiri (1.16.
|
141
|
+
nokogiri (1.16.7-x64-mingw-ucrt)
|
142
142
|
racc (~> 1.4)
|
143
|
-
nokogiri (1.16.
|
143
|
+
nokogiri (1.16.7-x86-linux)
|
144
144
|
racc (~> 1.4)
|
145
|
-
nokogiri (1.16.
|
145
|
+
nokogiri (1.16.7-x86_64-darwin)
|
146
146
|
racc (~> 1.4)
|
147
|
-
nokogiri (1.16.
|
147
|
+
nokogiri (1.16.7-x86_64-linux)
|
148
148
|
racc (~> 1.4)
|
149
149
|
others (0.0.3)
|
150
150
|
parallel (1.25.1)
|
@@ -153,8 +153,8 @@ GEM
|
|
153
153
|
racc
|
154
154
|
psych (5.1.2)
|
155
155
|
stringio
|
156
|
-
public_suffix (6.0.
|
157
|
-
racc (1.8.
|
156
|
+
public_suffix (6.0.1)
|
157
|
+
racc (1.8.1)
|
158
158
|
rack (3.1.7)
|
159
159
|
rack-session (2.0.0)
|
160
160
|
rack (>= 3.0.0)
|
@@ -187,7 +187,7 @@ GEM
|
|
187
187
|
reline (0.5.9)
|
188
188
|
io-console (~> 0.5)
|
189
189
|
retries (0.0.5)
|
190
|
-
rexml (3.3.
|
190
|
+
rexml (3.3.4)
|
191
191
|
strscan
|
192
192
|
rspec-core (3.13.0)
|
193
193
|
rspec-support (~> 3.13.0)
|
@@ -206,7 +206,7 @@ GEM
|
|
206
206
|
rspec-mocks (~> 3.13)
|
207
207
|
rspec-support (~> 3.13)
|
208
208
|
rspec-support (3.13.1)
|
209
|
-
rubocop (1.65.
|
209
|
+
rubocop (1.65.1)
|
210
210
|
json (~> 2.3)
|
211
211
|
language_server-protocol (>= 3.17.0)
|
212
212
|
parallel (~> 1.10)
|
@@ -252,7 +252,7 @@ GEM
|
|
252
252
|
webrick (1.8.1)
|
253
253
|
yaml (0.3.0)
|
254
254
|
yard (0.9.36)
|
255
|
-
zeitwerk (2.6.
|
255
|
+
zeitwerk (2.6.17)
|
256
256
|
|
257
257
|
PLATFORMS
|
258
258
|
aarch64-linux
|
@@ -272,7 +272,7 @@ DEPENDENCIES
|
|
272
272
|
rake (= 13.2.1)
|
273
273
|
random-port (~> 0.0)
|
274
274
|
rspec-rails (= 6.1.3)
|
275
|
-
rubocop (= 1.65.
|
275
|
+
rubocop (= 1.65.1)
|
276
276
|
rubocop-performance (= 1.21.1)
|
277
277
|
rubocop-rspec (= 3.0.3)
|
278
278
|
simplecov (= 0.22.0)
|
@@ -281,4 +281,4 @@ DEPENDENCIES
|
|
281
281
|
yard (= 0.9.36)
|
282
282
|
|
283
283
|
BUNDLED WITH
|
284
|
-
2.5.
|
284
|
+
2.5.16
|
data/bin/judges
CHANGED
@@ -32,7 +32,15 @@ Encoding.default_internal = Encoding::UTF_8
|
|
32
32
|
|
33
33
|
class JudgesGLI extend GLI::App
|
34
34
|
|
35
|
-
|
35
|
+
def self.run_it(cmd, ruby)
|
36
|
+
cmd.action do |global, options, args|
|
37
|
+
require_relative "../lib/judges/commands/#{ruby}"
|
38
|
+
@@loog.debug("Running '#{ruby}' command...")
|
39
|
+
Object.const_get("Judges::#{ruby.capitalize}").new(@@loog).run(options, args)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
@@loog = Loog::REGULAR
|
36
44
|
|
37
45
|
program_desc('Automated executor of judges for a factbase')
|
38
46
|
|
@@ -48,13 +56,13 @@ class JudgesGLI extend GLI::App
|
|
48
56
|
|
49
57
|
pre do |global, command, options, args|
|
50
58
|
if global[:verbose]
|
51
|
-
loog = Loog::VERBOSE
|
59
|
+
@@loog = Loog::VERBOSE
|
52
60
|
end
|
53
|
-
loog.debug("Judges #{Judges::VERSION}")
|
54
|
-
loog.debug("Factbase #{Factbase::VERSION}")
|
55
|
-
loog.debug("Ruby: #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}")
|
56
|
-
loog.debug("Current directory: #{Dir.getwd}")
|
57
|
-
loog.debug("Time: #{Time.now.utc.iso8601}")
|
61
|
+
@@loog.debug("Judges #{Judges::VERSION}")
|
62
|
+
@@loog.debug("Factbase #{Factbase::VERSION}")
|
63
|
+
@@loog.debug("Ruby: #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}")
|
64
|
+
@@loog.debug("Current directory: #{Dir.getwd}")
|
65
|
+
@@loog.debug("Time: #{Time.now.utc.iso8601}")
|
58
66
|
true
|
59
67
|
end
|
60
68
|
|
@@ -72,44 +80,29 @@ class JudgesGLI extend GLI::App
|
|
72
80
|
c.switch([:summary], default_value: false)
|
73
81
|
c.desc 'Use default logging facility'
|
74
82
|
c.switch([:log], default_value: true)
|
75
|
-
c
|
76
|
-
require_relative '../lib/judges/commands/update'
|
77
|
-
Judges::Update.new(loog).run(options, args)
|
78
|
-
end
|
83
|
+
run_it(c, 'update')
|
79
84
|
end
|
80
85
|
|
81
86
|
desc 'Evaluate a single Ruby expression on the factbase'
|
82
87
|
command :eval do |c|
|
83
|
-
c
|
84
|
-
require_relative '../lib/judges/commands/eval'
|
85
|
-
Judges::Eval.new(loog).run(options, args)
|
86
|
-
end
|
88
|
+
run_it(c, 'eval')
|
87
89
|
end
|
88
90
|
|
89
91
|
desc 'Join two factbases'
|
90
92
|
command :join do |c|
|
91
|
-
c
|
92
|
-
require_relative '../lib/judges/commands/join'
|
93
|
-
Judges::Join.new(loog).run(options, args)
|
94
|
-
end
|
93
|
+
run_it(c, 'join')
|
95
94
|
end
|
96
95
|
|
97
96
|
desc 'Import YAML into a factbase'
|
98
97
|
command :import do |c|
|
99
|
-
c
|
100
|
-
require_relative '../lib/judges/commands/import'
|
101
|
-
Judges::Import.new(loog).run(options, args)
|
102
|
-
end
|
98
|
+
run_it(c, 'import')
|
103
99
|
end
|
104
100
|
|
105
101
|
desc 'Remove the facts that are too old'
|
106
102
|
command :trim do |c|
|
107
103
|
c.desc 'Only the facts that match the expression are deleted'
|
108
104
|
c.flag([:query], default_value: '(never)')
|
109
|
-
c
|
110
|
-
require_relative '../lib/judges/commands/trim'
|
111
|
-
Judges::Trim.new(loog).run(options, args)
|
112
|
-
end
|
105
|
+
run_it(c, 'trim')
|
113
106
|
end
|
114
107
|
|
115
108
|
desc 'Print the factbase into a human-readable format (YAML, JSON, etc.)'
|
@@ -128,18 +121,12 @@ class JudgesGLI extend GLI::App
|
|
128
121
|
c.flag([:hidden], default_value: '_id,_time,_version')
|
129
122
|
c.desc 'Print even if target file already exists and is older than the factbase'
|
130
123
|
c.switch([:force], default_value: false)
|
131
|
-
c
|
132
|
-
require_relative '../lib/judges/commands/print'
|
133
|
-
Judges::Print.new(loog).run(options, args)
|
134
|
-
end
|
124
|
+
run_it(c, 'print')
|
135
125
|
end
|
136
126
|
|
137
127
|
desc 'Inspect the factbase and print all its possible meta-data'
|
138
128
|
command :inspect do |c|
|
139
|
-
c
|
140
|
-
require_relative '../lib/judges/commands/inspect'
|
141
|
-
Judges::Inspect.new(loog).run(options, args)
|
142
|
-
end
|
129
|
+
run_it(c, 'inspect')
|
143
130
|
end
|
144
131
|
|
145
132
|
desc 'Run automated tests for all judges'
|
@@ -160,10 +147,7 @@ class JudgesGLI extend GLI::App
|
|
160
147
|
c.switch([:quiet], default_value: false)
|
161
148
|
c.desc 'Use default logging facility'
|
162
149
|
c.switch([:log], default_value: true)
|
163
|
-
c
|
164
|
-
require_relative '../lib/judges/commands/test'
|
165
|
-
Judges::Test.new(loog).run(options, args)
|
166
|
-
end
|
150
|
+
run_it(c, 'test')
|
167
151
|
end
|
168
152
|
|
169
153
|
desc 'Push the factbase to the server'
|
@@ -184,10 +168,9 @@ class JudgesGLI extend GLI::App
|
|
184
168
|
c.flag([:meta], type: String, multiple: true)
|
185
169
|
c.desc 'How many times to retry'
|
186
170
|
c.flag([:retries], type: Integer, default_value: 3)
|
187
|
-
c.
|
188
|
-
|
189
|
-
|
190
|
-
end
|
171
|
+
c.desc 'Turn on the package compression'
|
172
|
+
c.switch([:zip], default_value: true)
|
173
|
+
run_it(c, 'push')
|
191
174
|
end
|
192
175
|
|
193
176
|
desc 'Pull the factbase from the server'
|
@@ -208,10 +191,7 @@ class JudgesGLI extend GLI::App
|
|
208
191
|
c.flag([:owner], default_value: 'default', type: String)
|
209
192
|
c.desc 'How many times to retry'
|
210
193
|
c.flag([:retries], type: Integer, default_value: 3)
|
211
|
-
c
|
212
|
-
require_relative '../lib/judges/commands/pull'
|
213
|
-
Judges::Pull.new(loog).run(options, args)
|
214
|
-
end
|
194
|
+
run_it(c, 'pull')
|
215
195
|
end
|
216
196
|
end
|
217
197
|
|
data/judges.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
27
27
|
s.required_ruby_version = '>=3.2'
|
28
28
|
s.name = 'judges'
|
29
|
-
s.version = '0.
|
29
|
+
s.version = '0.22.0'
|
30
30
|
s.license = 'MIT'
|
31
31
|
s.summary = 'Command-Line Tool for a Factbase'
|
32
32
|
s.description =
|
data/lib/judges/baza.rb
CHANGED
@@ -38,7 +38,7 @@ require_relative '../judges/elapsed'
|
|
38
38
|
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
39
39
|
# License:: MIT
|
40
40
|
class Judges::Baza
|
41
|
-
def initialize(host, port, token, ssl: true, timeout: 30, retries: 3, loog: Loog::NULL)
|
41
|
+
def initialize(host, port, token, ssl: true, timeout: 30, retries: 3, loog: Loog::NULL, compression: true)
|
42
42
|
@host = host
|
43
43
|
@port = port
|
44
44
|
@ssl = ssl
|
@@ -46,6 +46,7 @@ class Judges::Baza
|
|
46
46
|
@timeout = timeout
|
47
47
|
@loog = loog
|
48
48
|
@retries = retries
|
49
|
+
@compression = compression
|
49
50
|
end
|
50
51
|
|
51
52
|
# Push factbase to the server.
|
@@ -62,18 +63,22 @@ class Judges::Baza
|
|
62
63
|
unless meta.empty?
|
63
64
|
hdrs = hdrs.merge('X-Zerocracy-Meta' => meta.map { |v| Base64.encode64(v).gsub("\n", '') }.join(' '))
|
64
65
|
end
|
66
|
+
params = {
|
67
|
+
connecttimeout: @timeout,
|
68
|
+
timeout: @timeout,
|
69
|
+
body: data,
|
70
|
+
headers: hdrs
|
71
|
+
}
|
65
72
|
elapsed(@loog) do
|
66
|
-
ret =
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
timeout: @timeout
|
73
|
+
ret =
|
74
|
+
with_retries(max_tries: @retries) do
|
75
|
+
checked(
|
76
|
+
Typhoeus::Request.put(
|
77
|
+
home.append('push').append(name).to_s,
|
78
|
+
@compression ? zipped(params) : params
|
79
|
+
)
|
74
80
|
)
|
75
|
-
|
76
|
-
end
|
81
|
+
end
|
77
82
|
id = ret.body.to_i
|
78
83
|
throw :"Pushed #{data.size} bytes to #{@host}, job ID is ##{id}"
|
79
84
|
end
|
@@ -117,20 +122,63 @@ class Judges::Baza
|
|
117
122
|
def finished?(id)
|
118
123
|
finished = false
|
119
124
|
elapsed(@loog) do
|
120
|
-
ret =
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
+
ret =
|
126
|
+
with_retries(max_tries: @retries) do
|
127
|
+
checked(
|
128
|
+
Typhoeus::Request.get(
|
129
|
+
home.append('finished').append(id).to_s,
|
130
|
+
headers:
|
131
|
+
)
|
125
132
|
)
|
126
|
-
|
127
|
-
end
|
133
|
+
end
|
128
134
|
finished = ret.body == 'yes'
|
129
135
|
throw :"The job ##{id} is #{finished ? '' : 'not yet '}finished at #{@host}"
|
130
136
|
end
|
131
137
|
finished
|
132
138
|
end
|
133
139
|
|
140
|
+
# Read and return the stdout of the job.
|
141
|
+
# @param [Integer] id The ID of the job on the server
|
142
|
+
# @return [String] The stdout, as a text
|
143
|
+
def stdout(id)
|
144
|
+
stdout = ''
|
145
|
+
elapsed(@loog) do
|
146
|
+
ret =
|
147
|
+
with_retries(max_tries: @retries) do
|
148
|
+
checked(
|
149
|
+
Typhoeus::Request.get(
|
150
|
+
home.append('stdout').append(id).to_s,
|
151
|
+
headers:
|
152
|
+
)
|
153
|
+
)
|
154
|
+
end
|
155
|
+
ret.body
|
156
|
+
throw :"The stdout of the job ##{id} has #{stdout.split("\n")} lines"
|
157
|
+
end
|
158
|
+
stdout
|
159
|
+
end
|
160
|
+
|
161
|
+
# Read and return the exit code of the job.
|
162
|
+
# @param [Integer] id The ID of the job on the server
|
163
|
+
# @return [Integer] The exit code
|
164
|
+
def exit_code(id)
|
165
|
+
code = 0
|
166
|
+
elapsed(@loog) do
|
167
|
+
ret =
|
168
|
+
with_retries(max_tries: @retries) do
|
169
|
+
checked(
|
170
|
+
Typhoeus::Request.get(
|
171
|
+
home.append('exit').append(id).to_s,
|
172
|
+
headers:
|
173
|
+
)
|
174
|
+
)
|
175
|
+
end
|
176
|
+
code = ret.body.to_i
|
177
|
+
throw :"The exit code of the job ##{id} is #{code}"
|
178
|
+
end
|
179
|
+
code
|
180
|
+
end
|
181
|
+
|
134
182
|
# Lock the name.
|
135
183
|
# @param [String] name The name of the job on the server
|
136
184
|
# @param [String] owner The owner of the lock (any string)
|
@@ -171,14 +219,15 @@ class Judges::Baza
|
|
171
219
|
def recent(name)
|
172
220
|
job = 0
|
173
221
|
elapsed(@loog) do
|
174
|
-
ret =
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
222
|
+
ret =
|
223
|
+
with_retries(max_tries: @retries) do
|
224
|
+
checked(
|
225
|
+
Typhoeus::Request.get(
|
226
|
+
home.append('recent').append("#{name}.txt").to_s,
|
227
|
+
headers:
|
228
|
+
)
|
179
229
|
)
|
180
|
-
|
181
|
-
end
|
230
|
+
end
|
182
231
|
job = ret.body.to_i
|
183
232
|
throw :"The recent \"#{name}\" job's ID is ##{job} at #{@host}"
|
184
233
|
end
|
@@ -191,14 +240,15 @@ class Judges::Baza
|
|
191
240
|
def name_exists?(name)
|
192
241
|
exists = 0
|
193
242
|
elapsed(@loog) do
|
194
|
-
ret =
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
243
|
+
ret =
|
244
|
+
with_retries(max_tries: @retries) do
|
245
|
+
checked(
|
246
|
+
Typhoeus::Request.get(
|
247
|
+
home.append('exists').append(name).to_s,
|
248
|
+
headers:
|
249
|
+
)
|
199
250
|
)
|
200
|
-
|
201
|
-
end
|
251
|
+
end
|
202
252
|
exists = ret.body == 'yes'
|
203
253
|
throw :"The name \"#{name}\" #{exists ? 'exists' : "doesn't exist"} at #{@host}"
|
204
254
|
end
|
@@ -215,6 +265,27 @@ class Judges::Baza
|
|
215
265
|
}
|
216
266
|
end
|
217
267
|
|
268
|
+
def zipped(params)
|
269
|
+
body = gzip(params.fetch(:body))
|
270
|
+
headers = params
|
271
|
+
.fetch(:headers)
|
272
|
+
.merge({
|
273
|
+
'Content-Type' => 'application/zip',
|
274
|
+
'Content-Encoding' => 'gzip',
|
275
|
+
'Content-Length' => body.size
|
276
|
+
})
|
277
|
+
params.merge(body:, headers:)
|
278
|
+
end
|
279
|
+
|
280
|
+
def gzip(data)
|
281
|
+
''.dup.tap do |result|
|
282
|
+
io = StringIO.new(result)
|
283
|
+
gz = Zlib::GzipWriter.new(io)
|
284
|
+
gz.write(data)
|
285
|
+
gz.close
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
218
289
|
def home
|
219
290
|
Iri.new('')
|
220
291
|
.host(@host)
|
data/lib/judges/commands/pull.rb
CHANGED
@@ -51,9 +51,14 @@ class Judges::Pull
|
|
51
51
|
)
|
52
52
|
name = args[0]
|
53
53
|
elapsed(@loog) do
|
54
|
+
baza.lock(name, opts['owner'])
|
54
55
|
if baza.name_exists?(name)
|
55
|
-
baza.
|
56
|
-
|
56
|
+
jid = baza.recent(name)
|
57
|
+
unless baza.exit_code(jid).zero?
|
58
|
+
@loog.warn("STDOUT of the job ##{jid} (from the server):\n#{baza.stdout(jid)}")
|
59
|
+
raise "The job ##{jid} ('#{name}') is broken, maybe you should expire it"
|
60
|
+
end
|
61
|
+
fb.import(baza.pull(wait(name, baza, jid, opts['wait'])))
|
57
62
|
Judges::Impex.new(@loog, args[1]).export(fb)
|
58
63
|
throw :"Pulled #{fb.size} facts by the name '#{name}'"
|
59
64
|
else
|
data/lib/judges/commands/push.rb
CHANGED
@@ -48,7 +48,8 @@ class Judges::Push
|
|
48
48
|
ssl: opts['ssl'],
|
49
49
|
timeout: (opts['timeout'] || 30).to_i,
|
50
50
|
loog: @loog,
|
51
|
-
retries: (opts['retries'] || 3).to_i
|
51
|
+
retries: (opts['retries'] || 3).to_i,
|
52
|
+
compression: opts.fetch('zip', true)
|
52
53
|
)
|
53
54
|
elapsed(@loog) do
|
54
55
|
baza.lock(name, opts['owner'])
|
@@ -64,7 +64,7 @@ class Judges::Update
|
|
64
64
|
loop do
|
65
65
|
c += 1
|
66
66
|
if c > 1
|
67
|
-
@loog.info("\
|
67
|
+
@loog.info("\nStarting cycle ##{c}#{opts['max-cycles'] ? " (out of #{opts['max-cycles']})" : ''}...")
|
68
68
|
end
|
69
69
|
delta = cycle(opts, judges, fb, options)
|
70
70
|
churn += delta
|
@@ -103,17 +103,18 @@ class Judges::Update
|
|
103
103
|
churn = Judges::Churn.new(0, 0)
|
104
104
|
global = {}
|
105
105
|
elapsed(@loog) do
|
106
|
-
done =
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
106
|
+
done =
|
107
|
+
judges.each_with_index do |p, i|
|
108
|
+
@loog.info("\n👉 Running #{p.name} (##{i}) at #{p.dir.to_rel}...")
|
109
|
+
elapsed(@loog) do
|
110
|
+
c = one_judge(fb, p, global, options)
|
111
|
+
churn += c
|
112
|
+
throw :"👍 The judge #{p.name} modified #{c} facts out of #{fb.size}"
|
113
|
+
end
|
114
|
+
rescue StandardError, SyntaxError => e
|
115
|
+
@loog.warn(Backtrace.new(e))
|
116
|
+
churn << e.message
|
112
117
|
end
|
113
|
-
rescue StandardError, SyntaxError => e
|
114
|
-
@loog.warn(Backtrace.new(e))
|
115
|
-
churn << e.message
|
116
|
-
end
|
117
118
|
throw :"👍 #{done} judge(s) processed" if churn.errors.empty?
|
118
119
|
throw :"❌ #{done} judge(s) processed with #{churn.errors.size} errors"
|
119
120
|
end
|
data/lib/judges/options.rb
CHANGED
@@ -52,32 +52,33 @@ class Judges::Options
|
|
52
52
|
v = v.to_s
|
53
53
|
v = "#{v[0..3]}#{'*' * (v.length - 8)}#{v[-4..]}" if v.length > 8
|
54
54
|
"#{k} → \"#{v}\""
|
55
|
-
end.join("\n")
|
55
|
+
end.sort.join("\n")
|
56
56
|
end
|
57
57
|
|
58
58
|
def to_h
|
59
|
-
@to_h ||=
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
59
|
+
@to_h ||=
|
60
|
+
begin
|
61
|
+
pp = @pairs || []
|
62
|
+
pp = pp.split(',') if pp.is_a?(String)
|
63
|
+
if pp.is_a?(Array)
|
64
|
+
pp = pp
|
65
|
+
.compact
|
66
|
+
.map(&:strip)
|
67
|
+
.reject(&:empty?)
|
68
|
+
.map { |s| s.split('=', 2) }
|
69
|
+
.map { |a| a.size == 1 ? [a[0], nil] : a }
|
70
|
+
.reject { |a| a[0].empty? }
|
71
|
+
.to_h
|
72
|
+
end
|
73
|
+
pp
|
74
|
+
.reject { |k, _| k.nil? }
|
75
|
+
.reject { |k, _| k.is_a?(String) && k.empty? }
|
70
76
|
.to_h
|
77
|
+
.transform_values { |v| v.nil? ? 'true' : v }
|
78
|
+
.transform_values { |v| v.is_a?(String) ? v.strip : v }
|
79
|
+
.transform_values { |v| v.is_a?(String) && v.match?(/^[0-9]+$/) ? v.to_i : v }
|
80
|
+
.transform_keys { |k| k.to_s.strip.upcase.to_sym }
|
71
81
|
end
|
72
|
-
pp
|
73
|
-
.reject { |k, _| k.nil? }
|
74
|
-
.reject { |k, _| k.is_a?(String) && k.empty? }
|
75
|
-
.to_h
|
76
|
-
.transform_values { |v| v.nil? ? 'true' : v }
|
77
|
-
.transform_values { |v| v.is_a?(String) ? v.strip : v }
|
78
|
-
.transform_values { |v| v.is_a?(String) && v.match?(/^[0-9]+$/) ? v.to_i : v }
|
79
|
-
.transform_keys { |k| k.to_s.strip.upcase.to_sym }
|
80
|
-
end
|
81
82
|
end
|
82
83
|
|
83
84
|
# Get option by name.
|
data/lib/judges.rb
CHANGED
data/test/commands/test_pull.rb
CHANGED
@@ -38,6 +38,7 @@ class TestPull < Minitest::Test
|
|
38
38
|
stub_request(:get, 'http://example.org/exists/foo').to_return(body: 'yes')
|
39
39
|
stub_request(:get, 'http://example.org/recent/foo.txt').to_return(body: '42')
|
40
40
|
stub_request(:get, 'http://example.org/finished/42').to_return(body: 'yes')
|
41
|
+
stub_request(:get, 'http://example.org/exit/42').to_return(body: '0')
|
41
42
|
fb = Factbase.new
|
42
43
|
fb.insert.foo = 42
|
43
44
|
stub_request(:get, 'http://example.org/pull/42.fb').to_return(body: fb.export)
|
@@ -58,4 +59,32 @@ class TestPull < Minitest::Test
|
|
58
59
|
fb.import(File.binread(file))
|
59
60
|
end
|
60
61
|
end
|
62
|
+
|
63
|
+
def test_fail_pull_when_job_is_broken
|
64
|
+
WebMock.disable_net_connect!
|
65
|
+
stub_request(:get, 'http://example.org/lock/foo?owner=none').to_return(status: 302)
|
66
|
+
stub_request(:get, 'http://example.org/exists/foo').to_return(body: 'yes')
|
67
|
+
stub_request(:get, 'http://example.org/recent/foo.txt').to_return(body: '42')
|
68
|
+
stub_request(:get, 'http://example.org/finished/42').to_return(body: 'yes')
|
69
|
+
stub_request(:get, 'http://example.org/exit/42').to_return(body: '1')
|
70
|
+
stub_request(:get, 'http://example.org/stdout/42').to_return(body: 'oops, some trouble here')
|
71
|
+
Dir.mktmpdir do |d|
|
72
|
+
file = File.join(d, 'base.fb')
|
73
|
+
e =
|
74
|
+
assert_raises do
|
75
|
+
Judges::Pull.new(Loog::NULL).run(
|
76
|
+
{
|
77
|
+
'token' => '000',
|
78
|
+
'host' => 'example.org',
|
79
|
+
'port' => 80,
|
80
|
+
'ssl' => false,
|
81
|
+
'wait' => 10,
|
82
|
+
'owner' => 'none'
|
83
|
+
},
|
84
|
+
['foo', file]
|
85
|
+
)
|
86
|
+
end
|
87
|
+
assert(e.message.include?('expire it'), e)
|
88
|
+
end
|
89
|
+
end
|
61
90
|
end
|
data/test/test_baza.rb
CHANGED
@@ -22,8 +22,10 @@
|
|
22
22
|
|
23
23
|
require 'minitest/autorun'
|
24
24
|
require 'webmock/minitest'
|
25
|
+
require 'webrick'
|
25
26
|
require 'loog'
|
26
27
|
require 'socket'
|
28
|
+
require 'stringio'
|
27
29
|
require 'random-port'
|
28
30
|
require_relative '../lib/judges'
|
29
31
|
require_relative '../lib/judges/baza'
|
@@ -76,53 +78,75 @@ class TestBaza < Minitest::Test
|
|
76
78
|
end
|
77
79
|
|
78
80
|
def test_real_http
|
79
|
-
req =
|
80
|
-
|
81
|
-
|
82
|
-
|
81
|
+
req =
|
82
|
+
with_http_server(200, 'yes') do |baza|
|
83
|
+
baza.name_exists?('simple')
|
84
|
+
end
|
85
|
+
assert_equal("judges #{Judges::VERSION}", req['user-agent'])
|
83
86
|
end
|
84
87
|
|
85
88
|
def test_push_with_meta
|
86
|
-
req =
|
87
|
-
|
88
|
-
|
89
|
-
|
89
|
+
req =
|
90
|
+
with_http_server(200, 'yes') do |baza|
|
91
|
+
baza.push('simple', 'hello, world!', ['boom!', 'хей!'])
|
92
|
+
end
|
93
|
+
assert_equal('Ym9vbSE= 0YXQtdC5IQ==', req['x-zerocracy-meta'])
|
90
94
|
end
|
91
95
|
|
92
96
|
def test_push_with_big_meta
|
93
|
-
req =
|
94
|
-
baza
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
97
|
+
req =
|
98
|
+
with_http_server(200, 'yes') do |baza|
|
99
|
+
baza.push(
|
100
|
+
'simple',
|
101
|
+
'hello, world!',
|
102
|
+
[
|
103
|
+
'pages_url:https://zerocracy.github.io/zerocracy.html',
|
104
|
+
'others:https://zerocracy.github.io/zerocracy.html',
|
105
|
+
'duration:59595'
|
106
|
+
]
|
107
|
+
)
|
108
|
+
end
|
109
|
+
assert(req['x-zerocracy-meta'])
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_push_compressed_content
|
113
|
+
req =
|
114
|
+
with_http_server(200, 'yes') do |baza|
|
115
|
+
baza.push('simple', 'hello, world!', %w[meta1 meta2 meta3])
|
116
|
+
end
|
117
|
+
assert_equal('application/zip', req.content_type)
|
118
|
+
assert_equal('gzip', req['content-encoding'])
|
119
|
+
body = Zlib::GzipReader.zcat(StringIO.new(req.body))
|
120
|
+
assert_equal('hello, world!', body)
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_push_compression_disabled
|
124
|
+
req =
|
125
|
+
with_http_server(200, 'yes', compression: false) do |baza|
|
126
|
+
baza.push('simple', 'hello, world!', %w[meta1 meta2 meta3])
|
127
|
+
end
|
128
|
+
assert_equal('application/octet-stream', req.content_type)
|
129
|
+
assert_equal('hello, world!', req.body)
|
105
130
|
end
|
106
131
|
|
107
132
|
private
|
108
133
|
|
109
|
-
def with_http_server(code, response)
|
134
|
+
def with_http_server(code, response, opts = {})
|
135
|
+
opts = { ssl: false, timeout: 1 }.merge(opts)
|
110
136
|
WebMock.enable_net_connect!
|
111
|
-
req =
|
137
|
+
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
|
112
138
|
host = '127.0.0.1'
|
113
139
|
RandomPort::Pool::SINGLETON.acquire do |port|
|
114
140
|
server = TCPServer.new(host, port)
|
115
|
-
t =
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
141
|
+
t =
|
142
|
+
Thread.new do
|
143
|
+
socket = server.accept
|
144
|
+
req.parse(socket)
|
145
|
+
req.body
|
146
|
+
socket.puts "HTTP/1.1 #{code} OK\r\nContent-Length: #{response.length}\r\n\r\n#{response}"
|
147
|
+
socket.close
|
121
148
|
end
|
122
|
-
|
123
|
-
socket.close
|
124
|
-
end
|
125
|
-
yield Judges::Baza.new(host, port, '0000', ssl: false, timeout: 1)
|
149
|
+
yield Judges::Baza.new(host, port, '0000', **opts)
|
126
150
|
t.join
|
127
151
|
end
|
128
152
|
req
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: judges
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backtrace
|