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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +11 -11
  4. data/Rakefile +1 -1
  5. data/bin/README.md +23 -0
  6. data/bin/sweatshop +1 -1
  7. data/bin/sweatshop-assembler +101 -0
  8. data/bin/sweatshop-conveyor +64 -0
  9. data/bin/{sweatshop-input-http → sweatshop-input} +13 -7
  10. data/bin/sweatshop-job-dictionary +53 -0
  11. data/bin/sweatshop-payload-parser +28 -28
  12. data/bin/sweatshop-worker +58 -0
  13. data/config.defaults.yaml +6 -4
  14. data/lib/README.md +10 -13
  15. data/lib/robot_sweatshop/cli/common.rb +1 -1
  16. data/lib/robot_sweatshop/cli/config.rb +1 -1
  17. data/lib/robot_sweatshop/cli/job.rb +1 -1
  18. data/lib/robot_sweatshop/cli/start.rb +2 -2
  19. data/lib/robot_sweatshop/config.rb +2 -0
  20. data/lib/robot_sweatshop/connections.rb +17 -0
  21. data/lib/robot_sweatshop/create-config-directories.rb +0 -1
  22. data/lib/robot_sweatshop.rb +1 -2
  23. data/robot_sweatshop.eye +30 -32
  24. data/robot_sweatshop.gemspec +8 -6
  25. data/test/README.md +3 -1
  26. data/test/all.rb +35 -0
  27. data/test/assembler_spec.rb +89 -0
  28. data/test/conveyor_spec.rb +67 -0
  29. data/test/data/weird_job.yaml +6 -0
  30. data/test/end-to-end_spec.rb +19 -13
  31. data/test/input_spec.rb +49 -0
  32. data/test/job_dictionary_spec.rb +70 -0
  33. data/test/payload_parser_spec.rb +37 -26
  34. data/test/shared/helpers/input.rb +73 -0
  35. data/test/shared/helpers/output.rb +14 -0
  36. data/test/shared/helpers.rb +4 -83
  37. data/test/shared/scaffolding.rb +42 -0
  38. data/test/shared/stub.rb +44 -0
  39. data/test/worker_spec.rb +59 -0
  40. metadata +76 -44
  41. data/bin/sweatshop-job-assembler +0 -82
  42. data/bin/sweatshop-job-worker +0 -45
  43. data/bin/sweatshop-queue-broadcaster +0 -20
  44. data/bin/sweatshop-queue-handler +0 -24
  45. data/bin/sweatshop-queue-watcher +0 -18
  46. data/lib/robot_sweatshop/moneta-queue.rb +0 -49
  47. data/lib/robot_sweatshop/queue-helper.rb +0 -32
  48. data/robot_sweatshop.production.eye +0 -7
  49. data/robot_sweatshop.testing.eye +0 -7
  50. data/test/input_http_spec.rb +0 -49
  51. data/test/job_assembler_spec.rb +0 -80
  52. data/test/job_worker_spec.rb +0 -65
  53. data/test/moneta-queue_spec.rb +0 -49
  54. data/test/queue_broadcaster_spec.rb +0 -39
  55. data/test/queue_handler_spec.rb +0 -54
  56. data/test/run_all.rb +0 -3
  57. data/test/shared/process_spawning.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 04bbac597bb3b25f0ed7fdf9e44f5232fa6a5f46
4
- data.tar.gz: 1b8e0bef439759c90312b49580440624ca998f26
3
+ metadata.gz: 0549401a67fbd6e2dc3b5b22017d42700958f9c9
4
+ data.tar.gz: 5f741330b8b0999cb078cf0508e9440f595e02e6
5
5
  SHA512:
6
- metadata.gz: daae1e558e2276e84f1bd10692b673fee401a6fb09bfa25e5f944f058f26d9831a3fabaa86d9177df2cedc66f36b5d3e3ea392b81730297f946553a4c229b8ad
7
- data.tar.gz: cdae51f479d280542d028628bf6985c1c513acb597ca1ec567436e5d9c80106a7ecf2e5f222d9773c3aa78c9505f770b5302a82c2d7afef2fb5b1d6af365cbfd
6
+ metadata.gz: e1c7523aea2b3006952303d6e3dfb9f13886cd304479ecec7c5841cfaba5c1455aed8a6ff13815b18ae7ec6af7904dee785333d30ad1a4a4af52badebef6ca5a
7
+ data.tar.gz: 83b86d2de23a74dc9a4623fb23417e37d822271b42e96b05cb3c7cc6f62eb764924d11beb8b1b0417199ac5cdefaa2b09918f670f930b84d24c20558a09993ac
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ .test.*
1
2
  *.gem
