robot_sweatshop 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -3
  3. data/README.md +14 -12
  4. data/Rakefile +0 -4
  5. data/bin/sweatshop +28 -46
  6. data/{lib/input/http.rb → bin/sweatshop-input-http} +4 -3
  7. data/{lib/job/assembler.rb → bin/sweatshop-job-assembler} +15 -23
  8. data/{lib/job/worker.rb → bin/sweatshop-job-worker} +6 -3
  9. data/{lib/payload/parser.rb → bin/sweatshop-payload-parser} +2 -2
  10. data/{lib/queue/broadcaster.rb → bin/sweatshop-queue-broadcaster} +2 -1
  11. data/{lib/queue/handler.rb → bin/sweatshop-queue-handler} +1 -1
  12. data/{lib/queue/watcher.rb → bin/sweatshop-queue-watcher} +0 -0
  13. data/config.defaults.yaml +10 -0
  14. data/{jobs/example.yaml → kintama/data/test_job.yaml} +0 -0
  15. data/kintama/end-to-end_spec.rb +1 -1
  16. data/kintama/input_http_spec.rb +1 -1
  17. data/kintama/moneta-queue_spec.rb +1 -1
  18. data/kintama/shared/helpers.rb +9 -9
  19. data/kintama/shared/process_spawning.rb +2 -0
  20. data/{bin/lib → lib/sweatshop/cli}/common.rb +8 -16
  21. data/lib/sweatshop/cli/config.rb +16 -0
  22. data/lib/sweatshop/cli/job.rb +14 -0
  23. data/lib/sweatshop/cli/start.rb +25 -0
  24. data/lib/sweatshop/config.rb +19 -0
  25. data/lib/sweatshop/create-config-directories.rb +29 -0
  26. data/lib/{queue/lib → sweatshop}/moneta-queue.rb +2 -2
  27. data/lib/{payload/lib → sweatshop/payload}/bitbucket.rb +0 -0
  28. data/lib/{payload/lib → sweatshop/payload}/github.rb +0 -0
  29. data/lib/{payload/lib → sweatshop/payload}/payload.rb +0 -0
  30. data/lib/{queue-helper.rb → sweatshop/queue-helper.rb} +0 -0
  31. data/lib/sweatshop.rb +16 -0
  32. data/robot_sweatshop.eye +26 -26
  33. data/robot_sweatshop.gemspec +5 -2
  34. data/robot_sweatshop.production.eye +2 -3
  35. data/robot_sweatshop.testing.eye +2 -3
  36. metadata +59 -23
  37. data/bin/lib/config.rb +0 -20
  38. data/bin/lib/inspect.rb +0 -42
  39. data/bin/lib/job.rb +0 -13
  40. data/bin/lib/setup.rb +0 -25
  41. data/bin/lib/start.rb +0 -11
  42. data/config.rb +0 -16
  43. data/config.yaml +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dba386e07d0e4cced4e3f798b2e8b0bad86f7fbf
4
- data.tar.gz: d45191b2778dd0da0c68a3fa894af7b69adc6155
3
+ metadata.gz: edaa6abb2f131c571be0f100430763222e988055
4
+ data.tar.gz: dd254380c37b2e7cc946d077e01f5114bf15f609
5
5
  SHA512:
6
- metadata.gz: bacf799921528b9999ba5f4bf14f007f471dc25804ac573f7a0024ee0911e5120bb8cdabd7525a74b2fa4fa8740b0461738fb2d9fe83d9c7012a3367f1eb7d99
7
- data.tar.gz: 6f1799495398e16f2d50e3be43728513367dece4c5a7cca81354aaeb4893e656b85e88e869cb783e232fcce85c1631c25d3a0a578af10430ea098c439ccec9e2
6
+ metadata.gz: 67a7804817f3f55a23e147a5cb2f15043b34cc906c6783a4bd55dce02ce846ee7d9b442b1c51d96477c27b173dfc9ab9ea59a476b549b096bb9bce508956c6fb
7
+ data.tar.gz: d14b8909e070f2ac63346e233758f353e0345f61afe2e5f5fccf6f4afd6570024f9d8ef92ed3e1da1817f6c93e759b3a7ea4b62358d2b534f45d315c6528b298
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
- config.user.yaml
2
1
  *.gem
3
2
  jobs/*.yaml
4
- workspaces/**/*
5
- !workspaces/.keep
3
+ .robot_sweatshop
4
+
6
5
  Gemfile.lock
6
+ .bundle
7
+ vendor
data/README.md CHANGED
@@ -4,29 +4,30 @@
4
4
 
5
5
  Robot Sweatshop is a single-purpose CI server that runs collections of arbitrary scripts when it needs to, usually when new code is pushed. There's no assumptions about what you want to report, what front-end you need, or even what repositories you want to clone because you can do that better than I can. It's just you, your code, and the scripts that test and deploy it.
6
6
 
