robot_sweatshop 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +11 -11
- data/Rakefile +1 -1
- data/bin/README.md +23 -0
- data/bin/sweatshop +1 -1
- data/bin/sweatshop-assembler +101 -0
- data/bin/sweatshop-conveyor +64 -0
- data/bin/{sweatshop-input-http → sweatshop-input} +13 -7
- data/bin/sweatshop-job-dictionary +53 -0
- data/bin/sweatshop-payload-parser +28 -28
- data/bin/sweatshop-worker +58 -0
- data/config.defaults.yaml +6 -4
- data/lib/README.md +10 -13
- data/lib/robot_sweatshop/cli/common.rb +1 -1
- data/lib/robot_sweatshop/cli/config.rb +1 -1
- data/lib/robot_sweatshop/cli/job.rb +1 -1
- data/lib/robot_sweatshop/cli/start.rb +2 -2
- data/lib/robot_sweatshop/config.rb +2 -0
- data/lib/robot_sweatshop/connections.rb +17 -0
- data/lib/robot_sweatshop/create-config-directories.rb +0 -1
- data/lib/robot_sweatshop.rb +1 -2
- data/robot_sweatshop.eye +30 -32
- data/robot_sweatshop.gemspec +8 -6
- data/test/README.md +3 -1
- data/test/all.rb +35 -0
- data/test/assembler_spec.rb +89 -0
- data/test/conveyor_spec.rb +67 -0
- data/test/data/weird_job.yaml +6 -0
- data/test/end-to-end_spec.rb +19 -13
- data/test/input_spec.rb +49 -0
- data/test/job_dictionary_spec.rb +70 -0
- data/test/payload_parser_spec.rb +37 -26
- data/test/shared/helpers/input.rb +73 -0
- data/test/shared/helpers/output.rb +14 -0
- data/test/shared/helpers.rb +4 -83
- data/test/shared/scaffolding.rb +42 -0
- data/test/shared/stub.rb +44 -0
- data/test/worker_spec.rb +59 -0
- metadata +76 -44
- data/bin/sweatshop-job-assembler +0 -82
- data/bin/sweatshop-job-worker +0 -45
- data/bin/sweatshop-queue-broadcaster +0 -20
- data/bin/sweatshop-queue-handler +0 -24
- data/bin/sweatshop-queue-watcher +0 -18
- data/lib/robot_sweatshop/moneta-queue.rb +0 -49
- data/lib/robot_sweatshop/queue-helper.rb +0 -32
- data/robot_sweatshop.production.eye +0 -7
- data/robot_sweatshop.testing.eye +0 -7
- data/test/input_http_spec.rb +0 -49
- data/test/job_assembler_spec.rb +0 -80
- data/test/job_worker_spec.rb +0 -65
- data/test/moneta-queue_spec.rb +0 -49
- data/test/queue_broadcaster_spec.rb +0 -39
- data/test/queue_handler_spec.rb +0 -54
- data/test/run_all.rb +0 -3
- data/test/shared/process_spawning.rb +0 -16
data/test/shared/helpers.rb
CHANGED
@@ -1,84 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'json'
|
4
|
-
require 'robot_sweatshop/moneta-queue'
|
5
|
-
require 'robot_sweatshop/payload'
|
6
|
-
require 'robot_sweatshop/config'
|
1
|
+
require_relative 'helpers/input'
|
2
|
+
require_relative 'helpers/output'
|
7
3
|
|
8
|
-
|
9
|
-
|
10
|
-
MonetaQueue.watched_queues.each do |queue|
|
11
|
-
queue = MonetaQueue.new queue
|
12
|
-
queue.clear
|
13
|
-
end
|
14
|
-
end
|
15
|
-
def enqueue(queue_name, item)
|
16
|
-
queue = MonetaQueue.new queue_name
|
17
|
-
queue.enqueue item
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
module InHelper
|
22
|
-
def example_raw_payload(of_format:)
|
23
|
-
payload_strings = YAML.load_file "#{__dir__}/../data/payload_data.yaml"
|
24
|
-
payload_strings[of_format.downcase]
|
25
|
-
end
|
26
|
-
def input_http_url(for_job: 'test_job')
|
27
|
-
"http://localhost:#{configatron.http_port}/payload-for/#{for_job}"
|
28
|
-
end
|
29
|
-
def user_agent_for(format)
|
30
|
-
case format
|
31
|
-
when 'Bitbucket'
|
32
|
-
'Bitbucket.org'
|
33
|
-
when 'Github'
|
34
|
-
'Github-Hookshot'
|
35
|
-
else
|
36
|
-
'SomeUserAgent'
|
37
|
-
end
|
38
|
-
end
|
39
|
-
def example_payload_request(of_format:)
|
40
|
-
{
|
41
|
-
payload: example_raw_payload(of_format: of_format),
|
42
|
-
user_agent: user_agent_for(of_format)
|
43
|
-
}
|
44
|
-
end
|
45
|
-
def job_request_data(type)
|
46
|
-
case type
|
47
|
-
when 'Git'
|
48
|
-
['Bitbucket', 'git_job'] # develop branch payload
|
49
|
-
when 'JSON'
|
50
|
-
['JSON', 'test_job']
|
51
|
-
when 'MinimalJob'
|
52
|
-
['JSON', 'minimal_job']
|
53
|
-
when 'IgnoredBranch'
|
54
|
-
['Github', 'git_job'] # master branch payload
|
55
|
-
when 'UnknownJob'
|
56
|
-
['Bitbucket', 'unknown_job']
|
57
|
-
when 'EmptyJob'
|
58
|
-
['JSON', 'empty_job']
|
59
|
-
when 'NonJSON'
|
60
|
-
['NonJSON', 'test_job']
|
61
|
-
else
|
62
|
-
['', '']
|
63
|
-
end
|
64
|
-
end
|
65
|
-
def example_job_request(of_type:)
|
66
|
-
format, job_name = job_request_data of_type
|
67
|
-
JSON.generate payload: example_raw_payload(of_format: format),
|
68
|
-
job_name: job_name,
|
69
|
-
user_agent: user_agent_for(format)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
module JobHelper
|
74
|
-
def example_job(in_context: {}, with_commands: [])
|
75
|
-
JSON.generate context: in_context,
|
76
|
-
commands: with_commands,
|
77
|
-
job_name: 'test_job'
|
78
|
-
end
|
79
|
-
def reset_test_file
|
80
|
-
test_file = File.expand_path "#{configatron.workspace_path}/test_job-testingid/test.txt"
|
81
|
-
FileUtils.rm_rf test_file
|
82
|
-
test_file
|
83
|
-
end
|
84
|
-
end
|
4
|
+
$a_moment = 0.1
|
5
|
+
$a_while = 1
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'oj'
|
4
|
+
require 'robot_sweatshop/config'
|
5
|
+
require 'robot_sweatshop/connections'
|
6
|
+
require_relative 'stub'
|
7
|
+
|
8
|
+
module Setup
|
9
|
+
def self.empty_conveyor
|
10
|
+
db_file = "#{configatron.database_path}/conveyor.db"
|
11
|
+
File.truncate db_file, 0 if File.exist? db_file
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.populate_test_jobs
|
15
|
+
test_jobs = Dir.glob "#{__dir__}/../data/*_job.yaml"
|
16
|
+
test_jobs.each { |test_job| FileUtils.cp test_job, configatron.job_path }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module TestProcess
|
21
|
+
def self.start(name_list)
|
22
|
+
pids = []
|
23
|
+
name_list.each do |name|
|
24
|
+
input_script = File.expand_path "#{__dir__}/../../bin/sweatshop-#{name}"
|
25
|
+
input_script += ' testingid' if name == 'worker'
|
26
|
+
pids.push spawn(input_script, out: '/dev/null', err: '/dev/null')
|
27
|
+
end
|
28
|
+
pids
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.stop(pid_list)
|
32
|
+
pid_list.each { |pid| Process.kill 'TERM', pid }
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.stub(process_name)
|
36
|
+
process = {
|
37
|
+
conveyor: {type: 'Server', port: configatron.conveyor_port},
|
38
|
+
worker: {type: 'Puller', port: configatron.worker_port}
|
39
|
+
}[process_name]
|
40
|
+
Stub.new process[:type], on_port: process[:port]
|
41
|
+
end
|
42
|
+
end
|
data/test/shared/stub.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'ezmq'
|
2
|
+
using ExtendedEZMQ
|
3
|
+
|
4
|
+
class Stub
|
5
|
+
def initialize(type, on_port:)
|
6
|
+
@type = type
|
7
|
+
@port = on_port
|
8
|
+
clear_output
|
9
|
+
@thread = Thread.new { start_listener type, on_port } unless running?
|
10
|
+
end
|
11
|
+
|
12
|
+
def running?
|
13
|
+
not `lsof -i :#{@port}`.empty? # TODO: I'm so sorry
|
14
|
+
end
|
15
|
+
|
16
|
+
def output_file
|
17
|
+
".test.#{@type}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def clear_output
|
21
|
+
FileUtils.rm output_file if File.exist? output_file
|
22
|
+
end
|
23
|
+
|
24
|
+
def output_empty?
|
25
|
+
(not File.exist? output_file) || File.read(output_file).empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
def start_listener(type, port)
|
29
|
+
listener = case type
|
30
|
+
when 'Puller'
|
31
|
+
EZMQ::Puller.new :connect, port: port
|
32
|
+
else
|
33
|
+
EZMQ.const_get(type).new port: port
|
34
|
+
end
|
35
|
+
listener.serialize_with_json!
|
36
|
+
listener.listen { |message| write message }
|
37
|
+
end
|
38
|
+
|
39
|
+
def write(message)
|
40
|
+
file = File.new output_file, 'w'
|
41
|
+
file.write message
|
42
|
+
file.close
|
43
|
+
end
|
44
|
+
end
|
data/test/worker_spec.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'kintama'
|
3
|
+
require 'ezmq'
|
4
|
+
require 'timeout'
|
5
|
+
require 'robot_sweatshop/config'
|
6
|
+
require 'robot_sweatshop/connections'
|
7
|
+
require_relative 'shared/scaffolding'
|
8
|
+
require_relative 'shared/helpers'
|
9
|
+
$stdout.sync = true
|
10
|
+
|
11
|
+
Kintama.on_start do
|
12
|
+
Setup.empty_conveyor
|
13
|
+
@pids = TestProcess.start %w(worker)
|
14
|
+
end
|
15
|
+
|
16
|
+
Kintama.on_finish do
|
17
|
+
TestProcess.stop @pids
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'the Worker' do
|
21
|
+
include InputHelper
|
22
|
+
include OutputHelper
|
23
|
+
using ExtendedEZMQ
|
24
|
+
|
25
|
+
setup do
|
26
|
+
@conveyor = TestProcess.stub :conveyor
|
27
|
+
@pusher = EZMQ::Pusher.new :bind, port: configatron.worker_port
|
28
|
+
@pusher.serialize_with_json!
|
29
|
+
clear_worker_output
|
30
|
+
end
|
31
|
+
|
32
|
+
teardown do
|
33
|
+
@pusher.close
|
34
|
+
end
|
35
|
+
|
36
|
+
given 'valid job data is pushed' do
|
37
|
+
setup do
|
38
|
+
@pusher.send worker_push
|
39
|
+
Timeout.timeout($a_while) do
|
40
|
+
loop until File.exist? worker_output
|
41
|
+
loop while @conveyor.output_empty?
|
42
|
+
end
|
43
|
+
@worker_data = eval File.read(@conveyor.output_file)
|
44
|
+
end
|
45
|
+
|
46
|
+
should 'run the commands' do
|
47
|
+
assert_equal true, File.file?(worker_output)
|
48
|
+
end
|
49
|
+
|
50
|
+
should 'run with the context as environment variables' do
|
51
|
+
assert_equal "hello world\n", File.read(worker_output)
|
52
|
+
end
|
53
|
+
|
54
|
+
should 'tell the conveyor that job is complete' do
|
55
|
+
assert_equal 'finish', @worker_data[:method]
|
56
|
+
assert_kind_of Fixnum, @worker_data[:data]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: robot_sweatshop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Scott
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: faker
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: commander
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: eye
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: colorize
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: configatron
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -95,7 +95,7 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: moneta
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: contracts
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
@@ -123,7 +123,7 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: sinatra
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
@@ -137,13 +137,13 @@ dependencies:
|
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: ezmq
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
143
|
- - ">="
|
144
144
|
- !ruby/object:Gem::Version
|
145
145
|
version: '0'
|
146
|
-
type: :
|
146
|
+
type: :runtime
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
@@ -151,13 +151,13 @@ dependencies:
|
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
154
|
+
name: stubborn_queue
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
157
|
- - ">="
|
158
158
|
- !ruby/object:Gem::Version
|
159
159
|
version: '0'
|
160
|
-
type: :
|
160
|
+
type: :runtime
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
@@ -165,7 +165,35 @@ dependencies:
|
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
|
-
name:
|
168
|
+
name: oj
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: exponential-backoff
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :runtime
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: rake
|
169
197
|
requirement: !ruby/object:Gem::Requirement
|
170
198
|
requirements:
|
171
199
|
- - ">="
|
@@ -179,7 +207,7 @@ dependencies:
|
|
179
207
|
- !ruby/object:Gem::Version
|
180
208
|
version: '0'
|
181
209
|
- !ruby/object:Gem::Dependency
|
182
|
-
name:
|
210
|
+
name: kintama
|
183
211
|
requirement: !ruby/object:Gem::Requirement
|
184
212
|
requirements:
|
185
213
|
- - ">="
|
@@ -193,7 +221,7 @@ dependencies:
|
|
193
221
|
- !ruby/object:Gem::Version
|
194
222
|
version: '0'
|
195
223
|
- !ruby/object:Gem::Dependency
|
196
|
-
name:
|
224
|
+
name: http
|
197
225
|
requirement: !ruby/object:Gem::Requirement
|
198
226
|
requirements:
|
199
227
|
- - ">="
|
@@ -223,14 +251,14 @@ dependencies:
|
|
223
251
|
description: A lightweight, unopinionated CI server.
|
224
252
|
email: jvscott@gmail.com
|
225
253
|
executables:
|
254
|
+
- README.md
|
226
255
|
- sweatshop
|
227
|
-
- sweatshop-
|
228
|
-
- sweatshop-
|
229
|
-
- sweatshop-
|
256
|
+
- sweatshop-assembler
|
257
|
+
- sweatshop-conveyor
|
258
|
+
- sweatshop-input
|
259
|
+
- sweatshop-job-dictionary
|
230
260
|
- sweatshop-payload-parser
|
231
|
-
- sweatshop-
|
232
|
-
- sweatshop-queue-handler
|
233
|
-
- sweatshop-queue-watcher
|
261
|
+
- sweatshop-worker
|
234
262
|
extensions: []
|
235
263
|
extra_rdoc_files: []
|
236
264
|
files:
|
@@ -240,14 +268,14 @@ files:
|
|
240
268
|
- LICENSE
|
241
269
|
- README.md
|
242
270
|
- Rakefile
|
271
|
+
- bin/README.md
|
243
272
|
- bin/sweatshop
|
244
|
-
- bin/sweatshop-
|
245
|
-
- bin/sweatshop-
|
246
|
-
- bin/sweatshop-
|
273
|
+
- bin/sweatshop-assembler
|
274
|
+
- bin/sweatshop-conveyor
|
275
|
+
- bin/sweatshop-input
|
276
|
+
- bin/sweatshop-job-dictionary
|
247
277
|
- bin/sweatshop-payload-parser
|
248
|
-
- bin/sweatshop-
|
249
|
-
- bin/sweatshop-queue-handler
|
250
|
-
- bin/sweatshop-queue-watcher
|
278
|
+
- bin/sweatshop-worker
|
251
279
|
- config.defaults.yaml
|
252
280
|
- lib/README.md
|
253
281
|
- lib/robot_sweatshop.rb
|
@@ -257,35 +285,35 @@ files:
|
|
257
285
|
- lib/robot_sweatshop/cli/job.rb
|
258
286
|
- lib/robot_sweatshop/cli/start.rb
|
259
287
|
- lib/robot_sweatshop/config.rb
|
288
|
+
- lib/robot_sweatshop/connections.rb
|
260
289
|
- lib/robot_sweatshop/create-config-directories.rb
|
261
|
-
- lib/robot_sweatshop/moneta-queue.rb
|
262
290
|
- lib/robot_sweatshop/payload.rb
|
263
291
|
- lib/robot_sweatshop/payload/bitbucket.rb
|
264
292
|
- lib/robot_sweatshop/payload/github.rb
|
265
293
|
- lib/robot_sweatshop/payload/json.rb
|
266
294
|
- lib/robot_sweatshop/payload/payload.rb
|
267
|
-
- lib/robot_sweatshop/queue-helper.rb
|
268
295
|
- robot_sweatshop.eye
|
269
296
|
- robot_sweatshop.gemspec
|
270
|
-
- robot_sweatshop.production.eye
|
271
|
-
- robot_sweatshop.testing.eye
|
272
297
|
- test/README.md
|
298
|
+
- test/all.rb
|
299
|
+
- test/assembler_spec.rb
|
300
|
+
- test/conveyor_spec.rb
|
273
301
|
- test/data/empty_job.yaml
|
274
302
|
- test/data/git_job.yaml
|
275
303
|
- test/data/minimal_job.yaml
|
276
304
|
- test/data/payload_data.yaml
|
277
305
|
- test/data/test_job.yaml
|
306
|
+
- test/data/weird_job.yaml
|
278
307
|
- test/end-to-end_spec.rb
|
279
|
-
- test/
|
280
|
-
- test/
|
281
|
-
- test/job_worker_spec.rb
|
282
|
-
- test/moneta-queue_spec.rb
|
308
|
+
- test/input_spec.rb
|
309
|
+
- test/job_dictionary_spec.rb
|
283
310
|
- test/payload_parser_spec.rb
|
284
|
-
- test/queue_broadcaster_spec.rb
|
285
|
-
- test/queue_handler_spec.rb
|
286
|
-
- test/run_all.rb
|
287
311
|
- test/shared/helpers.rb
|
288
|
-
- test/shared/
|
312
|
+
- test/shared/helpers/input.rb
|
313
|
+
- test/shared/helpers/output.rb
|
314
|
+
- test/shared/scaffolding.rb
|
315
|
+
- test/shared/stub.rb
|
316
|
+
- test/worker_spec.rb
|
289
317
|
homepage: http://www.github.com/jscott/robot_sweatshop/
|
290
318
|
licenses:
|
291
319
|
- MIT
|
@@ -306,7 +334,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
306
334
|
version: '0'
|
307
335
|
requirements: []
|
308
336
|
rubyforge_project:
|
309
|
-
rubygems_version: 2.
|
337
|
+
rubygems_version: 2.4.5
|
310
338
|
signing_key:
|
311
339
|
specification_version: 4
|
312
340
|
summary: Robot Sweatshop
|
@@ -316,6 +344,10 @@ test_files:
|
|
316
344
|
- test/data/minimal_job.yaml
|
317
345
|
- test/data/payload_data.yaml
|
318
346
|
- test/data/test_job.yaml
|
347
|
+
- test/data/weird_job.yaml
|
319
348
|
- test/shared/helpers.rb
|
320
|
-
- test/shared/
|
349
|
+
- test/shared/helpers/input.rb
|
350
|
+
- test/shared/helpers/output.rb
|
351
|
+
- test/shared/scaffolding.rb
|
352
|
+
- test/shared/stub.rb
|
321
353
|
has_rdoc:
|
data/bin/sweatshop-job-assembler
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'yaml'
|
4
|
-
require 'json'
|
5
|
-
require 'contracts'
|
6
|
-
require 'robot_sweatshop/queue-helper'
|
7
|
-
require 'robot_sweatshop/config'
|
8
|
-
|
9
|
-
$stdout.sync = true
|
10
|
-
include Contracts
|
11
|
-
|
12
|
-
Contract None => Hash
|
13
|
-
def empty_config
|
14
|
-
puts "Job configuration not found or empty"
|
15
|
-
{}
|
16
|
-
end
|
17
|
-
|
18
|
-
Contract None => String
|
19
|
-
def job_path
|
20
|
-
File.expand_path configatron.job_path
|
21
|
-
end
|
22
|
-
|
23
|
-
Contract Or[String, nil], Hash => Bool
|
24
|
-
def whitelisted?(branch, in_config:)
|
25
|
-
return true if in_config['branch_whitelist'].nil?
|
26
|
-
in_config['branch_whitelist'].include? branch
|
27
|
-
end
|
28
|
-
|
29
|
-
Contract Hash => Hash
|
30
|
-
def sanitize(data)
|
31
|
-
data.each_pair { |key, value| data[key] = value.to_s }
|
32
|
-
end
|
33
|
-
|
34
|
-
Contract Hash, Hash => Hash
|
35
|
-
def job_context(job_environment, context_from_payload)
|
36
|
-
sanitize job_environment.merge(context_from_payload)
|
37
|
-
end
|
38
|
-
|
39
|
-
Contract String => Or[Hash, nil]
|
40
|
-
def load_if_exists(config)
|
41
|
-
puts "Reading job configuration from #{config}"
|
42
|
-
YAML.load_file config if File.exists? config
|
43
|
-
end
|
44
|
-
|
45
|
-
Contract String => Hash
|
46
|
-
def load_config_for(job_name)
|
47
|
-
load_if_exists("#{job_path}/#{job_name}.yaml") || empty_config
|
48
|
-
end
|
49
|
-
|
50
|
-
Contract Hash => [Hash, String]
|
51
|
-
def parse_payload(request)
|
52
|
-
client = EZMQ::Client.new port: configatron.payload_parser_port
|
53
|
-
response = JSON.load client.request(JSON.dump request)
|
54
|
-
puts response['error'] unless response['error'].empty?
|
55
|
-
[response['payload'], response['error']]
|
56
|
-
end
|
57
|
-
|
58
|
-
Contract Hash, Hash => Bool
|
59
|
-
def can_work_with?(job_config, payload)
|
60
|
-
return false if job_config.empty?
|
61
|
-
return false unless whitelisted? payload['branch'], in_config: job_config
|
62
|
-
true
|
63
|
-
end
|
64
|
-
|
65
|
-
Contract Hash => Or[Hash, false]
|
66
|
-
def assemble_job(request)
|
67
|
-
job_config = load_config_for request['job_name']
|
68
|
-
payload, error = parse_payload request
|
69
|
-
return false unless error.empty? && can_work_with?(job_config, payload)
|
70
|
-
{
|
71
|
-
commands: job_config['commands'],
|
72
|
-
context: job_context(job_config['environment'] || {}, payload),
|
73
|
-
job_name: request['job_name']
|
74
|
-
}
|
75
|
-
end
|
76
|
-
|
77
|
-
puts 'Started'
|
78
|
-
QueueHelper.wait_for('payload') do |request|
|
79
|
-
puts "Assembling: #{request}"
|
80
|
-
assembled_job = assemble_job request
|
81
|
-
QueueHelper.enqueue assembled_job, to: 'jobs' if assembled_job
|
82
|
-
end
|
data/bin/sweatshop-job-worker
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'faker'
|
4
|
-
require 'fileutils'
|
5
|
-
require 'robot_sweatshop/queue-helper'
|
6
|
-
require 'robot_sweatshop/config'
|
7
|
-
|
8
|
-
$stdout.sync = true
|
9
|
-
$stderr.sync = true
|
10
|
-
|
11
|
-
# TODO: check existing worker ids. it'd be disastrous to have two sharing a workspace
|
12
|
-
@worker_id = ARGV[0] || "#{Faker::Name.first_name}"
|
13
|
-
|
14
|
-
def from_workspace(named: 'no_job_name')
|
15
|
-
workspace = "#{named}-#{@worker_id}"
|
16
|
-
puts "Workspace: #{workspace}"
|
17
|
-
path = File.expand_path "#{configatron.workspace_path}/#{workspace}"
|
18
|
-
FileUtils.mkpath path
|
19
|
-
Dir.chdir(path) { yield if block_given? }
|
20
|
-
end
|
21
|
-
|
22
|
-
def execute(context = {}, command)
|
23
|
-
puts "Executing '#{command}'..."
|
24
|
-
# TODO: path.split(' ') to bypass the shell when we're not using env vars
|
25
|
-
|
26
|
-
# Run the command with the context in environment,
|
27
|
-
# printing the output as it's generated
|
28
|
-
IO.popen(context, command) do |io_stream|
|
29
|
-
while line = io_stream.gets
|
30
|
-
puts line
|
31
|
-
end
|
32
|
-
end
|
33
|
-
puts "Execution complete with exit status: #{$?.exitstatus}"
|
34
|
-
end
|
35
|
-
|
36
|
-
QueueHelper.wait_for('jobs') do |data|
|
37
|
-
puts "Running: #{data}"
|
38
|
-
if data['commands'].is_a? Array
|
39
|
-
from_workspace(named: data['job_name']) do
|
40
|
-
context = data['context'] || {}
|
41
|
-
data['commands'].each { |command| execute context, command }
|
42
|
-
end
|
43
|
-
end
|
44
|
-
puts "Job finished.\n\n"
|
45
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'ezmq'
|
4
|
-
require 'robot_sweatshop/moneta-queue'
|
5
|
-
|
6
|
-
publisher = EZMQ::Publisher.new port: 5557
|
7
|
-
queues = {}
|
8
|
-
MonetaQueue.watched_queues.each do |queue|
|
9
|
-
queues[queue] = MonetaQueue.new queue
|
10
|
-
end
|
11
|
-
|
12
|
-
@wait_time = ARGV[0].nil? ? 0.5 : ARGV[0].to_f
|
13
|
-
|
14
|
-
loop do
|
15
|
-
queues.each do |queue_name, queue|
|
16
|
-
p queue_name if queue.size > 0
|
17
|
-
publisher.send queue_name, topic: 'busy-queues' if queue.size > 0
|
18
|
-
end
|
19
|
-
sleep @wait_time unless @wait_time == 0
|
20
|
-
end
|
data/bin/sweatshop-queue-handler
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'ezmq'
|
4
|
-
require 'robot_sweatshop/moneta-queue'
|
5
|
-
|
6
|
-
def enqueue(name, item)
|
7
|
-
puts "enqueue #{name} #{item}"
|
8
|
-
queue = MonetaQueue.new name
|
9
|
-
queue.enqueue item
|
10
|
-
queue.size.to_s
|
11
|
-
end
|
12
|
-
|
13
|
-
def dequeue(name)
|
14
|
-
puts "dequeue #{name}"
|
15
|
-
queue = MonetaQueue.new name
|
16
|
-
queue.dequeue
|
17
|
-
end
|
18
|
-
|
19
|
-
server = EZMQ::Server.new port: 5556
|
20
|
-
server.listen do |message|
|
21
|
-
name, item = message.split ' ', 2
|
22
|
-
is_dequeue_request = item.nil?
|
23
|
-
is_dequeue_request ? dequeue(name) : enqueue(name, item)
|
24
|
-
end
|