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/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
|