robot_sweatshop 0.3.3 → 0.4.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/.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
|