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.
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'