robot_sweatshop 0.4.7 → 0.4.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +9 -3
- data/README.md +18 -9
- data/Rakefile +9 -1
- data/bin/sweatshop +1 -1
- data/bin/sweatshop-input +2 -2
- data/bin/sweatshop-overseer +24 -0
- data/bin/sweatshop-worker +22 -9
- data/config.defaults.yaml +6 -5
- data/docs/README.md +6 -0
- data/docs/architecture.dot +8 -3
- data/docs/architecture.gif +0 -0
- data/lib/robot_sweatshop/cli/job.rb +1 -10
- data/lib/robot_sweatshop/overseer.rb +35 -0
- data/lib/robot_sweatshop/templates/default_job.yaml +9 -0
- data/lib/robot_sweatshop/templates/index.html.eruby +45 -0
- data/lib/robot_sweatshop/templates/log.html.eruby +14 -0
- data/lib/robot_sweatshop.rb +1 -0
- data/robot_sweatshop.eye +6 -0
- data/robot_sweatshop.gemspec +3 -1
- data/test/all.rb +13 -3
- data/test/overseer_spec.rb +50 -0
- data/test/shared/helpers/input.rb +11 -2
- data/test/shared/helpers/overseer.rb +8 -0
- data/test/shared/helpers.rb +2 -1
- data/test/worker_spec.rb +4 -0
- metadata +39 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0117fcc7d8e0d91f24a08a46a8b7e24f4cd0b65b
|
4
|
+
data.tar.gz: e01c0e51398d698e8dc4d7a56f53c77fb35955e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1255a647775979d5da1d5fb2be512e23af38979b6aba58dd37906c45e1da4f25a34d72d0b31e48a13a50f2e08b8661b2da611c1bbb76ce98ffde092e8490599a
|
7
|
+
data.tar.gz: 8dda97b15749001ff014e0500bf37663cffad1201d1f91066f057068b68fc752913b87ff638aa67e0386541c075def54d4c8f8e305ff7433e9382e4eda658698
|
data/Gemfile.lock
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
robot_sweatshop (0.4.
|
4
|
+
robot_sweatshop (0.4.8)
|
5
5
|
bundler
|
6
6
|
commander
|
7
7
|
configatron
|
8
8
|
contracts
|
9
|
+
erubis
|
9
10
|
exponential-backoff
|
10
11
|
eye
|
11
12
|
ezmq
|
@@ -33,6 +34,7 @@ GEM
|
|
33
34
|
docile (1.1.5)
|
34
35
|
domain_name (0.5.24)
|
35
36
|
unf (>= 0.0.5, < 1.0.0)
|
37
|
+
erubis (2.7.0)
|
36
38
|
exponential-backoff (0.0.2)
|
37
39
|
eye (0.6.4)
|
38
40
|
celluloid (~> 0.15.0)
|
@@ -44,7 +46,7 @@ GEM
|
|
44
46
|
ffi-rzmq (~> 2.0)
|
45
47
|
faker (1.4.3)
|
46
48
|
i18n (~> 0.5)
|
47
|
-
ffi (1.9.
|
49
|
+
ffi (1.9.9)
|
48
50
|
ffi-rzmq (2.0.4)
|
49
51
|
ffi-rzmq-core (>= 1.0.1)
|
50
52
|
ffi-rzmq-core (1.0.3)
|
@@ -62,10 +64,13 @@ GEM
|
|
62
64
|
i18n (0.7.0)
|
63
65
|
json (1.8.3)
|
64
66
|
kintama (0.1.13)
|
67
|
+
mini_portile (0.6.2)
|
65
68
|
moneta (0.8.0)
|
66
69
|
nio4r (1.1.0)
|
70
|
+
nokogiri (1.6.6.2)
|
71
|
+
mini_portile (~> 0.6.0)
|
67
72
|
oj (2.12.9)
|
68
|
-
rack (1.6.
|
73
|
+
rack (1.6.4)
|
69
74
|
rack-protection (1.5.3)
|
70
75
|
rack
|
71
76
|
rainbow (2.0.0)
|
@@ -106,6 +111,7 @@ PLATFORMS
|
|
106
111
|
DEPENDENCIES
|
107
112
|
http
|
108
113
|
kintama
|
114
|
+
nokogiri
|
109
115
|
rake
|
110
116
|
robot_sweatshop!
|
111
117
|
simplecov
|
data/README.md
CHANGED
@@ -6,44 +6,53 @@
|
|
6
6
|
|
7
7
|
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.
|
8
8
|
|
9
|
-
|
9
|
+
## Quick start
|
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
13
|
- `sweatshop start`
|
14
14
|
- `sweatshop job example --auto`
|
15
|
-
- `curl -d '' localhost:
|
16
|
-
- `cat .robot_sweatshop/log/
|
15
|
+
- `curl -d '' localhost:10555/run/example`
|
16
|
+
- `cat .robot_sweatshop/log/worker.log`
|
17
17
|
|
18
|
-
|
18
|
+
## Usage
|
19
19
|
|
20
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
|
+
Oh yeah, and there's a front end in case you want to run and watch jobs without using a console. By default it runs on port 10554.
|
25
|
+
|
26
|
+
## The implicit job
|
27
|
+
|
28
|
+
Just like Travis-CI will look for `.travis.yml`, Robot Sweatshop will look for `.robot_sweatshop.yaml` at the end of a job and run the job within immediately after. See [the wiki](https://github.com/JScott/robot_sweatshop/wiki/Implicit-jobs) for more details on how you might utilize this.
|
29
|
+
|
30
|
+
This is useful because it allows you to have a more centralized source of truth for building and testing your code. You can set up your canonical testing definition in your repository and have it pulled down for any server that runs it.
|
31
|
+
|
32
|
+
## Configuration
|
25
33
|
|
26
34
|
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
35
|
|
28
|
-
|
36
|
+
## Supported payload formats
|
29
37
|
|
30
38
|
- Github (application/json format only)
|
31
39
|
- Bitbucket
|
32
40
|
- JSON
|
33
41
|
- Empty
|
34
42
|
|
35
|
-
|
43
|
+
## Security
|
36
44
|
|
37
45
|
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
46
|
|
39
|
-
|
47
|
+
## Roadmap
|
40
48
|
|
41
49
|
1.0
|
42
50
|
|
43
|
-
- Mascot
|
51
|
+
- Mascot/logo
|
44
52
|
|
45
53
|
1.1
|
46
54
|
|
55
|
+
- Use something appropriate than TCP for ZMQ connections
|
47
56
|
- Easier way to run multiple workers
|
48
57
|
- Push/pull out node that worker streams output to
|
49
58
|
- Add worker tags to output so it can all go to one file
|
data/Rakefile
CHANGED
@@ -1,5 +1,13 @@
|
|
1
|
-
require '
|
1
|
+
require 'terminal-announce'
|
2
|
+
require 'rake'
|
2
3
|
|
3
4
|
task :test do
|
4
5
|
require_relative 'test/all'
|
5
6
|
end
|
7
|
+
|
8
|
+
task :build do
|
9
|
+
Announce.info 'Building and installing local gem...'
|
10
|
+
puts `rm -rf robot_sweatshop-*.gem`
|
11
|
+
puts `gem build robot_sweatshop.gemspec --force`
|
12
|
+
puts `gem install robot_sweatshop-*.gem`
|
13
|
+
end
|
data/bin/sweatshop
CHANGED
@@ -7,7 +7,7 @@ require 'robot_sweatshop/config'
|
|
7
7
|
require 'robot_sweatshop/create-config-directories'
|
8
8
|
|
9
9
|
program :name, 'Robot Sweatshop'
|
10
|
-
program :version, '0.4.
|
10
|
+
program :version, '0.4.9'
|
11
11
|
program :description, 'A lightweight, nonopinionated CI server'
|
12
12
|
program :help, 'Author', 'Justin Scott <jvscott@gmail.com>'
|
13
13
|
|
data/bin/sweatshop-input
CHANGED
@@ -7,7 +7,7 @@ require 'robot_sweatshop/connections'
|
|
7
7
|
using ExtendedEZMQ
|
8
8
|
|
9
9
|
configure do
|
10
|
-
set :port, configatron.
|
10
|
+
set :port, configatron.input_port
|
11
11
|
set :bind, configatron.http_bind
|
12
12
|
set :run, true
|
13
13
|
set :conveyor, EZMQ::Client.new(port: configatron.conveyor_port)
|
@@ -16,7 +16,7 @@ configure do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
get '/' do
|
19
|
-
'
|
19
|
+
'Usage: POST /run/<job-name>'
|
20
20
|
end
|
21
21
|
|
22
22
|
post '/run/:job_name' do
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'sinatra'
|
3
|
+
require 'sinatra/cross_origin'
|
4
|
+
require 'robot_sweatshop/config'
|
5
|
+
require 'robot_sweatshop/overseer'
|
6
|
+
|
7
|
+
helpers OverseerHelper
|
8
|
+
|
9
|
+
configure do
|
10
|
+
set :port, configatron.overseer_port
|
11
|
+
set :bind, configatron.http_bind
|
12
|
+
set :run, true
|
13
|
+
enable :cross_origin if configatron.http_cross_origin
|
14
|
+
end
|
15
|
+
|
16
|
+
get '/' do
|
17
|
+
frontpage
|
18
|
+
end
|
19
|
+
|
20
|
+
get '/log' do
|
21
|
+
redirect to('/'), 303 if params[:for].nil?
|
22
|
+
process = params[:for]
|
23
|
+
log_page_for process
|
24
|
+
end
|
data/bin/sweatshop-worker
CHANGED
@@ -27,19 +27,19 @@ def ensure_shell_for(command)
|
|
27
27
|
"#{command};"
|
28
28
|
end
|
29
29
|
|
30
|
-
Contract
|
31
|
-
def
|
30
|
+
Contract String, Hash => Maybe[IO]
|
31
|
+
def stream(command, with_context:)
|
32
32
|
command = ensure_shell_for command
|
33
|
-
IO.popen(
|
34
|
-
puts stream.gets until stream.eof?
|
33
|
+
IO.popen(with_context, command) do |stream|
|
34
|
+
puts stream.gets until stream.eof?
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
Contract
|
39
|
-
def execute(
|
38
|
+
Contract String, Hash => nil
|
39
|
+
def execute(command, context)
|
40
40
|
puts "Executing '#{command}'"
|
41
41
|
begin
|
42
|
-
|
42
|
+
stream command, with_context: context
|
43
43
|
rescue Errno::ENOENT => error
|
44
44
|
puts error.message
|
45
45
|
end
|
@@ -52,6 +52,19 @@ def finish(id)
|
|
52
52
|
puts "Job finished.\n\n"
|
53
53
|
end
|
54
54
|
|
55
|
+
Contract Array, Hash => Any
|
56
|
+
def run(commands, with_context: {})
|
57
|
+
commands.each { |command| execute command, with_context }
|
58
|
+
end
|
59
|
+
|
60
|
+
Contract None => Any
|
61
|
+
def run_implicit_job
|
62
|
+
implicit_job_file = '.robot_sweatshop.yaml'
|
63
|
+
return unless File.exist? implicit_job_file
|
64
|
+
implicit_job = YAML.load_file implicit_job_file
|
65
|
+
run implicit_job['commands'], with_context: implicit_job['environment']
|
66
|
+
end
|
67
|
+
|
55
68
|
puts 'Starting'
|
56
69
|
@sockets = {
|
57
70
|
conveyor: EZMQ::Client.new(port: configatron.conveyor_port),
|
@@ -62,8 +75,8 @@ puts 'Starting'
|
|
62
75
|
@sockets[:puller].listen do |data|
|
63
76
|
puts "Running: #{data}"
|
64
77
|
from_workspace named: data[:job_name] do
|
65
|
-
|
66
|
-
|
78
|
+
run data[:commands], with_context: data[:context]
|
79
|
+
run_implicit_job
|
67
80
|
end
|
68
81
|
finish data[:job_id]
|
69
82
|
end
|
data/config.defaults.yaml
CHANGED
@@ -5,11 +5,12 @@ job_path: .robot_sweatshop/jobs
|
|
5
5
|
workspace_path: .robot_sweatshop/workspaces
|
6
6
|
database_path: .robot_sweatshop/db
|
7
7
|
scripts_path: .robot_sweatshop/scripts
|
8
|
-
http_port: 8080
|
9
8
|
http_bind: 0.0.0.0
|
10
9
|
http_cross_origin: true
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
overseer_port: 10554
|
11
|
+
input_port: 10555
|
12
|
+
conveyor_port: 10556
|
13
|
+
payload_parser_port: 10557
|
14
|
+
job_dictionary_port: 10558
|
15
|
+
worker_port: 10559
|
15
16
|
job_timeout_length: 300 # 5 minutes
|
data/docs/README.md
CHANGED
data/docs/architecture.dot
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
digraph architecture {
|
2
|
-
label="Robot Sweatshop
|
2
|
+
label="Robot Sweatshop process interaction"
|
3
3
|
labelloc="top"
|
4
4
|
|
5
|
+
O [label="Overseer",shape=box]
|
5
6
|
I [label="Input"]
|
6
7
|
A [label="Assembler"]
|
7
8
|
W [label="Worker"]
|
8
|
-
subgraph
|
9
|
+
subgraph cluster_services {
|
9
10
|
label="Req/Rep Services"
|
10
11
|
labelloc="bottom"
|
11
12
|
style="dashed"
|
@@ -14,9 +15,13 @@ digraph architecture {
|
|
14
15
|
D [label="Job Dictionary"]
|
15
16
|
}
|
16
17
|
|
17
|
-
I
|
18
|
+
O->I
|
19
|
+
I->C
|
18
20
|
A->C [dir="both"]
|
19
21
|
A->P [dir="both"]
|
20
22
|
A->D [dir="both"]
|
21
23
|
A->W [headlabel="1..*",labeldistance=2]
|
24
|
+
W->C
|
25
|
+
|
26
|
+
{ rank=same; I W A }
|
22
27
|
}
|
data/docs/architecture.gif
CHANGED
Binary file
|
@@ -4,16 +4,7 @@ module CLI
|
|
4
4
|
# Methods for creating and editing jobs
|
5
5
|
module Job
|
6
6
|
def self.default
|
7
|
-
"
|
8
|
-
# branch_whitelist:
|
9
|
-
# - master
|
10
|
-
|
11
|
-
commands:
|
12
|
-
- echo \"Hello $WORLD!\"
|
13
|
-
|
14
|
-
environment:
|
15
|
-
WORLD: Earth
|
16
|
-
"
|
7
|
+
File.read "#{__dir__}/../templates/default_job.yaml"
|
17
8
|
end
|
18
9
|
|
19
10
|
def self.path_for(job)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'erubis'
|
2
|
+
|
3
|
+
# Helper methods for the Overseer Sinatra server
|
4
|
+
module OverseerHelper
|
5
|
+
def log_list
|
6
|
+
%w(assembler conveyor input job-dictionary payload-parser worker)
|
7
|
+
end
|
8
|
+
|
9
|
+
def job_list
|
10
|
+
log_path = File.expand_path "#{configatron.job_path}"
|
11
|
+
p log_path, Dir.glob("#{log_path}/*.yaml")
|
12
|
+
Dir.glob("#{log_path}/*.yaml").map { |path| File.basename path, '.yaml' }
|
13
|
+
end
|
14
|
+
|
15
|
+
def frontpage
|
16
|
+
context = {
|
17
|
+
jobs: job_list,
|
18
|
+
logs: log_list,
|
19
|
+
input_port: configatron.input_port
|
20
|
+
}
|
21
|
+
template = File.read "#{__dir__}/templates/index.html.eruby"
|
22
|
+
eruby = Erubis::Eruby.new template
|
23
|
+
eruby.result context
|
24
|
+
end
|
25
|
+
|
26
|
+
def log_page_for(process)
|
27
|
+
context = {
|
28
|
+
process: process,
|
29
|
+
raw_log: File.read("#{configatron.logfile_path}/#{process}.log")
|
30
|
+
}
|
31
|
+
template = File.read "#{__dir__}/templates/log.html.eruby"
|
32
|
+
eruby = Erubis::Eruby.new template
|
33
|
+
eruby.result context
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8" />
|
5
|
+
<title>Robot Sweatshop</title>
|
6
|
+
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
|
7
|
+
<script>
|
8
|
+
var QueueJob = function() {
|
9
|
+
var job = $('select#job').val();
|
10
|
+
var data = $('textarea#data').val();
|
11
|
+
console.log("http://localhost:<%= input_port %>/run/"+job);
|
12
|
+
$.post("http://localhost:<%= input_port %>/run/"+job, data);
|
13
|
+
}
|
14
|
+
</script>
|
15
|
+
<style>
|
16
|
+
button { background-color: #00db00; padding: 10px 20px; font-size: 1.2em; }
|
17
|
+
</style>
|
18
|
+
</head>
|
19
|
+
|
20
|
+
<body>
|
21
|
+
<h1>Robot Sweatshop</h1>
|
22
|
+
|
23
|
+
<h2>Big Green Button</h2>
|
24
|
+
<form class="job_runner">
|
25
|
+
<label for="job">Select job</label>
|
26
|
+
<select id="job">
|
27
|
+
<% for job in jobs %>
|
28
|
+
<option value="<%= job %>"><%= job %></option>
|
29
|
+
<% end %>
|
30
|
+
</select>
|
31
|
+
<br><br>
|
32
|
+
<label for="data">Data payload</label>
|
33
|
+
<textarea id="data">{}</textarea>
|
34
|
+
<br><br>
|
35
|
+
<button type="button" onclick="QueueJob()">Queue Job</button>
|
36
|
+
</form>
|
37
|
+
|
38
|
+
<h2>Logs</h2>
|
39
|
+
<ul>
|
40
|
+
<% for log in logs %>
|
41
|
+
<li><a href="/log?for=<%= log %>"><%= log %></a></li>
|
42
|
+
<% end %>
|
43
|
+
</ul>
|
44
|
+
</body>
|
45
|
+
</html>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8" />
|
5
|
+
<title>Robot Sweatshop - <%= process %> log</title>
|
6
|
+
</head>
|
7
|
+
|
8
|
+
<body>
|
9
|
+
<h1>Raw <%= process %> log</h1>
|
10
|
+
<a href="/">Back</a>
|
11
|
+
<pre class="raw_log"><%= raw_log %></pre>
|
12
|
+
<a href="#">Top</a>
|
13
|
+
</body>
|
14
|
+
</html>
|
data/lib/robot_sweatshop.rb
CHANGED
data/robot_sweatshop.eye
CHANGED
@@ -36,6 +36,12 @@ Eye.application :robot_sweatshop do
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
process :overseer do
|
40
|
+
pid_file "#{PID_PATH}/overseer.pid"
|
41
|
+
stdall "#{LOG_PATH}/overseer.log"
|
42
|
+
start_command "#{__dir__}/bin/sweatshop-overseer"
|
43
|
+
daemonize true
|
44
|
+
end
|
39
45
|
process :input do
|
40
46
|
pid_file "#{PID_PATH}/input.pid"
|
41
47
|
stdall "#{LOG_PATH}/input.log"
|
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.4.
|
3
|
+
gem.version = '0.4.9'
|
4
4
|
gem.licenses = 'MIT'
|
5
5
|
gem.authors = ['Justin Scott']
|
6
6
|
gem.email = 'jvscott@gmail.com'
|
@@ -28,9 +28,11 @@ Gem::Specification.new do |gem|
|
|
28
28
|
gem.add_runtime_dependency 'stubborn_queue'
|
29
29
|
gem.add_runtime_dependency 'oj'
|
30
30
|
gem.add_runtime_dependency 'exponential-backoff'
|
31
|
+
gem.add_runtime_dependency 'erubis'
|
31
32
|
|
32
33
|
gem.add_development_dependency 'rake'
|
33
34
|
gem.add_development_dependency 'kintama'
|
34
35
|
gem.add_development_dependency 'http'
|
35
36
|
gem.add_development_dependency 'simplecov'
|
37
|
+
gem.add_development_dependency 'nokogiri'
|
36
38
|
end
|
data/test/all.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'terminal-announce'
|
2
|
+
|
1
3
|
# Because of needing to isolate processes, I can't run all tests in one call.
|
2
4
|
# This means that I have multiple sets of results which isn't nice, but the
|
3
5
|
# tests are largely for the sake of TDD anyway.
|
@@ -23,6 +25,7 @@ tests = %w(
|
|
23
25
|
job_dictionary
|
24
26
|
assembler
|
25
27
|
worker
|
28
|
+
overseer
|
26
29
|
end-to-end
|
27
30
|
)
|
28
31
|
exit_statuses = []
|
@@ -30,6 +33,13 @@ exit_statuses = []
|
|
30
33
|
tests.each do |name|
|
31
34
|
exit_statuses.push run_test(name)
|
32
35
|
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
if non_zero(exit_statuses).empty?
|
37
|
+
Announce.success 'Everything passed'
|
38
|
+
else
|
39
|
+
failed_tests = tests.each_with_index.select do |test, index|
|
40
|
+
exit_statuses[index] != 0
|
41
|
+
end
|
42
|
+
failed_tests.map! { |test| test[0] }
|
43
|
+
Announce.failure "Tests failed: #{failed_tests.join ', '}"
|
44
|
+
exit 1
|
45
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'kintama'
|
3
|
+
require 'timeout'
|
4
|
+
require 'http'
|
5
|
+
require 'nokogiri'
|
6
|
+
require_relative 'shared/scaffolding'
|
7
|
+
require_relative 'shared/helpers'
|
8
|
+
$stdout.sync = true
|
9
|
+
|
10
|
+
Kintama.on_start do
|
11
|
+
@pids = TestProcess.start %w(overseer)
|
12
|
+
sleep $a_while
|
13
|
+
end
|
14
|
+
|
15
|
+
Kintama.on_finish do
|
16
|
+
TestProcess.stop @pids
|
17
|
+
end
|
18
|
+
|
19
|
+
given 'the Overseer' do
|
20
|
+
include OverseerHelper
|
21
|
+
|
22
|
+
context '/' do
|
23
|
+
setup { Timeout.timeout($a_while) { @response = HTTP.get overseer_url } }
|
24
|
+
should('respond') { assert_equal 200, @response.code }
|
25
|
+
should('link to process logs') do
|
26
|
+
page = Nokogiri::HTML(@response.to_s)
|
27
|
+
links = page.css('a').select { |link| link.text.include? 'worker' }
|
28
|
+
assert_not_equal 0, links.count
|
29
|
+
end
|
30
|
+
should('have a form for running jobs') do
|
31
|
+
page = Nokogiri::HTML(@response.to_s)
|
32
|
+
form = page.css('form.job_runner')
|
33
|
+
assert_not_equal 0, form.count
|
34
|
+
end
|
35
|
+
end
|
36
|
+
context '/log' do
|
37
|
+
setup { Timeout.timeout($a_while) { @response = HTTP.get overseer_url('log') } }
|
38
|
+
should('redirect') { assert_equal 303, @response.code }
|
39
|
+
end
|
40
|
+
context '/log?for=worker' do
|
41
|
+
setup { Timeout.timeout($a_while) { @response = HTTP.get overseer_url('log?for=worker') } }
|
42
|
+
should('respond') { assert_equal 200, @response.code }
|
43
|
+
should('show logs from file') do
|
44
|
+
page = Nokogiri::HTML(@response.to_s)
|
45
|
+
log = File.read "#{configatron.logfile_path}/worker.log"
|
46
|
+
output = page.css('.raw_log').first
|
47
|
+
assert_equal log, output.text, 'Expected raw log output'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -11,7 +11,7 @@ module InputHelper
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def input_url(for_job: 'test_job')
|
14
|
-
"http://localhost:#{configatron.
|
14
|
+
"http://localhost:#{configatron.input_port}/run/#{for_job}"
|
15
15
|
end
|
16
16
|
|
17
17
|
def conveyor_enqueue(type)
|
@@ -33,6 +33,14 @@ module InputHelper
|
|
33
33
|
}
|
34
34
|
end
|
35
35
|
|
36
|
+
def implicit_job
|
37
|
+
job = {
|
38
|
+
'commands' => ['echo $this >> test.txt'],
|
39
|
+
'environment' => { 'this' => 'implicit'}
|
40
|
+
}
|
41
|
+
YAML.dump job
|
42
|
+
end
|
43
|
+
|
36
44
|
def worker_push
|
37
45
|
{
|
38
46
|
commands: [
|
@@ -40,7 +48,8 @@ module InputHelper
|
|
40
48
|
'echo $custom > test.txt',
|
41
49
|
'custom_script',
|
42
50
|
'custom_script >> test.txt',
|
43
|
-
'bad command about nothing'
|
51
|
+
'bad command about nothing',
|
52
|
+
"echo '#{implicit_job}' > .robot_sweatshop.yaml"
|
44
53
|
],
|
45
54
|
context: {
|
46
55
|
'PATH' => "#{ENV['PATH']}:#{File.expand_path configatron.scripts_path}",
|
data/test/shared/helpers.rb
CHANGED
data/test/worker_spec.rb
CHANGED
@@ -56,6 +56,10 @@ describe 'the Worker' do
|
|
56
56
|
assert_match /custom/, File.read(worker_output)
|
57
57
|
end
|
58
58
|
|
59
|
+
should 'run implicit jobs' do
|
60
|
+
assert_match /implicit/, File.read(worker_output)
|
61
|
+
end
|
62
|
+
|
59
63
|
should 'tell the conveyor that job is complete' do
|
60
64
|
assert_equal 'finish', @worker_data[:method]
|
61
65
|
assert_kind_of Fixnum, @worker_data[:data]
|
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.4.
|
4
|
+
version: 0.4.9
|
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-
|
11
|
+
date: 2015-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -192,6 +192,20 @@ dependencies:
|
|
192
192
|
- - ">="
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: erubis
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :runtime
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
195
209
|
- !ruby/object:Gem::Dependency
|
196
210
|
name: rake
|
197
211
|
requirement: !ruby/object:Gem::Requirement
|
@@ -248,6 +262,20 @@ dependencies:
|
|
248
262
|
- - ">="
|
249
263
|
- !ruby/object:Gem::Version
|
250
264
|
version: '0'
|
265
|
+
- !ruby/object:Gem::Dependency
|
266
|
+
name: nokogiri
|
267
|
+
requirement: !ruby/object:Gem::Requirement
|
268
|
+
requirements:
|
269
|
+
- - ">="
|
270
|
+
- !ruby/object:Gem::Version
|
271
|
+
version: '0'
|
272
|
+
type: :development
|
273
|
+
prerelease: false
|
274
|
+
version_requirements: !ruby/object:Gem::Requirement
|
275
|
+
requirements:
|
276
|
+
- - ">="
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: '0'
|
251
279
|
description: A lightweight, nonopinionated CI server.
|
252
280
|
email: jvscott@gmail.com
|
253
281
|
executables:
|
@@ -256,6 +284,7 @@ executables:
|
|
256
284
|
- sweatshop-conveyor
|
257
285
|
- sweatshop-input
|
258
286
|
- sweatshop-job-dictionary
|
287
|
+
- sweatshop-overseer
|
259
288
|
- sweatshop-payload-parser
|
260
289
|
- sweatshop-worker
|
261
290
|
extensions: []
|
@@ -273,6 +302,7 @@ files:
|
|
273
302
|
- bin/sweatshop-conveyor
|
274
303
|
- bin/sweatshop-input
|
275
304
|
- bin/sweatshop-job-dictionary
|
305
|
+
- bin/sweatshop-overseer
|
276
306
|
- bin/sweatshop-payload-parser
|
277
307
|
- bin/sweatshop-worker
|
278
308
|
- config.defaults.yaml
|
@@ -288,11 +318,15 @@ files:
|
|
288
318
|
- lib/robot_sweatshop/config.rb
|
289
319
|
- lib/robot_sweatshop/connections.rb
|
290
320
|
- lib/robot_sweatshop/create-config-directories.rb
|
321
|
+
- lib/robot_sweatshop/overseer.rb
|
291
322
|
- lib/robot_sweatshop/payload.rb
|
292
323
|
- lib/robot_sweatshop/payload/bitbucket.rb
|
293
324
|
- lib/robot_sweatshop/payload/github.rb
|
294
325
|
- lib/robot_sweatshop/payload/json.rb
|
295
326
|
- lib/robot_sweatshop/payload/payload.rb
|
327
|
+
- lib/robot_sweatshop/templates/default_job.yaml
|
328
|
+
- lib/robot_sweatshop/templates/index.html.eruby
|
329
|
+
- lib/robot_sweatshop/templates/log.html.eruby
|
296
330
|
- robot_sweatshop.eye
|
297
331
|
- robot_sweatshop.gemspec
|
298
332
|
- test/README.md
|
@@ -310,10 +344,12 @@ files:
|
|
310
344
|
- test/end-to-end_spec.rb
|
311
345
|
- test/input_spec.rb
|
312
346
|
- test/job_dictionary_spec.rb
|
347
|
+
- test/overseer_spec.rb
|
313
348
|
- test/payload_parser_spec.rb
|
314
349
|
- test/shared/helpers.rb
|
315
350
|
- test/shared/helpers/input.rb
|
316
351
|
- test/shared/helpers/output.rb
|
352
|
+
- test/shared/helpers/overseer.rb
|
317
353
|
- test/shared/scaffolding.rb
|
318
354
|
- test/shared/stub.rb
|
319
355
|
- test/worker_spec.rb
|
@@ -353,6 +389,7 @@ test_files:
|
|
353
389
|
- test/shared/helpers.rb
|
354
390
|
- test/shared/helpers/input.rb
|
355
391
|
- test/shared/helpers/output.rb
|
392
|
+
- test/shared/helpers/overseer.rb
|
356
393
|
- test/shared/scaffolding.rb
|
357
394
|
- test/shared/stub.rb
|
358
395
|
has_rdoc:
|