2
3
  jobs/*.yaml
3
4
  .robot_sweatshop
data/README.md CHANGED
@@ -10,20 +10,20 @@ Robot Sweatshop is a single-purpose CI server that runs collections of arbitrary
10
10
 
11
11
  - install [ZMQ as described in the EZMQ gem](https://github.com/colstrom/ezmq#operating-system-notes)
12
12
  - `gem install robot_sweatshop`
13
- - `sweatshop start` ([you may need sudo on OSX](https://github.com/JScott/robot_sweatshop/wiki))
13
+ - `sweatshop start`
14
14
  - `sweatshop job example --auto`
15
- - `curl -X POST http://localhost:8080/payload-for/example`
15
+ - `curl -d '' localhost:8080/run/example`
16
16
  - `cat .robot_sweatshop/log/job-worker.log`
17
17
 
18
18
  # Usage
19
19
 
20
- Drop the `--auto` flag to create the job interactively. You can specify which branches will trigger the job, which commands will be run, and any environment variables you might need.
20
+ Drop the `--auto` flag to create the job interactively. You can specify which branches will trigger the job, which commands will be run, and any environment variables you might need. See [the wiki](https://github.com/JScott/robot_sweatshop/wiki/Job-configuration) for more details.
21
21
 
22
22
  Robot Sweatshop uses [Eye](https://github.com/kostya/eye) to handle its processes so you can use its commandline tool to monitor their status.
23
23
 
24
24
  # Configuration
25
25
 
26
- By default, Robot Sweatshop looks in your current working path to configure and run. You can supply a custom configuration with `sweatshop config [local|user|system]`. Read [the wiki](https://github.com/JScott/robot_sweatshop/wiki) for more information.
26
+ By default, Robot Sweatshop looks in your current working path to configure and run. You can supply a custom configuration with `sweatshop config [local|user|system]`. See [the wiki](https://github.com/JScott/robot_sweatshop/wiki) for more information.
27
27
 
28
28
  # Supported payload formats
29
29
 
@@ -34,21 +34,21 @@ By default, Robot Sweatshop looks in your current working path to configure and
34
34
 
35
35
  # Security
36
36
 
37
- You probably don't want to run Robot Sweatshop as a sudo user. Create a testing user and group and point to them in the configuration file to run Robot Sweatshop processes with those permissions.
37
+ You probably don't want to run Robot Sweatshop as a sudo user. Create a testing user and group and run `sweatshop start` as them.
38
38
 
39
39
  # Roadmap
40
40
 
41
41
  1.0
42
42
 
43
- - Improved architecture:
44
-
45
- ![Improved architecture diagram](http://40.media.tumblr.com/8a5b6ca59c0d93c4ce6fc6b733932a5f/tumblr_nko478zp9N1qh941oo1_1280.jpg)
46
-
47
- - Support for multiple workers
43
+ - Docs on architecture
44
+ - Easier way to run multiple workers
45
+ - Mascot
48
46
 
49
47
  Beyond
50
48
 
49
+ - Jenkins-to-Sweatshop job converting script
50
+ - Take a look at beefcake for data versioning/serialization
51
51
  - Better logging for the processes
52
52
  - CLI configuration via chomp and/or flags
53
- - Common scrips such as git repo syncing and creating a job run ID
53
+ - Common scrips such as git repo syncing and creating a job run ID (see: [sweatshop-tears](https://github.com/JScott/sweatshop-tears))
54
54
  - Use [eye-http](https://github.com/kostya/eye-http) for the '/' route?
data/Rakefile CHANGED
@@ -7,5 +7,5 @@ task :test do
7
7
  add_filter "/vendor/"
8
8
  add_filter "/test/"
9
9
  end
10
- require_relative 'test/run_all'
10
+ require_relative 'test/all'
11
11
  end
data/bin/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # Services
2
+
3
+ sweatshop-conveyor
4
+ ```
5
+ { method:, data: }
6
+
7
+ id = enqueue(item)
8
+ id = dequeue
9
+ item = lookup(id)
10
+ something = finish(id)
11
+ ```
12
+
13
+ sweatshop-payload-parser
14
+ ```
15
+ req: { payload:, user_agent: }
16
+ rep: { data:, error: }
17
+ ```
18
+
19
+ sweatshop-job-dictionary
20
+ ```
21
+ req: { job_name: }
22
+ rep: { data:, error: }
23
+ ```
data/bin/sweatshop CHANGED
@@ -8,7 +8,7 @@ require 'robot_sweatshop/config'
8
8
  require 'robot_sweatshop/create-config-directories'
9
9
 
10
10
  program :name, 'Robot Sweatshop'
11
- program :version, '0.3.3'
11
+ program :version, '0.4.0'
12
12
  program :description, 'A lightweight, unopinionated CI server'
13
13
  program :help, 'Author', 'Justin Scott <jvscott@gmail.com>'
14
14
 
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup'
3
+ require 'yaml'
4
+ require 'contracts'
5
+ require 'exponential_backoff'
6
+ require 'ezmq'
7
+ require 'robot_sweatshop/config'
8
+ require 'robot_sweatshop/connections'
9
+ $stdout.sync = true
10
+ include Contracts
11
+ using ExtendedEZMQ
12
+
13
+ Contract Hash => Hash
14
+ def sanitize(data)
15
+ data = data.map { |key, value| {key => value.to_s} }
16
+ data.reduce(:merge)
17
+ end
18
+
19
+ Contract Hash, Hash => Hash
20
+ def job_context(job_environment, context_from_payload)
21
+ sanitize job_environment.merge(context_from_payload)
22
+ end
23
+
24
+ Contract Hash, Hash, Hash => Hash
25
+ def assemble(job, payload, definition)
26
+ {
27
+ commands: definition['commands'],
28
+ context: job_context(definition['environment'] || {}, payload),
29
+ job_name: job[:job_name],
30
+ job_id: job[:job_id]
31
+ }
32
+ end
33
+
34
+ Contract None => Or[Hash,nil]
35
+ def request_job
36
+ job_id = @sockets[:conveyor].request({method: 'dequeue'}, {})
37
+ return nil if job_id.nil?
38
+ raw_job = @sockets[:conveyor].request({method: 'lookup', data: job_id}, {})
39
+ puts "Assembling: '#{raw_job}'"
40
+ raw_job.merge job_id: job_id
41
+ end
42
+
43
+ Contract EZMQ::Socket, Any => Hash
44
+ def request(socket, data)
45
+ response = socket.request data, {}
46
+ raise response[:error] unless response[:error].empty?
47
+ response[:data]
48
+ end
49
+
50
+ Contract Hash => [Hash, Hash]
51
+ def request_data_for(job)
52
+ payload = request @sockets[:parser], job
53
+ definition = request @sockets[:dictionary], job[:job_name]
54
+ [payload, definition]
55
+ end
56
+
57
+ Contract Or[Array,nil], Or[String, nil] => nil
58
+ def check_whitelist(whitelist, branch)
59
+ return if whitelist.nil?
60
+ raise 'Branch not whitelisted' unless whitelist.include? branch
61
+ end
62
+
63
+ Contract Fixnum => Bool
64
+ def finish(job_id)
65
+ @sockets[:conveyor].request({method: 'finish', data: job_id}, {})
66
+ end
67
+
68
+ job_search = Fiber.new do
69
+ # TODO: profiler to get a better idea of how long we should wait based on historical information
70
+ timer = ExponentialBackoff.new 0.1, 3
71
+ loop do
72
+ sleep timer.next_interval
73
+ job = request_job
74
+ next if job.nil?
75
+ timer.clear
76
+ Fiber.yield job
77
+ end
78
+ end
79
+
80
+ puts 'Started'
81
+ @sockets = {
82
+ conveyor: EZMQ::Client.new(port: configatron.conveyor_port),
83
+ worker: EZMQ::Pusher.new(:bind, port: configatron.worker_port),
84
+ parser: EZMQ::Client.new(port: configatron.payload_parser_port),
85
+ dictionary: EZMQ::Client.new(port: configatron.job_dictionary_port)
86
+ }
87
+ @sockets.each { |_key, socket| socket.serialize_with_json! }
88
+
89
+ loop do
90
+ job = job_search.resume
91
+ begin
92
+ payload, definition = request_data_for job
93
+ check_whitelist definition['branch_whitelist'], payload['branch']
94
+ assembled_job = assemble job, payload, definition
95
+ @sockets[:worker].send(assembled_job, {})
96
+ rescue RuntimeError => error
97
+ puts error.message
98
+ finish job[:job_id]
99
+ next
100
+ end
101
+ end
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup'
3
+ require 'ezmq'
4
+ require 'stubborn_queue'
5
+ require 'oj'
6
+ require 'contracts'
7
+ require 'robot_sweatshop/config'
8
+ require 'robot_sweatshop/connections'
9
+ using ExtendedEZMQ
10
+
11
+ queue_settings = {
12
+ name: 'test',
13
+ timeout: configatron.job_timeout_length,
14
+ file: "#{configatron.database_path}/conveyor.db"
15
+ }
16
+ @items = StubbornQueue.new queue_settings
17
+ $stdout.sync = true
18
+ include Contracts
19
+
20
+ Contract Hash => Fixnum
21
+ def enqueue(item)
22
+ puts "enqueue #{item}"
23
+ @items.enqueue Oj.dump(item)
24
+ end
25
+
26
+ Contract None => Or[Fixnum,nil]
27
+ def dequeue
28
+ puts "dequeue"
29
+ @items.dequeue
30
+ end
31
+
32
+ Contract Fixnum => Hash
33
+ def lookup(id)
34
+ puts "lookup #{id}"
35
+ Oj.load @items.lookup(id)
36
+ end
37
+
38
+ Contract Fixnum => Bool
39
+ def finish(id)
40
+ puts "finish #{id}"
41
+ @items.finish id
42
+ end
43
+
44
+ Contract String => Bool
45
+ def supported?(method)
46
+ %w(enqueue dequeue lookup finish).include? method
47
+ end
48
+
49
+ Contract Hash => Any
50
+ def complete(request)
51
+ arguments = []
52
+ return send(request[:method], request[:data]) if request[:data]
53
+ send(request[:method])
54
+ end
55
+
56
+ puts 'Starting the Conveyor'
57
+ server = EZMQ::Server.new port: configatron.conveyor_port
58
+ server.serialize_with_json!
59
+ server.listen do |request|
60
+ puts "Received: #{request.inspect}"
61
+ next unless request.is_a? Hash
62
+ next unless supported? request[:method]
63
+ complete request
64
+ end
@@ -2,28 +2,34 @@
2
2
  require 'bundler/setup'
3
3
  require 'sinatra'
4
4
  require 'ezmq'
5
- require 'json'
6
5
  require 'robot_sweatshop/config'
6
+ require 'robot_sweatshop/connections'
7
+ using ExtendedEZMQ
7
8
 
8
9
  configure do
9
10
  set :port, configatron.http_port
10
11
  set :bind, configatron.http_bind
11
12
  set :run, true
13
+ set :conveyor, EZMQ::Client.new(port: configatron.conveyor_port)
14
+ settings.conveyor.serialize_with_json!
12
15
  end
13
16
 
14
17
  get '/' do
15
18
  'Everything\'s on schedule!'
16
19
  end
17
20
 
18
- post '/payload-for/:job_name' do
21
+ post '/run/:job_name' do
19
22
  puts "Received payload for #{params['job_name']}"
20
23
  request.body.rewind
21
24
  payload = request.body.read
22
25
  hash = {
23
- payload: payload,
24
- user_agent: request.env['HTTP_USER_AGENT'],
25
- job_name: params['job_name']
26
+ method: 'enqueue',
27
+ data: {
28
+ payload: payload,
29
+ user_agent: request.env['HTTP_USER_AGENT'],
30
+ job_name: params['job_name']
31
+ }
26
32
  }
27
- client = EZMQ::Client.new port: 5556
28
- client.request "payload #{JSON.generate hash}"
33
+ settings.conveyor.request hash, {}
34
+ 200
29
35
  end
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup'
3
+ require 'oj'
4
+ require 'ezmq'
5
+ require 'contracts'
6
+ require 'robot_sweatshop/config'
7
+ require 'robot_sweatshop/connections'
8
+ $stdout.sync = true
9
+ include Contracts
10
+ using ExtendedEZMQ
11
+
12
+ Contract None => String
13
+ def job_path
14
+ File.expand_path configatron.job_path
15
+ end
16
+
17
+ Contract String => Or[Hash, nil]
18
+ def load_if_exists(config_path)
19
+ puts "Reading job configuration from #{config_path}"
20
+ YAML.load_file config_path if File.exists? config_path
21
+ end
22
+
23
+ Contract None => Hash
24
+ def empty_config
25
+ puts "Job configuration not found or empty"
26
+ {}
27
+ end
28
+
29
+ Contract String => Hash
30
+ def load_config_for(job_name)
31
+ load_if_exists("#{job_path}/#{job_name}.yaml") || empty_config
32
+ end
33
+
34
+ Contract Hash, Hash => Hash
35
+ def formatted(payload={}, error:'')
36
+ {data: payload, error: error}
37
+ end
38
+
39
+ Contract String => Hash
40
+ def define(job_name)
41
+ config = load_config_for job_name
42
+ return formatted error: 'Job not found or empty' if config.empty?
43
+ return formatted error: 'No commands' unless config['commands'].is_a? Array
44
+ formatted config
45
+ end
46
+
47
+ puts 'Started'
48
+ server = EZMQ::Server.new port: configatron.job_dictionary_port
49
+ server.serialize_with_json!
50
+ server.listen do |job_name|
51
+ puts "Looking up: #{job_name}"
52
+ define job_name
53
+ end
@@ -1,20 +1,21 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'bundler/setup'
3
- require 'json'
3
+ require 'oj'
4
4
  require 'ezmq'
5
5
  require 'contracts'
6
6
  require 'robot_sweatshop/config'
7
7
  require 'robot_sweatshop/payload'
8
-
8
+ require 'robot_sweatshop/connections'
9
9
  $stdout.sync = true
10
10
  include Contracts
11
+ using ExtendedEZMQ
11
12
 
12
13
  Contract String => Bool
13
14
  def json?(string)
14
15
  begin
15
- JSON.load string
16
+ Oj.load string
16
17
  true
17
- rescue JSON::ParserError => e
18
+ rescue Oj::ParseError => e
18
19
  false
19
20
  end
20
21
  end
@@ -31,42 +32,41 @@ end
31
32
 
32
33
  Contract Hash => String
33
34
  def detect_format_of(request)
34
- return 'empty' if request['payload'].empty?
35
- return 'Github' if from_github? request['user_agent']
36
- return 'Bitbucket' if from_bitbucket? request['user_agent']
37
- return 'JSON' if json? request['payload']
35
+ return 'empty' if request[:payload].empty?
36
+ return 'Github' if from_github? request[:user_agent]
37
+ return 'Bitbucket' if from_bitbucket? request[:user_agent]
38
+ return 'JSON' if json? request[:payload]
38
39
  'unsupported'
39
40
  end
40
41
 
41
42
  Contract String, String => Or[Hash, nil]
42
43
  def payload_hash_from(payload, format)
43
- # TODO: use require instead of require_relative
44
- lib_file = "#{__dir__}/../lib/robot_sweatshop/payload/#{format.downcase}.rb"
45
- return nil unless File.file?(lib_file)
46
- require_relative lib_file
47
- Object.const_get("#{format}Payload").new(payload).to_hash
44
+ begin
45
+ Object.const_get("#{format}Payload").new(payload).to_hash
46
+ rescue NameError
47
+ nil
48
+ end
48
49
  end
49
50
 
50
- Contract Hash => Hash
51
- def parse(request)
52
- format = detect_format_of request
53
- return {payload: {}, error: ''} if format == 'empty'
54
- payload = payload_hash_from request['payload'], format
55
- return {payload: {}, error: "Can't parse #{format} payload"} if payload.nil?
56
- {payload: payload, error: ''}
51
+ Contract Hash, Hash => Hash
52
+ def formatted(payload={}, error:'')
53
+ {data: payload, error: error}
57
54
  end
58
55
 
59
- Contract Any => Hash
60
- def validate(request)
61
- return {payload: {}, error: "Invalid JSON request"} unless json? request
62
- JSON.load request
56
+ Contract String, String => Hash
57
+ def parse(raw_payload, format)
58
+ return formatted if format == 'empty'
59
+ return formatted error: 'Unknown format' if format == 'unsupported'
60
+ payload = payload_hash_from raw_payload, format
61
+ return formatted error: "Invalid #{format} payload" if payload.nil?
62
+ formatted payload
63
63
  end
64
64
 
65
65
  puts 'Started'
66
- server = EZMQ::Server.new port: configatron.payload_parser_port#, encode: -> m { JSON.dump m }
66
+ server = EZMQ::Server.new port: configatron.payload_parser_port
67
+ server.serialize_with_json!
67
68
  server.listen do |request|
68
69
  puts "Parsing: #{request}"
69
- request = validate request
70
- request = parse request unless request[:error]
71
- JSON.dump request
70
+ format = detect_format_of request
71
+ parse request[:payload], format
72
72
  end
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup'
3
+ require 'ezmq'
4
+ require 'faker'
5
+ require 'fileutils'
6
+ require 'contracts'
7
+ require 'robot_sweatshop/config'
8
+ require 'robot_sweatshop/connections'
9
+ using ExtendedEZMQ
10
+ $stdout.sync = true
11
+ $stderr.sync = true
12
+ include Contracts
13
+
14
+ # TODO: check existing worker ids. it'd be a problem to share a workspace
15
+ @worker_id = ARGV[0] || "#{Faker::Name.first_name}"
16
+
17
+ Contract Hash, Proc => Any
18
+ def from_workspace(named:)
19
+ workspace = "#{named}-#{@worker_id}"
20
+ puts "Workspace: #{workspace}"
21
+ path = File.expand_path "#{configatron.workspace_path}/#{workspace}"
22
+ FileUtils.mkpath path
23
+ Dir.chdir(path) { yield if block_given? }
24
+ end
25
+
26
+ Contract Hash, String => nil
27
+ def execute(context, command)
28
+ puts "Executing '#{command}'..."
29
+ # TODO: path.split(' ') to bypass the shell when we're not using env vars
30
+ IO.popen(context, command) do |io_stream|
31
+ while line = io_stream.gets
32
+ puts line
33
+ end
34
+ end
35
+ puts "Execution complete with exit status: #{$?.exitstatus}"
36
+ end
37
+
38
+ Contract Fixnum => nil
39
+ def finish(id)
40
+ @sockets[:conveyor].request({method: 'finish', data: id}, {})
41
+ puts "Job finished.\n\n"
42
+ end
43
+
44
+ puts 'Starting'
45
+ @sockets = {
46
+ conveyor: EZMQ::Client.new(port: configatron.conveyor_port),
47
+ puller: EZMQ::Puller.new(:connect, port: configatron.worker_port)
48
+ }
49
+ @sockets.each { |_key, socket| socket.serialize_with_json! }
50
+
51
+ @sockets[:puller].listen do |data|
52
+ puts "Running: #{data}"
53
+ from_workspace named: data[:job_name] do
54
+ context = data[:context] || {}
55
+ data[:commands].each { |command| execute context, command }
56
+ end
57
+ finish data[:job_id]
58
+ end
data/config.defaults.yaml CHANGED
@@ -3,9 +3,11 @@ pidfile_path: .robot_sweatshop/run
3
3
  logfile_path: .robot_sweatshop/log
4
4
  job_path: .robot_sweatshop/jobs
5
5
  workspace_path: .robot_sweatshop/workspaces
6
- moneta_path: .robot_sweatshop/db
6
+ database_path: .robot_sweatshop/db
7
7
  http_port: 8080
8
8
  http_bind: 0.0.0.0
9
- # queue_handler_port: 5556
10
- # queue_broadcaster_port: 5557
11
- payload_parser_port: 5558
9
+ conveyor_port: 5555
10
+ payload_parser_port: 5556
11
+ job_dictionary_port: 5557
12
+ worker_port: 5558
13
+ job_timeout_length: 300 # 5 minutes
data/lib/README.md CHANGED
@@ -1,21 +1,18 @@
1
1
  Job lifecycle:
2
2
 
3
3
  ```
4
- in-* -> payloads { payload:, user_agent:, job_name: } ->
5
- job-assembler -> jobs { context:, commands:, job_name: } ->
6
- job-worker
7
- ```
8
-
9
- All passing done via the moneta core in queue/*
4
+ input -> conveyor
5
+ { payload:, user_agent:, job_name: }
10
6
 
11
- Also queue/watcher for debugging
7
+ assembler <-> conveyor
12
8
 
13
- ---
9
+ assembler <-> payload-parser
10
+ assembler <-> job-dictionary
11
+ { payload:, user_agent: } <-> { payload:, error: }
14
12
 
15
- The Job Assembler also uses the Payload Parser service:
16
-
17
- ```
18
- { payload:, user_agent: } -> payload-parser -> { payload:, error: }
13
+ assembler -> worker
14
+ { context:, commands:, job_name:, job_id }
19
15
  ```
20
16
 
21
- Error is an empty string when it's successful. Otherwise it details what went wrong.
17
+ context is passed around with string keys because it's user provided
18
+ everything else is passed with symbol keys
@@ -1,5 +1,5 @@
1
1
  require 'fileutils'
2
- require_relative '../config'
2
+ require 'robot_sweatshop/config'
3
3
 
4
4
  def notify(type = :success, string)
5
5
  color = case type
@@ -1,4 +1,4 @@
1
- require_relative '../config'
1
+ require 'robot_sweatshop/config'
2
2
 
3
3
  def default_config
4
4
  File.read "#{__dir__}/../../../config.defaults.yaml"
@@ -1,4 +1,4 @@
1
- require_relative '../config'
1
+ require 'robot_sweatshop/config'
2
2
 
3
3
  def default_job
4
4
  "---\n# branch_whitelist:\n# - master\n\ncommands:\n- echo \"Hello $WORLD!\"\n\nenvironment:\n WORLD: Earth\n"
@@ -1,5 +1,5 @@
1
1
  require 'yaml'
2
- require_relative '../config'
2
+ require 'robot_sweatshop/config'
3
3
 
4
4
  def store_config_for_eye
5
5
  config = configatron.to_h
@@ -12,7 +12,7 @@ end
12
12
 
13
13
  def start_sweatshop(for_environment:)
14
14
  store_config_for_eye
15
- eye_config = File.expand_path "#{__dir__}/../../../robot_sweatshop.#{for_environment}.eye"
15
+ eye_config = File.expand_path "#{__dir__}/../../../robot_sweatshop.eye"
16
16
  output = `eye load #{eye_config}`
17
17
  if $?.exitstatus != 0
18
18
  notify :failure, output
@@ -17,3 +17,5 @@ configurations.each do |config_path|
17
17
  configatron.configure_from_hash hash
18
18
  end
19
19
  end
20
+
21
+ require 'robot_sweatshop/create-config-directories'
@@ -0,0 +1,17 @@
1
+ require 'ezmq'
2
+ require 'oj'
3
+ require 'robot_sweatshop/config'
4
+
5
+ module ExtendedEZMQ
6
+ refine EZMQ::Socket do
7
+ def serialize_with_json!
8
+ self.encode = -> message { Oj.dump message }
9
+ self.decode = -> message { Oj.load message }
10
+ end
11
+
12
+ def close
13
+ self.socket.close
14
+ self.context.terminate
15
+ end
16
+ end
17
+ end
@@ -1,5 +1,4 @@
1
1
  require 'fileutils'
2
- require_relative 'config'
3
2
 
4
3
  def create_path(path)
5
4
  begin
@@ -1,5 +1,4 @@
1
- require_relative 'robot_sweatshop/moneta-queue'
2
- require_relative 'robot_sweatshop/queue-helper'
3
1
  require_relative 'robot_sweatshop/config'
4
2
  require_relative 'robot_sweatshop/payload'
5
3
  require_relative 'robot_sweatshop/cli'
4
+ require_relative 'robot_sweatshop/connections'