7
- # Usage
7
+ # Quick start
8
+
9
+ - install [ZMQ as described in the EZMQ gem](https://github.com/colstrom/ezmq)
10
+ - `gem install robot_sweatshop`
11
+ - `sweatshop start` ([you may need sudo on OSX](https://github.com/JScott/robot_sweatshop/wiki))
12
+ - `sweatshop job example --auto`
13
+ - POST a Github payload to `localhost:8080/github/payload-for/example`
14
+ - `cat .robot_sweatshop/log/job-worker.log`
8
15
 
9
- First install [ZMQ as described in the EZMQ gem](https://github.com/colstrom/ezmq). Then `gem install robot_sweatshop`.
16
+ # Usage
10
17
 
11
- You can now use `sweatshop config` to configure the processes, `sweatshop setup` to ensure the directories in your config exist, and `sweatshop start` to run everything.
18
+ 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.
12
19
 
13
20
  Robot Sweatshop uses [Eye](https://github.com/kostya/eye) to handle its processes so you can use its commandline tool to monitor their status.
14
21
 
15
- After configuring a job, POST a payload to `localhost:8080/:format/payload-for/:job`. For example, triggering a Bitbucket Git POST hook on `localhost:8080/bitbucket/payload-for/example` will parse the payload and run the 'example' job with the payload data in the environment.
22
+ # Configuration
16
23
 
17
- You can see what jobs are available with `sweatshop job --list`.
24
+ By default, Robot Sweatshop looks in your current working directory 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.
18
25
 
19
- Currently supported formats:
26
+ # Supported payload formats
20
27
 
21
28
  - Github (application/json format only)
22
29
  - Bitbucket
23
30
 
24
- # Configuration
25
-
26
- The server isn't much help without a job to run. Run `sweatshop job <name>` to create a new job or edit an existing one.
27
-
28
- Not sure if your job is valid? Run `sweatshop job --inspection <name>` to see if there's something you overlooked.
29
-
30
31
  # Security
31
32
 
32
33
  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.
@@ -38,6 +39,7 @@ You probably don't want to run Robot Sweatshop as a sudo user. Create a testing
38
39
  - Common scrips such as git repo syncing and creating a job run ID
39
40
  - Support for multiple workers
40
41
  - Better logging for the processes
42
+ - Use [eye-http](https://github.com/kostya/eye-http) for the '/' route?
41
43
  - Improved architecture:
42
44
 
43
45
  ![Improved architecture diagram](http://40.media.tumblr.com/8a5b6ca59c0d93c4ce6fc6b733932a5f/tumblr_nko478zp9N1qh941oo1_1280.jpg)
data/Rakefile CHANGED
@@ -1,7 +1,3 @@
1
1
  task :test do
2
2
  require_relative 'kintama/run_all'
3
3
  end
4
-
5
- task :create_dirs do
6
- require_relative 'config'
7
- end
data/bin/sweatshop CHANGED
@@ -2,43 +2,52 @@
2
2
  require 'yaml'
3
3
  require 'commander/import'
4
4
  require 'colorize'
5
- require_relative 'lib/common'
6
- require_relative 'lib/job'
7
- require_relative 'lib/inspect'
8
- require_relative 'lib/start'
9
- require_relative 'lib/config'
10
- require_relative '../config'
5
+ require_relative '../lib/sweatshop/cli/common'
6
+ require_relative '../lib/sweatshop/cli/job'
7
+ require_relative '../lib/sweatshop/cli/start'
8
+ require_relative '../lib/sweatshop/cli/config'
9
+ require_relative '../lib/sweatshop/config'
10
+ require_relative '../lib/sweatshop/create-config-directories'
11
11
 
12
12
  program :name, 'Robot Sweatshop'
13
- program :version, '0.1.2'
13
+ program :version, '0.2.0'
14
14
  program :description, 'A lightweight, unopinionated CI server'
15
15
  program :help, 'Author', 'Justin Scott <jvscott@gmail.com>'
16
16
 
17
17
  command :job do |c|
18
18
  c.syntax = 'sweatshop job <name>'
19
19
  c.description = 'Creates and edits jobs.'
20
- c.option '--list', 'List all available jobs.'
21
- c.option '--inspection', 'Inspect the given job.'
20
+ c.option '--auto', 'Create the file without opening the editor.'
22
21
  c.action do |args, options|
23
- options.default :list => false
24
- options.default :inspect => false
25
-
26
- job_file = get_job_file for_job: args.first
27
- if options.list
28
- list_jobs
29
- elsif options.inspection
30
- validate job_file unless job_file.nil?
22
+ options.default :auto => false
23
+ if args.count < 1
24
+ notify :failure, "Specify a job name as the command argument."
25
+ exit 1
31
26
  else
32
- create_and_edit_job job_file unless job_file.nil?
27
+ job_file = get_job_path for_job: args.first
28
+ create job_file, with_contents: default_job
29
+ edit job_file unless options.auto
33
30
  end
34
31
  end
35
32
  end
36
33
 
34
+ command :config do |c|
35
+ c.syntax = 'sweatshop config [options]'
36
+ c.description = 'Creates and edits the user configuration file.'
37
+ c.option '--auto', 'Create the file without opening the editor.'
38
+ c.action do |args, options|
39
+ options.default :auto => false
40
+ config_file = get_config_path for_scope: args.first
41
+ create config_file, with_contents: default_config
42
+ edit config_file unless options.auto
43
+ end
44
+ end
45
+
37
46
  command :start do |c|
38
47
  c.syntax = 'sweatshop start [options]'
39
48
  c.description = 'Start the Sweatshop.'
40
49
  c.option '--testing', 'Load the testing Eye configuration.'
41
- c.action do |args, options|
50
+ c.action do |_args, options|
42
51
  options.default :testing => false
43
52
  environment = options.testing ? 'testing' : 'production'
44
53
  start_sweatshop for_environment: environment
@@ -52,30 +61,3 @@ command :stop do |c|
52
61
  notify :info, `eye stop robot_sweatshop`
53
62
  end
54
63
  end
55
-
56
- command :setup do |c|
57
- c.syntax = 'sweatshop setup'
58
- c.description = 'Create the directories and set permissions as specified in the config.'
59
- c.action do
60
- require_relative 'lib/setup'
61
- end
62
- end
63
-
64
- command :directory do |c|
65
- c.syntax = 'sweatshop directory'
66
- c.description = 'Return the path that Robot Sweatshop runs from.'
67
- c.action do
68
- puts File.expand_path("#{__dir__}/..")
69
- end
70
- end
71
-
72
- command :config do |c|
73
- c.syntax = 'sweatshop config [options]'
74
- c.description = 'Creates and edits the user configuration file.'
75
- c.option '--reset', 'Reset to factory defaults before editing.'
76
- c.action do |args, options|
77
- options.default :reset => false
78
- remove_user_config if options.reset
79
- create_and_edit_user_config
80
- end
81
- end
@@ -2,12 +2,13 @@
2
2
  require 'sinatra'
3
3
  require 'ezmq'
4
4
  require 'json'
5
- require_relative '../../config'
5
+ require_relative '../lib/sweatshop/config'
6
6
 
7
7
  configure do
8
- set :port, configatron.input.http.port
9
- set :bind, configatron.input.http.bind
8
+ set :port, configatron.http_port
9
+ set :bind, configatron.http_bind
10
10
  set :output_queue, 'raw-payload'
11
+ set :run, true
11
12
  end
12
13
 
13
14
  get '/' do
@@ -1,28 +1,18 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'yaml'
3
- require_relative '../queue-helper'
4
- require_relative '../../config'
3
+ require_relative '../lib/sweatshop/queue-helper'
4
+ require_relative '../lib/sweatshop/config'
5
5
 
6
- def find_job_config_file(job_name)
7
- configurations = [
8
- "#{__dir__}/../../jobs",
9
- configatron.assembler.job_directory
10
- ]
11
- configurations.each do |config_path|
12
- file_path = "#{config_path}/#{job_name}.yaml"
13
- puts file_path
14
- return file_path if File.file? file_path
15
- end
16
- nil
17
- end
18
-
19
- def load_config(for_job_name:)
20
- job_config_path = find_job_config_file for_job_name
21
- if job_config_path.nil?
22
- puts "No config found for job '#{for_job_name}'"
23
- return nil
6
+ def load_config(for_job:)
7
+ job_directory = File.expand_path configatron.job_directory
8
+ file_path = "#{job_directory}/#{for_job}.yaml"
9
+ puts file_path
10
+ if File.file?(file_path)
11
+ YAML.load_file file_path
12
+ else
13
+ puts "No config found for job '#{for_job}'"
14
+ nil
24
15
  end
25
- YAML.load_file job_config_path
26
16
  end
27
17
 
28
18
  def serialize(value)
@@ -30,8 +20,8 @@ def serialize(value)
30
20
  end
31
21
 
32
22
  def assemble_job(data)
33
- job_config = load_config for_job_name: data['job_name']
34
- return nil unless job_config
23
+ job_config = load_config for_job: data['job_name']
24
+ return nil if job_config.nil?
35
25
  if job_config['branch_whitelist'].include? data['payload']['branch']
36
26
  context = job_config['environment'].merge(data['payload'])
37
27
  context.each { |key, value| context[key] = serialize value }
@@ -50,4 +40,6 @@ QueueHelper.wait_for('parsed-payload') do |data|
50
40
  puts "Assembling: #{data}"
51
41
  assembled_job = assemble_job data
52
42
  QueueHelper.enqueue assembled_job, to: 'jobs' if assembled_job
43
+ $stdout.flush
44
+ $stderr.flush
53
45
  end
@@ -1,8 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'faker'
3
3
  require 'fileutils'
4
- require_relative '../queue-helper'
5
- require_relative '../../config'
4
+ require_relative '../lib/sweatshop/queue-helper'
5
+ require_relative '../lib/sweatshop/config'
6
+
7
+ $stdout.sync = true
8
+ $stderr.sync = true
6
9
 
7
10
  # TODO: check existing worker ids. it'd be disastrous to have two sharing a workspace
8
11
  @worker_id = ARGV[0] || "#{Faker::Name.first_name}"
@@ -10,7 +13,7 @@ require_relative '../../config'
10
13
  def from_workspace(named: 'no_job_name')
11
14
  workspace = "#{named}-#{@worker_id}"
12
15
  puts "Workspace: #{workspace}"
13
- path = "#{configatron.worker.workspace_directory}/#{workspace}"
16
+ path = File.expand_path "#{configatron.workspace_directory}/#{workspace}"
14
17
  FileUtils.mkpath path
15
18
  Dir.chdir(path) { yield if block_given? }
16
19
  end
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
- require_relative '../queue-helper'
2
+ require_relative '../lib/sweatshop/queue-helper'
3
3
 
4
4
  def parse(payload = '', of_format:)
5
5
  of_format = of_format.downcase
6
- lib_file = "#{__dir__}/lib/#{of_format}.rb"
6
+ lib_file = "#{__dir__}/../lib/sweatshop/payload/#{of_format}.rb"
7
7
  if of_format != 'payload' && File.file?(lib_file)
8
8
  require_relative lib_file
9
9
  Object.const_get("#{of_format.capitalize}Payload").new payload
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- require_relative 'lib/moneta-queue'
2
+ require_relative '../lib/sweatshop/moneta-queue'
3
3
  require 'ezmq'
4
4
 
5
5
  publisher = EZMQ::Publisher.new port: 5557
@@ -12,6 +12,7 @@ end
12
12
 
13
13
  loop do
14
14
  queues.each do |queue_name, queue|
15
+ p queue_name if queue.size > 0
15
16
  publisher.send queue_name, topic: 'busy-queues' if queue.size > 0
16
17
  end
17
18
  sleep @wait_time unless @wait_time == 0
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- require_relative 'lib/moneta-queue'
2
+ require_relative '../lib/sweatshop/moneta-queue'
3
3
  require 'ezmq'
4
4
 
5
5
  def enqueue(name, item)
@@ -0,0 +1,10 @@
1
+ ---
2
+ pidfile_directory: .robot_sweatshop/run
3
+ logfile_directory: .robot_sweatshop/log
4
+ job_directory: .robot_sweatshop/jobs
5
+ workspace_directory: .robot_sweatshop/workspaces
6
+ moneta_directory: .robot_sweatshop/db
7
+ # user: ci-bot
8
+ # group: nogroup
9
+ http_port: 8080
10
+ http_bind: 0.0.0.0
File without changes
@@ -11,7 +11,7 @@ describe 'Robot Sweatshop' do
11
11
 
12
12
  setup do
13
13
  @client = EZMQ::Client.new port: 5556
14
- @job_name = 'example'
14
+ @job_name = 'test_job'
15
15
  @test_file = reset_test_file
16
16
  clear_all_queues
17
17
  end
@@ -13,7 +13,7 @@ given 'the HTTP Input' do
13
13
  setup do
14
14
  @subscriber = EZMQ::Subscriber.new port: 5557, topic: 'busy-queues'
15
15
  @client = EZMQ::Client.new port: 5556
16
- @job_name = 'example'
16
+ @job_name = 'test_job'
17
17
  @raw_payload_queue = 'raw-payload'
18
18
  clear_all_queues
19
19
  end
@@ -1,6 +1,6 @@
1
1
  require 'kintama'
2
2
  require_relative 'shared/helpers'
3
- require_relative '../lib/queue/lib/moneta-queue'
3
+ require_relative '../lib/sweatshop/moneta-queue'
4
4
 
5
5
  given 'the Moneta Queue class' do
6
6
  include QueueHelper
@@ -1,8 +1,8 @@
1
1
  require 'yaml'
2
2
  require 'json'
3
- require_relative '../../lib/queue/lib/moneta-queue'
4
- require_relative '../../lib/payload/lib/payload'
5
- require_relative '../../config'
3
+ require_relative '../../lib/sweatshop/moneta-queue'
4
+ require_relative '../../lib/sweatshop/payload/payload'
5
+ require_relative '../../lib/sweatshop/config'
6
6
 
7
7
  module QueueHelper
8
8
  def clear_all_queues
@@ -26,15 +26,15 @@ module InHelper
26
26
  payload = load_payload with_format
27
27
  JSON.generate payload: payload,
28
28
  format: with_format,
29
- job_name: 'example'
29
+ job_name: 'test_job'
30
30
  end
31
- def input_http_url(for_job: 'example', in_format: 'bitbucket')
32
- "http://localhost:#{configatron.input.http.port}/#{in_format}/payload-for/#{for_job}"
31
+ def input_http_url(for_job: 'test_job', in_format: 'bitbucket')
32
+ "http://localhost:#{configatron.http_port}/#{in_format}/payload-for/#{for_job}"
33
33
  end
34
34
  end
35
35
 
36
36
  module PayloadHelper
37
- def example_parsed_payload(with_payload: nil, for_branch: 'develop', for_job: 'example')
37
+ def example_parsed_payload(with_payload: nil, for_branch: 'develop', for_job: 'test_job')
38
38
  payload = with_payload || { branch: for_branch }
39
39
  JSON.generate payload: payload,
40
40
  job_name: for_job
@@ -45,10 +45,10 @@ module JobHelper
45
45
  def example_job(in_context: {}, with_commands: [])
46
46
  JSON.generate context: in_context,
47
47
  commands: with_commands,
48
- job_name: 'example'
48
+ job_name: 'test_job'
49
49
  end
50
50
  def reset_test_file
51
- test_file = File.expand_path "#{configatron.worker.workspace_directory}/example-testingid/test.txt"
51
+ test_file = File.expand_path "#{configatron.workspace_directory}/test_job-testingid/test.txt"
52
52
  FileUtils.rm_rf test_file
53
53
  test_file
54
54
  end
@@ -5,9 +5,11 @@ $for_everything = 3
5
5
 
6
6
  Kintama.on_start do
7
7
  puts `#{__dir__}/../../bin/sweatshop start --testing`
8
+ FileUtils.cp "#{__dir__}/../data/test_job.yaml", File.expand_path(configatron.job_directory)
8
9
  sleep $for_everything
9
10
  end
10
11
 
11
12
  Kintama.on_finish do
12
13
  puts `#{__dir__}/../../bin/sweatshop stop`
14
+ # FileUtils.rm "#{configatron.job_directory}/test_job.yaml"
13
15
  end
@@ -1,4 +1,5 @@
1
1
  require 'fileutils'
2
+ require_relative '../config'
2
3
 
3
4
  def notify(type = :success, string)
4
5
  color = case type
@@ -16,34 +17,25 @@ def notify(type = :success, string)
16
17
  puts "[#{type.to_s.capitalize.colorize(color)}] #{string}"
17
18
  end
18
19
 
19
- def get_job_file(for_job:)
20
- for_job = "#{__dir__}/../../jobs/#{for_job}.yaml"
21
- if for_job.nil?
22
- notify :failure, 'Please specify the job to create or edit. See --help for details'
23
- nil
24
- else
25
- File.expand_path for_job
26
- end
27
- end
28
-
29
20
  def edit(file)
30
21
  edit = ENV['EDITOR']
31
22
  if edit
32
23
  notify :info, "Manually editing file '#{file}'"
33
24
  system edit, file
34
25
  else
35
- notify :failure, "No editor specified in $EDITOR environment variable"
26
+ notify :warning, "No editor specified in $EDITOR environment variable"
36
27
  notify :info, "Displaying file contents instead"
37
28
  system 'cat', file
38
29
  end
39
30
  end
40
31
 
41
- def create_and_edit(file, with_default: '')
32
+ def create(file, with_contents: '')
42
33
  file = File.expand_path file
43
- FileUtils.mkdir_p File.dirname(file)
44
- unless File.file?(file)
45
- File.write file, with_default
34
+ if File.file?(file)
35
+ notify :info, "'#{file}' already exists"
36
+ else
37
+ FileUtils.mkdir_p File.dirname(file)
38
+ File.write file, with_contents
46
39
  notify :success, "Created new file '#{file}'"
47
40
  end
48
- edit file
49
41
  end
@@ -0,0 +1,16 @@
1
+ require_relative '../config'
2
+
3
+ def default_config
4
+ File.read "#{__dir__}/../../../config.defaults.yaml"
5
+ end
6
+
7
+ def get_config_path(for_scope: 'local')
8
+ case for_scope
9
+ when 'system'
10
+ "/etc/robot_sweatshop/config.yaml"
11
+ when 'user'
12
+ "~/.robot_sweatshop/config.yaml"
13
+ else
14
+ ".robot_sweatshop/config.yaml"
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../config'
2
+
3
+ def default_job
4
+ "---\nbranch_whitelist:\n- master\n\ncommands:\n- echo 'Hello $WORLD!'\n\nenvironment:\n WORLD: Earth\n"
5
+ end
6
+
7
+ def get_job_path(for_job: nil)
8
+ "#{configatron.job_directory}/#{for_job}.yaml"
9
+ end
10
+
11
+ def list_jobs
12
+ job_directory = File.expand_path configatron.job_directory
13
+ puts Dir.glob("#{job_directory}/*.yaml").map { |file| File.basename(file, '.yaml') }
14
+ end
@@ -0,0 +1,25 @@
1
+ require 'yaml'
2
+ require_relative '../config'
3
+
4
+ def store_config_for_eye
5
+ config = configatron.to_h
6
+ config = config.each do |key, value|
7
+ config[key] = File.expand_path value if key.to_s.match /_directory/
8
+ end
9
+ config[:working_directory] = Dir.pwd
10
+ File.write('/tmp/.robot_sweatshop-eye-config.yaml', config.to_yaml)
11
+ end
12
+
13
+ def start_sweatshop(for_environment:)
14
+ store_config_for_eye
15
+ eye_config = File.expand_path "#{__dir__}/../../../robot_sweatshop.#{for_environment}.eye"
16
+ output = `eye load #{eye_config}`
17
+ if $?.exitstatus != 0
18
+ notify :failure, output
19
+ exit 1
20
+ else
21
+ notify :success, "Robot Sweatshop loaded with a #{for_environment} configuration"
22
+ notify :info, `eye restart robot_sweatshop`
23
+ notify :info, 'Run \'eye --help\' for more info on debugging'
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ require 'configatron'
2
+ require 'yaml'
3
+
4
+ configatron.reset!
5
+
6
+ configurations = [
7
+ "#{__dir__}/../../config.defaults.yaml",
8
+ "/etc/robot_sweatshop/config.yaml",
9
+ "~/.robot_sweatshop/config.yaml",
10
+ ".robot_sweatshop/config.yaml",
11
+ ]
12
+
13
+ configurations.each do |config_path|
14
+ config_path = File.expand_path config_path
15
+ if File.file? config_path
16
+ hash = YAML.load_file config_path
17
+ configatron.configure_from_hash hash
18
+ end
19
+ end
@@ -0,0 +1,29 @@
1
+ require 'fileutils'
2
+ require_relative 'config'
3
+
4
+ def set_dir_permissions(for_path:)
5
+ user = configatron.user
6
+ group = configatron.has_key?(:group) ? configatron.group : 'nogroup'
7
+ begin
8
+ FileUtils.chown_R user, group, for_path unless user.nil?
9
+ rescue ArgumentError
10
+ puts "Could not set permissions for '#{for_path}'"
11
+ end
12
+ end
13
+
14
+ def create_path(path)
15
+ begin
16
+ FileUtils.mkdir_p path
17
+ rescue Errno::EACCES
18
+ puts "Permission denied to create '#{path}'"
19
+ end
20
+ end
21
+
22
+ config = configatron.to_h
23
+ config.each do |key, value|
24
+ if key.to_s.match /_directory/
25
+ path = File.expand_path value
26
+ create_path path
27
+ set_dir_permissions for_path: path if configatron.has_key? :user
28
+ end
29
+ end
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'moneta'
3
- require_relative '../../../config'
3
+ require_relative 'config'
4
4
 
5
5
  # A class to handle queueing through Moneta's key-value storage
6
6
  class MonetaQueue
7
7
  attr_reader :watched_queues
8
8
 
9
- @@store = Moneta.new :File, dir: configatron.queue.moneta_directory
9
+ @@store = Moneta.new :File, dir: File.expand_path(configatron.moneta_directory)
10
10
 
11
11
  def initialize(name)
12
12
  @name = name
File without changes
File without changes
File without changes
File without changes
data/lib/sweatshop.rb ADDED
@@ -0,0 +1,16 @@
1
+ require_relative 'sweatshop/moneta-queue'
2
+ require_relative 'sweatshop/queue-helper'
3
+ require_relative 'sweatshop/config'
4
+
5
+ require_relative 'sweatshop/payload/payload'
6
+ require_relative 'sweatshop/payload/bitbucket'
7
+ require_relative 'sweatshop/payload/github'
8
+
9
+ require_relative 'sweatshop/cli/common'
10
+ require_relative 'sweatshop/cli/config'
11
+ require_relative 'sweatshop/cli/inspect'
12
+ require_relative 'sweatshop/cli/job'
13
+ require_relative 'sweatshop/cli/setup'
14
+ require_relative 'sweatshop/cli/start'
15
+
16
+
data/robot_sweatshop.eye CHANGED
@@ -1,60 +1,60 @@
1
- #!/usr/bin/env ruby
2
- require_relative 'config'
1
+ require 'yaml'
3
2
 
4
- log_path = configatron.common.logfile_directory
5
- pid_path = configatron.common.pidfile_directory
3
+ CONFIG = YAML.load_file '/tmp/.robot_sweatshop-eye-config.yaml'
4
+ PID_PATH = CONFIG[:pidfile_directory]
5
+ LOG_PATH = CONFIG[:logfile_directory]
6
6
 
7
7
  Eye.config do
8
- logger "#{log_path}/eye.log"
8
+ logger CONFIG[:log_file]
9
9
  end
10
10
 
11
11
  Eye.application :robot_sweatshop do
12
12
  trigger :flapping, times: 10, within: 1.minute, retry_in: 10.minutes
13
13
  check :cpu, every: 10.seconds, below: 100, times: 3
14
- working_dir "#{__dir__}/lib"
15
- uid "#{configatron.common.user}"
16
- gid "#{configatron.common.group}"
14
+ working_dir CONFIG[:working_directory]
15
+ uid "#{CONFIG[:user]}" if CONFIG[:user]
16
+ gid "#{CONFIG[:group]}" if CONFIG[:group]
17
17
 
18
18
  group 'input' do
19
19
  process :http do
20
- pid_file "#{pid_path}/input-http.pid"
21
- stdall "#{log_path}/input-http.log"
22
- start_command "ruby input/http.rb"
20
+ pid_file "#{PID_PATH}/input-http.pid"
21
+ stdall "#{LOG_PATH}/input-http.log"
22
+ start_command "#{__dir__}/bin/sweatshop-input-http"
23
23
  daemonize true
24
24
  end
25
25
  end
26
26
  group 'queue' do
27
27
  process :handler do
28
- pid_file "#{pid_path}/queue-handler.pid"
29
- stdall "#{log_path}/queue-handler.log"
30
- start_command "ruby queue/handler.rb"
28
+ pid_file "#{PID_PATH}/queue-handler.pid"
29
+ stdall "#{LOG_PATH}/queue-handler.log"
30
+ start_command "#{__dir__}/bin/sweatshop-queue-handler"
31
31
  daemonize true
32
32
  end
33
33
  process :broadcaster do
34
- pid_file "#{pid_path}/queue-broadcaster.pid"
35
- stdall "#{log_path}/queue-broadcaster.log"
36
- start_command "ruby queue/broadcaster.rb #{configatron.eye.broadcaster_interval}"
34
+ pid_file "#{PID_PATH}/queue-broadcaster.pid"
35
+ stdall "#{LOG_PATH}/queue-broadcaster.log"
36
+ start_command "#{__dir__}/bin/sweatshop-queue-broadcaster #{configatron.eye.broadcaster_interval}"
37
37
  daemonize true
38
38
  end
39
39
  end
40
40
  group 'job' do
41
41
  process :assembler do
42
- pid_file "#{pid_path}/job-assembler.pid"
43
- stdall "#{log_path}/job-assembler.log"
44
- start_command "ruby job/assembler.rb"
42
+ pid_file "#{PID_PATH}/job-assembler.pid"
43
+ stdall "#{LOG_PATH}/job-assembler.log"
44
+ start_command "#{__dir__}/bin/sweatshop-job-assembler"
45
45
  daemonize true
46
46
  end
47
47
  process :worker do
48
- pid_file "#{pid_path}/job-worker.pid"
49
- stdall "#{log_path}/job-worker.log"
50
- start_command "ruby job/worker.rb #{configatron.eye.worker_id}"
48
+ pid_file "#{PID_PATH}/job-worker.pid"
49
+ stdall "#{LOG_PATH}/job-worker.log"
50
+ start_command "#{__dir__}/bin/sweatshop-job-worker #{configatron.eye.worker_id}"
51
51
  daemonize true
52
52
  end
53
53
  end
54
54
  process :payload_parser do
55
- pid_file "#{pid_path}/payload_parser.pid"
56
- stdall "#{log_path}/payload_parser.log"
57
- start_command "ruby payload/parser.rb"
55
+ pid_file "#{PID_PATH}/payload_parser.pid"
56
+ stdall "#{LOG_PATH}/payload_parser.log"
57
+ start_command "#{__dir__}/bin/sweatshop-payload-parser"
58
58
  daemonize true
59
59
  end
60
60
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = 'robot_sweatshop'
3
- gem.version = '0.1.6'
3
+ gem.version = '0.2.0'
4
4
  gem.licenses = 'MIT'
5
5
  gem.authors = ['Justin Scott']
6
6
  gem.email = 'jvscott@gmail.com'
@@ -10,7 +10,8 @@ Gem::Specification.new do |gem|
10
10
 
11
11
  gem.files = `git ls-files`.split("\n")
12
12
  gem.test_files = `git ls-files -- kintama/**/*`.split("\n")
13
- gem.executables = `git ls-files -- bin/sweatshop`.split("\n").map { |f| File.basename(f) }
13
+ gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
14
+ gem.require_paths = ['lib']
14
15
 
15
16
  gem.required_ruby_version = '>= 2.1'
16
17
 
@@ -26,4 +27,6 @@ Gem::Specification.new do |gem|
26
27
  gem.add_development_dependency 'rake'
27
28
  gem.add_development_dependency 'kintama'
28
29
  gem.add_development_dependency 'http'
30
+ gem.add_development_dependency 'pry'
31
+ gem.add_development_dependency 'pry-byebug'
29
32
  end
@@ -1,8 +1,7 @@
1
- #!/usr/bin/env ruby
2
- Eye.load('./config.rb')
1
+ require 'configatron'
3
2
 
4
3
  configatron.temp do
5
4
  configatron.eye.broadcaster_interval = ''
6
5
  configatron.eye.worker_id = ''
7
- Eye.load('./robot_sweatshop.eye')
6
+ Eye.load('robot_sweatshop.eye')
8
7
  end
@@ -1,8 +1,7 @@
1
- #!/usr/bin/env ruby
2
- Eye.load('./config.rb')
1
+ require 'configatron'
3
2
 
4
3
  configatron.temp do
5
4
  configatron.eye.broadcaster_interval = 0.0
6
5
  configatron.eye.worker_id = 'testingid'
7
- Eye.load('./robot_sweatshop.eye')
6
+ Eye.load('robot_sweatshop.eye')
8
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: robot_sweatshop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Scott
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-02 00:00:00.000000000 Z
11
+ date: 2015-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -164,10 +164,45 @@ dependencies:
164
164
  - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: pry
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: pry-byebug
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
167
195
  description: A lightweight, unopinionated CI server.
168
196
  email: jvscott@gmail.com
169
197
  executables:
170
198
  - sweatshop
199
+ - sweatshop-input-http
200
+ - sweatshop-job-assembler
201
+ - sweatshop-job-worker
202
+ - sweatshop-payload-parser
203
+ - sweatshop-queue-broadcaster
204
+ - sweatshop-queue-handler
205
+ - sweatshop-queue-watcher
171
206
  extensions: []
172
207
  extra_rdoc_files: []
173
208
  files:
@@ -177,18 +212,18 @@ files:
177
212
  - LICENSE
178
213
  - README.md
179
214
  - Rakefile
180
- - bin/lib/common.rb
181
- - bin/lib/config.rb
182
- - bin/lib/inspect.rb
183
- - bin/lib/job.rb
184
- - bin/lib/setup.rb
185
- - bin/lib/start.rb
186
215
  - bin/sweatshop
187
- - config.rb
188
- - config.yaml
189
- - jobs/example.yaml
216
+ - bin/sweatshop-input-http
217
+ - bin/sweatshop-job-assembler
218
+ - bin/sweatshop-job-worker
219
+ - bin/sweatshop-payload-parser
220
+ - bin/sweatshop-queue-broadcaster
221
+ - bin/sweatshop-queue-handler
222
+ - bin/sweatshop-queue-watcher
223
+ - config.defaults.yaml
190
224
  - kintama/README.md
191
225
  - kintama/data/payload_data.yaml
226
+ - kintama/data/test_job.yaml
192
227
  - kintama/end-to-end_spec.rb
193
228
  - kintama/input_http_spec.rb
194
229
  - kintama/job_assembler_spec.rb
@@ -201,18 +236,18 @@ files:
201
236
  - kintama/shared/helpers.rb
202
237
  - kintama/shared/process_spawning.rb
203
238
  - lib/README.md
204
- - lib/input/http.rb
205
- - lib/job/assembler.rb
206
- - lib/job/worker.rb
207
- - lib/payload/lib/bitbucket.rb
208
- - lib/payload/lib/github.rb
209
- - lib/payload/lib/payload.rb
210
- - lib/payload/parser.rb
211
- - lib/queue-helper.rb
212
- - lib/queue/broadcaster.rb
213
- - lib/queue/handler.rb
214
- - lib/queue/lib/moneta-queue.rb
215
- - lib/queue/watcher.rb
239
+ - lib/sweatshop.rb
240
+ - lib/sweatshop/cli/common.rb
241
+ - lib/sweatshop/cli/config.rb
242
+ - lib/sweatshop/cli/job.rb
243
+ - lib/sweatshop/cli/start.rb
244
+ - lib/sweatshop/config.rb
245
+ - lib/sweatshop/create-config-directories.rb
246
+ - lib/sweatshop/moneta-queue.rb
247
+ - lib/sweatshop/payload/bitbucket.rb
248
+ - lib/sweatshop/payload/github.rb
249
+ - lib/sweatshop/payload/payload.rb
250
+ - lib/sweatshop/queue-helper.rb
216
251
  - robot_sweatshop.eye
217
252
  - robot_sweatshop.gemspec
218
253
  - robot_sweatshop.production.eye
@@ -243,5 +278,6 @@ specification_version: 4
243
278
  summary: Robot Sweatshop
244
279
  test_files:
245
280
  - kintama/data/payload_data.yaml
281
+ - kintama/data/test_job.yaml
246
282
  - kintama/shared/helpers.rb
247
283
  - kintama/shared/process_spawning.rb
data/bin/lib/config.rb DELETED
@@ -1,20 +0,0 @@
1
- require 'yaml'
2
- require 'fileutils'
3
- require_relative '../../config'
4
-
5
- def default_config
6
- File.read "#{__dir__}/../../config.yaml"
7
- end
8
-
9
- def user_config_file
10
- '/etc/robot_sweatshop/config.yaml'
11
- end
12
-
13
- def remove_user_config
14
- FileUtils.rm_rf user_config_file
15
- notify :success, 'Removing current user config file'
16
- end
17
-
18
- def create_and_edit_user_config
19
- create_and_edit user_config_file, with_default: default_config
20
- end
data/bin/lib/inspect.rb DELETED
@@ -1,42 +0,0 @@
1
- def valid_lists?(job)
2
- errors = false
3
- %w(branch_whitelist commands).each do |list|
4
- if job[list].nil? || job[list].empty?
5
- notify :failure, "#{list} empty or not found"
6
- errors = true
7
- end
8
- end
9
- errors
10
- end
11
-
12
- def valid_environment?(job)
13
- errors = false
14
- job['environment'].each do |key, value|
15
- unless value.is_a? String
16
- notify :warning, "Non-string value for '#{key}'"
17
- errors = true
18
- end
19
- end
20
- errors
21
- end
22
-
23
- def valid_yaml?(job)
24
- if job
25
- true
26
- else
27
- notify :failure, "Invalid YAML"
28
- false
29
- end
30
- end
31
-
32
- def validate(job_file)
33
- unless File.file?(job_file)
34
- notify :failure, 'Job not found. Create it with \'workshop job\''
35
- else
36
- job = YAML.load_file job_file
37
- return unless valid_yaml?(job)
38
- errors = valid_lists?(job) |
39
- valid_environment?(job)
40
- notify :success, 'Valid job configuration' unless errors
41
- end
42
- end
data/bin/lib/job.rb DELETED
@@ -1,13 +0,0 @@
1
- require_relative 'common'
2
-
3
- def empty_job
4
- "---\nbranch_whitelist:\n- master\n\ncommands:\n- echo 'Hello $WORLD!'\n\nenvironment:\n WORLD: Earth\n"
5
- end
6
-
7
- def create_and_edit_job(job_path)
8
- create_and_edit job_path, with_default: empty_job
9
- end
10
-
11
- def list_jobs
12
- puts Dir.glob("#{__dir__}/../../jobs/*").map { |file| File.basename(file, '.yaml') }
13
- end
data/bin/lib/setup.rb DELETED
@@ -1,25 +0,0 @@
1
- require 'fileutils'
2
- require 'configatron'
3
- require_relative 'common'
4
- require_relative '../../config'
5
-
6
- config_directories = [
7
- configatron.common.logfile_directory,
8
- configatron.common.pidfile_directory,
9
- configatron.common.user_config_directory,
10
- configatron.queue.moneta_directory,
11
- configatron.assembler.job_directory,
12
- configatron.worker.workspace_directory
13
- ]
14
- config_directories.each do |directory|
15
- user = configatron.common.user
16
- group = configatron.common.group
17
- if Dir.exists? directory
18
- notify :info, "'#{directory}' already exists"
19
- else
20
- FileUtils.mkdir_p directory
21
- notify :success, "Created '#{directory}' and set owner as #{user}:#{group}"
22
- end
23
- FileUtils.chown_R user, group, directory
24
- notify :success, "Recursively set owner of '#{directory}' as #{user}:#{group}\n\n"
25
- end
data/bin/lib/start.rb DELETED
@@ -1,11 +0,0 @@
1
- def start_sweatshop(for_environment:)
2
- eye_config = "#{__dir__}/../../robot_sweatshop.#{for_environment}.eye"
3
- output = `eye load #{eye_config}`
4
- if $?.exitstatus != 0
5
- notify :failure, output
6
- else
7
- notify :success, "Robot Sweatshop loaded with a #{for_environment} configuration"
8
- notify :info, `eye restart robot_sweatshop`
9
- puts 'Check \'eye --help\' for more info on debugging'
10
- end
11
- end
data/config.rb DELETED
@@ -1,16 +0,0 @@
1
- require 'configatron'
2
- require 'yaml'
3
-
4
- # TODO: namespace to avoid collisions?
5
-
6
- configurations = [
7
- "#{__dir__}/config.yaml",
8
- "#{__dir__}/config.user.yaml",
9
- "/etc/robot_sweatshop/config.yaml"
10
- ]
11
- configurations.each do |config_path|
12
- if File.file? config_path
13
- hash = YAML.load_file config_path
14
- configatron.configure_from_hash hash
15
- end
16
- end
data/config.yaml DELETED
@@ -1,20 +0,0 @@
1
- common:
2
- pidfile_directory: /var/run/robot_sweatshop
3
- logfile_directory: /var/log/robot_sweatshop
4
- user_config_directory: /etc/robot_sweatshop
5
- user: jscott
6
- group: nogroup
7
-
8
- input:
9
- http:
10
- port: 8080
11
- bind: 0.0.0.0
12
-
13
- queue:
14
- moneta_directory: /var/db/robot_sweatshop
15
-
16
- assembler:
17
- job_directory: /etc/robot_sweatshop/jobs
18
-
19
- worker:
20
- workspace_directory: /etc/robot_sweatshop/workspaces