judges 0.21.0 → 0.22.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/.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
|