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/robot_sweatshop.eye
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
|
+
# TODO: per-user temp file
|
3
4
|
CONFIG = YAML.load_file '/tmp/.robot_sweatshop-eye-config.yaml'
|
4
5
|
PID_PATH = CONFIG[:pidfile_path]
|
5
6
|
LOG_PATH = CONFIG[:logfile_path]
|
@@ -13,46 +14,43 @@ Eye.application :robot_sweatshop do
|
|
13
14
|
check :cpu, every: 10.seconds, below: 100, times: 3
|
14
15
|
working_dir CONFIG[:working_path]
|
15
16
|
|
16
|
-
group '
|
17
|
-
process :
|
18
|
-
pid_file "#{PID_PATH}/
|
19
|
-
stdall "#{LOG_PATH}/
|
20
|
-
start_command "#{__dir__}/bin/sweatshop-
|
17
|
+
group 'services' do
|
18
|
+
process :job_dictionary do
|
19
|
+
pid_file "#{PID_PATH}/job-dictionary.pid"
|
20
|
+
stdall "#{LOG_PATH}/job-dictionary.log"
|
21
|
+
start_command "#{__dir__}/bin/sweatshop-job-dictionary"
|
21
22
|
daemonize true
|
22
23
|
end
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
stdall "#{LOG_PATH}/queue-handler.log"
|
28
|
-
start_command "#{__dir__}/bin/sweatshop-queue-handler"
|
24
|
+
process :payload_parser do
|
25
|
+
pid_file "#{PID_PATH}/payload-parser.pid"
|
26
|
+
stdall "#{LOG_PATH}/payload-parser.log"
|
27
|
+
start_command "#{__dir__}/bin/sweatshop-payload-parser"
|
29
28
|
daemonize true
|
30
29
|
end
|
31
|
-
process :
|
32
|
-
pid_file "#{PID_PATH}/
|
33
|
-
stdall "#{LOG_PATH}/
|
34
|
-
start_command "#{__dir__}/bin/sweatshop-
|
30
|
+
process :conveyor do
|
31
|
+
pid_file "#{PID_PATH}/conveyor.pid"
|
32
|
+
stdall "#{LOG_PATH}/conveyor.log"
|
33
|
+
start_command "#{__dir__}/bin/sweatshop-conveyor"
|
35
34
|
daemonize true
|
36
35
|
end
|
37
36
|
end
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
37
|
+
|
38
|
+
process :input do
|
39
|
+
pid_file "#{PID_PATH}/input.pid"
|
40
|
+
stdall "#{LOG_PATH}/input.log"
|
41
|
+
start_command "#{__dir__}/bin/sweatshop-input"
|
42
|
+
daemonize true
|
43
|
+
end
|
44
|
+
process :assembler do
|
45
|
+
pid_file "#{PID_PATH}/assembler.pid"
|
46
|
+
stdall "#{LOG_PATH}/assembler.log"
|
47
|
+
start_command "#{__dir__}/bin/sweatshop-assembler"
|
48
|
+
daemonize true
|
51
49
|
end
|
52
|
-
process :
|
53
|
-
pid_file "#{PID_PATH}/
|
54
|
-
stdall "#{LOG_PATH}/
|
55
|
-
start_command "#{__dir__}/bin/sweatshop-
|
50
|
+
process :worker do
|
51
|
+
pid_file "#{PID_PATH}/worker.pid"
|
52
|
+
stdall "#{LOG_PATH}/worker.log"
|
53
|
+
start_command "#{__dir__}/bin/sweatshop-worker"
|
56
54
|
daemonize true
|
57
55
|
end
|
58
56
|
end
|
data/robot_sweatshop.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |gem|
|
2
2
|
gem.name = 'robot_sweatshop'
|
3
|
-
gem.version = '0.
|
3
|
+
gem.version = '0.4.0'
|
4
4
|
gem.licenses = 'MIT'
|
5
5
|
gem.authors = ['Justin Scott']
|
6
6
|
gem.email = 'jvscott@gmail.com'
|
@@ -15,20 +15,22 @@ Gem::Specification.new do |gem|
|
|
15
15
|
|
16
16
|
gem.required_ruby_version = '>= 2.1'
|
17
17
|
|
18
|
-
gem.add_runtime_dependency '
|
19
|
-
gem.add_runtime_dependency 'ezmq'
|
18
|
+
gem.add_runtime_dependency 'bundler'
|
20
19
|
gem.add_runtime_dependency 'faker'
|
21
20
|
gem.add_runtime_dependency 'commander'
|
22
21
|
gem.add_runtime_dependency 'eye'
|
23
22
|
gem.add_runtime_dependency 'colorize' # TODO: replace with rainbow
|
24
23
|
gem.add_runtime_dependency 'configatron'
|
25
|
-
gem.add_runtime_dependency 'moneta'
|
24
|
+
gem.add_runtime_dependency 'moneta' # TODO: needed with stubborn_queue?
|
26
25
|
gem.add_runtime_dependency 'contracts'
|
26
|
+
gem.add_runtime_dependency 'sinatra'
|
27
|
+
gem.add_runtime_dependency 'ezmq'
|
28
|
+
gem.add_runtime_dependency 'stubborn_queue'
|
29
|
+
gem.add_runtime_dependency 'oj'
|
30
|
+
gem.add_runtime_dependency 'exponential-backoff'
|
27
31
|
|
28
32
|
gem.add_development_dependency 'rake'
|
29
33
|
gem.add_development_dependency 'kintama'
|
30
34
|
gem.add_development_dependency 'http'
|
31
|
-
gem.add_development_dependency 'pry'
|
32
|
-
gem.add_development_dependency 'pry-byebug'
|
33
35
|
gem.add_development_dependency 'simplecov'
|
34
36
|
end
|
data/test/README.md
CHANGED
@@ -1 +1,3 @@
|
|
1
|
-
You can run individual `_spec.rb` files with Ruby or `
|
1
|
+
You can run individual `_spec.rb` files with Ruby or `all.rb` to go through each. There's no way to run everything together with the way processes are set up but this hasn't been a problem so far.
|
2
|
+
|
3
|
+
Because I'm lazy, TestProcess::Stub uses the UNIX `lsof` to check if ports are in use. There's probably a better, more portable way to do this.
|
data/test/all.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Because of needing to isolate processes, I can't run all tests in one call.
|
2
|
+
# This means that I have multiple sets of results which isn't nice, but the
|
3
|
+
# tests are largely for the sake of TDD anyway.
|
4
|
+
|
5
|
+
def run_test(component)
|
6
|
+
test_path = File.expand_path __dir__
|
7
|
+
IO.popen("ruby #{test_path}/#{component}_spec.rb") do |data|
|
8
|
+
while line = data.gets
|
9
|
+
puts line
|
10
|
+
end
|
11
|
+
end
|
12
|
+
$?.exitstatus
|
13
|
+
end
|
14
|
+
|
15
|
+
def non_zero(array)
|
16
|
+
array.select { |number| number != 0 }
|
17
|
+
end
|
18
|
+
|
19
|
+
tests = %w(
|
20
|
+
input
|
21
|
+
conveyor
|
22
|
+
payload_parser
|
23
|
+
job_dictionary
|
24
|
+
assembler
|
25
|
+
worker
|
26
|
+
end-to-end
|
27
|
+
)
|
28
|
+
exit_statuses = []
|
29
|
+
|
30
|
+
tests.each do |name|
|
31
|
+
exit_statuses.push run_test(name)
|
32
|
+
end
|
33
|
+
exit 1 unless non_zero(exit_statuses).empty?
|
34
|
+
|
35
|
+
puts "Everything passed successfully" # TODO: announce gem
|
@@ -0,0 +1,89 @@
|
|
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(assembler conveyor payload-parser job-dictionary)
|
14
|
+
Setup.populate_test_jobs
|
15
|
+
end
|
16
|
+
|
17
|
+
Kintama.on_finish do
|
18
|
+
TestProcess.stop @pids
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'the Job Assembler' do
|
22
|
+
include InputHelper
|
23
|
+
include OutputHelper
|
24
|
+
using ExtendedEZMQ
|
25
|
+
|
26
|
+
setup do
|
27
|
+
@worker = TestProcess.stub :worker
|
28
|
+
# @conveyor = TestProcess::Stub.new 'Server', on_port: configatron.conveyor_port
|
29
|
+
@client = EZMQ::Client.new port: configatron.conveyor_port
|
30
|
+
@client.serialize_with_json!
|
31
|
+
end
|
32
|
+
|
33
|
+
teardown do
|
34
|
+
@client.close
|
35
|
+
end
|
36
|
+
|
37
|
+
%w(Git JSON MinimalJob).each do |request|
|
38
|
+
given "#{request} requests on the Conveyor" do
|
39
|
+
setup do
|
40
|
+
@client.request conveyor_enqueue(request)
|
41
|
+
Timeout.timeout($a_while) { loop while @worker.output_empty? }
|
42
|
+
@worker_data = eval File.read(@worker.output_file) # TODO: oh god why
|
43
|
+
end
|
44
|
+
|
45
|
+
should 'push the parsed payload to a Worker' do
|
46
|
+
assert_kind_of Hash, @worker_data[:context]
|
47
|
+
assert_kind_of Array, @worker_data[:commands]
|
48
|
+
assert_kind_of String, @worker_data[:job_name]
|
49
|
+
end
|
50
|
+
|
51
|
+
should 'store everything in the context as strings' do
|
52
|
+
@worker_data[:context].each do |key, value|
|
53
|
+
assert_kind_of String, key
|
54
|
+
assert_kind_of String, value
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
should 'build the context with a parsed payload' do
|
59
|
+
if request == 'Git'
|
60
|
+
assert_equal 'develop', @worker_data[:context]['branch']
|
61
|
+
else
|
62
|
+
assert_equal 'value', @worker_data[:context]['test1']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
should 'grab commands from the job config' do
|
67
|
+
assert_match /echo/, @worker_data[:commands].first
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
%w(IgnoredBranch UnknownJob EmptyJob NonJSON).each do |request|
|
73
|
+
given "#{request} requests on the Conveyor" do
|
74
|
+
setup do
|
75
|
+
@client.request conveyor_enqueue(request)
|
76
|
+
sleep $a_moment
|
77
|
+
end
|
78
|
+
|
79
|
+
should 'push nothing to Workers' do
|
80
|
+
assert @worker.output_empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
should 'tell the Conveyor that the job is finished'
|
84
|
+
# testing needs a real conveyor to grab the jobs from
|
85
|
+
# so it would require much refactoring and complexity to stub a fake one
|
86
|
+
# in order to test that finish is actually called
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,67 @@
|
|
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
|
+
$stdout.sync = true
|
9
|
+
|
10
|
+
Kintama.on_start do
|
11
|
+
Setup.empty_conveyor
|
12
|
+
@pids = TestProcess.start %w(conveyor)
|
13
|
+
end
|
14
|
+
|
15
|
+
Kintama.on_finish do
|
16
|
+
TestProcess.stop @pids
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'the Conveyor' do
|
20
|
+
using ExtendedEZMQ
|
21
|
+
|
22
|
+
setup do
|
23
|
+
@client = EZMQ::Client.new port: configatron.conveyor_port
|
24
|
+
@client.serialize_with_json!
|
25
|
+
@item = {test: 'item'}
|
26
|
+
end
|
27
|
+
|
28
|
+
teardown do
|
29
|
+
@client.close
|
30
|
+
end
|
31
|
+
|
32
|
+
should 'enqueue and dequeue items' do
|
33
|
+
id = Timeout.timeout($a_moment) do
|
34
|
+
@client.request method: 'enqueue', data: @item
|
35
|
+
@client.request method: 'dequeue'
|
36
|
+
end
|
37
|
+
assert_kind_of Fixnum, id
|
38
|
+
end
|
39
|
+
|
40
|
+
should 'lookup items by ID' do
|
41
|
+
item = Timeout.timeout($a_moment) do
|
42
|
+
@client.request method: 'enqueue', data: @item
|
43
|
+
id = @client.request method: 'dequeue'
|
44
|
+
@client.request method: 'lookup', data: id
|
45
|
+
end
|
46
|
+
assert_equal @item, item
|
47
|
+
end
|
48
|
+
|
49
|
+
should 'return nothing when given invalid data' do
|
50
|
+
response = Timeout.timeout($a_moment) do
|
51
|
+
@client.request 'not json'
|
52
|
+
@client.request method: 'invalid'
|
53
|
+
@client.request ''
|
54
|
+
@client.request 'assurance that the server is still up'
|
55
|
+
end
|
56
|
+
assert_nil response
|
57
|
+
end
|
58
|
+
|
59
|
+
should 'finish items by ID to prevent requeueing' do
|
60
|
+
response = Timeout.timeout($a_moment) do
|
61
|
+
@client.request method: 'enqueue', data: @item
|
62
|
+
id = @client.request method: 'dequeue'
|
63
|
+
@client.request method: 'finish', data: id
|
64
|
+
end
|
65
|
+
assert_not_equal '', response
|
66
|
+
end
|
67
|
+
end
|
data/test/end-to-end_spec.rb
CHANGED
@@ -1,29 +1,35 @@
|
|
1
|
+
require 'bundler/setup'
|
1
2
|
require 'kintama'
|
2
3
|
require 'ezmq'
|
3
4
|
require 'http'
|
4
|
-
require_relative 'shared/
|
5
|
+
require_relative 'shared/scaffolding'
|
5
6
|
require_relative 'shared/helpers'
|
6
7
|
|
7
8
|
describe 'Robot Sweatshop' do
|
8
|
-
include
|
9
|
-
include
|
10
|
-
include JobHelper
|
9
|
+
include InputHelper
|
10
|
+
include OutputHelper
|
11
11
|
|
12
12
|
setup do
|
13
|
-
|
14
|
-
@
|
15
|
-
|
13
|
+
Setup.empty_conveyor
|
14
|
+
@pids = TestProcess.start %w(input conveyor payload-parser job-dictionary assembler worker)
|
15
|
+
Setup.populate_test_jobs
|
16
|
+
sleep $a_while
|
16
17
|
end
|
17
18
|
|
18
|
-
|
19
|
+
teardown do
|
20
|
+
TestProcess.stop @pids
|
21
|
+
end
|
22
|
+
|
23
|
+
context "POSTing data to the HTTP Input" do
|
19
24
|
setup do
|
20
|
-
|
21
|
-
|
22
|
-
|
25
|
+
clear_worker_output
|
26
|
+
url = input_url for_job: 'test_job'
|
27
|
+
Timeout.timeout($a_while) { @response = HTTP.post url, body: example_raw_payload('JSON') }
|
23
28
|
end
|
24
29
|
|
25
|
-
should 'run
|
26
|
-
|
30
|
+
should 'run the appropriate job' do
|
31
|
+
Timeout.timeout($a_while) { loop until File.exist? worker_output }
|
32
|
+
assert_equal true, File.file?(worker_output)
|
27
33
|
end
|
28
34
|
end
|
29
35
|
end
|
data/test/input_spec.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'kintama'
|
3
|
+
require 'ezmq'
|
4
|
+
require 'oj'
|
5
|
+
require 'timeout'
|
6
|
+
require 'http'
|
7
|
+
require 'robot_sweatshop/config'
|
8
|
+
require_relative 'shared/scaffolding'
|
9
|
+
require_relative 'shared/helpers'
|
10
|
+
$stdout.sync = true
|
11
|
+
|
12
|
+
Kintama.on_start do
|
13
|
+
@pids = TestProcess.start %w(input)
|
14
|
+
sleep $a_while
|
15
|
+
end
|
16
|
+
|
17
|
+
Kintama.on_finish do
|
18
|
+
TestProcess.stop @pids
|
19
|
+
end
|
20
|
+
|
21
|
+
given 'the HTTP Input' do
|
22
|
+
include InputHelper
|
23
|
+
include OutputHelper
|
24
|
+
|
25
|
+
%w(Bitbucket Github JSON Empty).each do |format|
|
26
|
+
context "POSTing #{format} data" do
|
27
|
+
setup do
|
28
|
+
@conveyor = TestProcess.stub :conveyor
|
29
|
+
url = input_url for_job: 'test_job'
|
30
|
+
Timeout.timeout($a_while) do
|
31
|
+
@response = HTTP.post url, body: example_raw_payload(format)
|
32
|
+
end
|
33
|
+
assert_equal 200, @response.code
|
34
|
+
end
|
35
|
+
|
36
|
+
should 'send to the conveyor' do
|
37
|
+
assert_equal true, File.exist?(@conveyor.output_file)
|
38
|
+
end
|
39
|
+
|
40
|
+
should 'enqueue payload details, user agent, and job name' do
|
41
|
+
request = eval File.read(@conveyor.output_file) # please don't hack me thx
|
42
|
+
assert_equal 'enqueue', request[:method]
|
43
|
+
assert_not_nil request[:data][:payload]
|
44
|
+
assert_not_nil request[:data][:user_agent]
|
45
|
+
assert_not_nil request[:data][:job_name]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,70 @@
|
|
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' # do I need this?
|
9
|
+
$stdout.sync = true
|
10
|
+
|
11
|
+
Kintama.on_start do
|
12
|
+
@pids = TestProcess.start %w(job-dictionary)
|
13
|
+
Setup.populate_test_jobs
|
14
|
+
end
|
15
|
+
|
16
|
+
Kintama.on_finish do
|
17
|
+
TestProcess.stop @pids
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'the Job Dictionary' do
|
21
|
+
include InputHelper
|
22
|
+
using ExtendedEZMQ
|
23
|
+
|
24
|
+
setup do
|
25
|
+
@client = EZMQ::Client.new port: configatron.job_dictionary_port
|
26
|
+
@client.serialize_with_json!
|
27
|
+
end
|
28
|
+
|
29
|
+
teardown do
|
30
|
+
@client.close
|
31
|
+
end
|
32
|
+
|
33
|
+
%w(git_job minimal_job test_job).each do |job_name|
|
34
|
+
given "a #{job_name.gsub '_', ' '}" do
|
35
|
+
setup do
|
36
|
+
@response = Timeout.timeout($a_while) do
|
37
|
+
@client.request job_name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
should 'return no error' do
|
42
|
+
assert_equal true, @response[:error].empty?
|
43
|
+
end
|
44
|
+
|
45
|
+
should 'return a defined job object' do
|
46
|
+
assert_kind_of Hash, @response[:data]
|
47
|
+
no_environment = job_name =~ /empty|minimal/
|
48
|
+
has_whitelist = job_name =~ /git/
|
49
|
+
assert_not_nil @response[:data]['branch_whitelist'] if has_whitelist
|
50
|
+
assert_not_nil @response[:data]['commands']
|
51
|
+
assert_not_nil @response[:data]['environment'] unless no_environment
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
%w(empty_job undefined_job weird_job).each do |job_name|
|
57
|
+
given "a #{job_name.gsub '_', ' '}" do
|
58
|
+
setup do
|
59
|
+
@response = Timeout.timeout($a_while) do
|
60
|
+
@client.request job_name
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
should 'return an error object' do
|
65
|
+
assert_kind_of String, @response[:error]
|
66
|
+
assert_equal true, @response[:data].empty?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/test/payload_parser_spec.rb
CHANGED
@@ -1,42 +1,54 @@
|
|
1
|
+
require 'bundler/setup'
|
1
2
|
require 'kintama'
|
2
3
|
require 'ezmq'
|
3
|
-
require 'json'
|
4
4
|
require 'timeout'
|
5
|
-
|
5
|
+
require 'robot_sweatshop/config'
|
6
|
+
require 'robot_sweatshop/connections'
|
7
|
+
require_relative 'shared/scaffolding'
|
6
8
|
require_relative 'shared/helpers'
|
9
|
+
$stdout.sync = true
|
10
|
+
|
11
|
+
Kintama.on_start do
|
12
|
+
@pids = TestProcess.start %w(payload-parser)
|
13
|
+
end
|
14
|
+
|
15
|
+
Kintama.on_finish do
|
16
|
+
TestProcess.stop @pids
|
17
|
+
end
|
7
18
|
|
8
19
|
describe 'the Payload Parser' do
|
9
|
-
include
|
10
|
-
|
20
|
+
include InputHelper
|
21
|
+
using ExtendedEZMQ
|
11
22
|
|
12
23
|
setup do
|
13
24
|
@client = EZMQ::Client.new port: configatron.payload_parser_port
|
25
|
+
@client.serialize_with_json!
|
26
|
+
end
|
27
|
+
|
28
|
+
teardown do
|
29
|
+
@client.close
|
14
30
|
end
|
15
31
|
|
16
32
|
%w(Bitbucket Github JSON Empty).each do |format|
|
17
33
|
given "valid #{format} payloads" do
|
18
34
|
setup do
|
19
|
-
payload =
|
20
|
-
@response = Timeout.timeout($
|
21
|
-
@client.request
|
35
|
+
payload = payload_parser_request format
|
36
|
+
@response = Timeout.timeout($a_while) do
|
37
|
+
@client.request payload
|
22
38
|
end
|
23
39
|
end
|
24
40
|
|
41
|
+
should 'return no error' do
|
42
|
+
assert_equal true, @response[:error].empty?
|
43
|
+
end
|
44
|
+
|
25
45
|
should 'return a parsed payload object' do
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
keys = case format
|
31
|
-
when 'JSON'
|
32
|
-
%w(test1 test2)
|
33
|
-
when 'Empty'
|
34
|
-
[]
|
35
|
-
else
|
36
|
-
Payload.hash_keys
|
37
|
-
end
|
46
|
+
assert_kind_of Hash, @response[:data]
|
47
|
+
keys = Payload.hash_keys
|
48
|
+
keys = %w(test1 test2) if format == 'JSON'
|
49
|
+
keys = [] if format == 'Empty'
|
38
50
|
keys.each do |key|
|
39
|
-
payload = @response[
|
51
|
+
payload = @response[:data]
|
40
52
|
assert_not_nil payload[key]
|
41
53
|
assert_not_equal key, payload[key] # catches "string"[key]
|
42
54
|
end
|
@@ -47,16 +59,15 @@ describe 'the Payload Parser' do
|
|
47
59
|
%w(NonJSON).each do |format|
|
48
60
|
given "#{format} payloads" do
|
49
61
|
setup do
|
50
|
-
payload =
|
51
|
-
@response = Timeout.timeout($
|
52
|
-
@client.request
|
62
|
+
payload = payload_parser_request format
|
63
|
+
@response = Timeout.timeout($a_while) do
|
64
|
+
@client.request payload
|
53
65
|
end
|
54
66
|
end
|
55
67
|
|
56
68
|
should 'return an error object' do
|
57
|
-
|
58
|
-
|
59
|
-
assert_equal true, @response['payload'].empty?
|
69
|
+
assert_kind_of String, @response[:error]
|
70
|
+
assert_equal true, @response[:data].empty?
|
60
71
|
end
|
61
72
|
end
|
62
73
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'yaml'
|
3
|
+
require 'oj'
|
4
|
+
require 'robot_sweatshop/payload'
|
5
|
+
require 'robot_sweatshop/config'
|
6
|
+
|
7
|
+
module InputHelper
|
8
|
+
def example_raw_payload(format)
|
9
|
+
payload_strings = YAML.load_file "#{__dir__}/../../data/payload_data.yaml"
|
10
|
+
payload_strings[format.downcase]
|
11
|
+
end
|
12
|
+
|
13
|
+
def input_url(for_job: 'test_job')
|
14
|
+
"http://localhost:#{configatron.http_port}/run/#{for_job}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def conveyor_enqueue(type)
|
18
|
+
format, job = payload_configuration type
|
19
|
+
{
|
20
|
+
method: 'enqueue',
|
21
|
+
data: {
|
22
|
+
payload: example_raw_payload(format),
|
23
|
+
user_agent: user_agent_for(format),
|
24
|
+
job_name: job
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def payload_parser_request(format)
|
30
|
+
{
|
31
|
+
payload: example_raw_payload(format),
|
32
|
+
user_agent: user_agent_for(format)
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def worker_push
|
37
|
+
{
|
38
|
+
commands: [
|
39
|
+
'echo $custom',
|
40
|
+
'echo $custom > test.txt'
|
41
|
+
],
|
42
|
+
context: {'custom' => 'hello world'},
|
43
|
+
job_name: 'test_job',
|
44
|
+
job_id: 1
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def payload_configuration(type)
|
49
|
+
format = 'JSON'
|
50
|
+
format = 'Bitbucket' if type == 'Git' # develop branch
|
51
|
+
format = 'Github' if type == 'IgnoredBranch' # master branch
|
52
|
+
format = 'NonJSON' if type == 'NonJSON'
|
53
|
+
|
54
|
+
job = 'test_job'
|
55
|
+
job = 'git_job' if type == 'Git' || type == 'IgnoredBranch'
|
56
|
+
job = 'minimal_job' if type == 'MinimalJob'
|
57
|
+
job = 'unknown_job' if type == 'UnknownJob' # TODO: why does commenting this out still pass payload parser?!
|
58
|
+
job = 'empty_job' if type == 'EmptyJob'
|
59
|
+
|
60
|
+
[format, job]
|
61
|
+
end
|
62
|
+
|
63
|
+
def user_agent_for(format)
|
64
|
+
case format
|
65
|
+
when 'Bitbucket'
|
66
|
+
'Bitbucket.org'
|
67
|
+
when 'Github'
|
68
|
+
'Github-Hookshot'
|
69
|
+
else
|
70
|
+
'SomeUserAgent'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'robot_sweatshop/payload'
|
4
|
+
require 'robot_sweatshop/config'
|
5
|
+
|
6
|
+
module OutputHelper
|
7
|
+
def worker_output
|
8
|
+
"#{configatron.workspace_path}/test_job-testingid/test.txt"
|
9
|
+
end
|
10
|
+
|
11
|
+
def clear_worker_output
|
12
|
+
FileUtils.rm_rf worker_output
|
13
|
+
end
|
14
|
+
end
|