buildbox 0.0.4 → 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.ruby-version +1 -0
- data/Gemfile +4 -1
- data/Gemfile.lock +49 -0
- data/README.md +3 -3
- data/Rakefile +4 -0
- data/bin/buildbox +2 -94
- data/buildbox-ruby.gemspec +5 -4
- data/lib/buildbox.rb +20 -33
- data/lib/buildbox/api.rb +32 -87
- data/lib/buildbox/build.rb +10 -64
- data/lib/buildbox/cli.rb +92 -0
- data/lib/buildbox/command.rb +33 -39
- data/lib/buildbox/configuration.rb +18 -42
- data/lib/buildbox/environment.rb +17 -0
- data/lib/buildbox/monitor.rb +25 -0
- data/lib/buildbox/runner.rb +59 -0
- data/lib/buildbox/version.rb +1 -1
- data/lib/buildbox/worker.rb +25 -9
- data/spec/buildbox/buildbox/command_spec.rb +46 -33
- data/spec/integration/running_a_build_spec.rb +140 -23
- data/spec/support/silence_logger.rb +6 -1
- data/spec/support/webmock.rb +1 -0
- metadata +47 -40
- data/.buildbox.toml +0 -2
- data/lib/buildbox/auth.rb +0 -37
- data/lib/buildbox/client.rb +0 -86
- data/lib/buildbox/observer.rb +0 -59
- data/lib/buildbox/pid_file.rb +0 -25
- data/lib/buildbox/response.rb +0 -49
- data/lib/buildbox/result.rb +0 -36
- data/spec/buildbox/buildbox/build_spec.rb +0 -66
- data/spec/buildbox/buildbox/configuration_spec.rb +0 -9
- data/spec/buildbox/buildbox_spec.rb +0 -4
- data/spec/support/dotenv.rb +0 -3
data/lib/buildbox/client.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
module Buildbox
|
2
|
-
class Client
|
3
|
-
def initialize(options)
|
4
|
-
@options = options
|
5
|
-
@interval = 5
|
6
|
-
end
|
7
|
-
|
8
|
-
def start
|
9
|
-
exit_if_already_running
|
10
|
-
|
11
|
-
Buildbox.logger.info "Starting client..."
|
12
|
-
|
13
|
-
register_client
|
14
|
-
|
15
|
-
begin
|
16
|
-
daemonize if @options[:daemon]
|
17
|
-
pid_file.save
|
18
|
-
|
19
|
-
loop do
|
20
|
-
reload_configuration
|
21
|
-
Buildbox::Worker.new.process
|
22
|
-
wait_for_interval
|
23
|
-
end
|
24
|
-
rescue => e
|
25
|
-
Buildbox.logger.error "#{e.class.name}: #{e.message}"
|
26
|
-
e.backtrace.each { |line| Buildbox.logger.error line }
|
27
|
-
|
28
|
-
api.crash(e)
|
29
|
-
ensure
|
30
|
-
pid_file.delete
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def stop
|
35
|
-
Buildbox.logger.info "Stopping client..."
|
36
|
-
|
37
|
-
Process.kill(:KILL, pid_file.delete)
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def daemonize
|
43
|
-
if @options[:daemon]
|
44
|
-
Process.daemon
|
45
|
-
|
46
|
-
Buildbox.logger = Logger.new(Buildbox.root_path.join("buildbox.log"))
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def register_client
|
51
|
-
worker_uuid = Buildbox.configuration.worker_uuid
|
52
|
-
response = api.register(:uuid => worker_uuid, :hostname => `hostname`.chomp)
|
53
|
-
|
54
|
-
Buildbox.configuration.update :worker_uuid, response.payload[:uuid]
|
55
|
-
end
|
56
|
-
|
57
|
-
def reload_configuration
|
58
|
-
Buildbox.configuration.reload
|
59
|
-
end
|
60
|
-
|
61
|
-
def wait_for_interval
|
62
|
-
Buildbox.logger.debug "Sleeping for #{@interval} seconds"
|
63
|
-
|
64
|
-
sleep(@interval)
|
65
|
-
end
|
66
|
-
|
67
|
-
def exit_if_already_running
|
68
|
-
if pid_file.exist?
|
69
|
-
Buildbox.logger.error "Process (#{pid_file.pid} - #{pid_file.path}) is already running."
|
70
|
-
|
71
|
-
exit 1
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def worker
|
76
|
-
end
|
77
|
-
|
78
|
-
def api
|
79
|
-
@api ||= Buildbox::API.new(:api_key => Buildbox.configuration.api_key)
|
80
|
-
end
|
81
|
-
|
82
|
-
def pid_file
|
83
|
-
@pid_file ||= Buildbox::PidFile.new
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
data/lib/buildbox/observer.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
module Buildbox
|
2
|
-
class Observer
|
3
|
-
INTERVAL = 3 # feels like a good number
|
4
|
-
|
5
|
-
def initialize(api, build_uuid)
|
6
|
-
@api = api
|
7
|
-
@build_uuid = build_uuid
|
8
|
-
|
9
|
-
@queue = Queue.new
|
10
|
-
@results = {}
|
11
|
-
@threads = {}
|
12
|
-
end
|
13
|
-
|
14
|
-
def started(result)
|
15
|
-
@results[result.uuid] = result
|
16
|
-
|
17
|
-
update(result.uuid)
|
18
|
-
end
|
19
|
-
|
20
|
-
def chunk(result)
|
21
|
-
update_on_interval(result.uuid)
|
22
|
-
end
|
23
|
-
|
24
|
-
def finished(result)
|
25
|
-
# kill off the interval updater
|
26
|
-
thread = @threads[result.uuid]
|
27
|
-
thread.kill if thread && thread.alive?
|
28
|
-
|
29
|
-
update(result.uuid)
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
# every INTERVAL seconds, read from the result and update the server with the output.
|
35
|
-
# if we don't do updates every INTERVAL like this, then we end up spamming the server
|
36
|
-
# with every chunk we get from the command runner (which ends up being every line), and in the case
|
37
|
-
# of a bundle install for example, it may have 100 lines, we end up doing 100 updates to the server.
|
38
|
-
def update_on_interval(uuid)
|
39
|
-
return if @threads[uuid]
|
40
|
-
|
41
|
-
@threads[uuid] = Thread.new do
|
42
|
-
loop do
|
43
|
-
update(uuid)
|
44
|
-
sleep INTERVAL
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
@threads[uuid].abort_on_exception = true
|
49
|
-
end
|
50
|
-
|
51
|
-
def update(uuid)
|
52
|
-
result = @results[uuid]
|
53
|
-
json = result.as_json
|
54
|
-
json[:state] = json.delete(:finished) ? 'finished' : 'started'
|
55
|
-
|
56
|
-
@api.update_build_result_async(@build_uuid, json.delete(:uuid), json)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
data/lib/buildbox/pid_file.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Buildbox
|
2
|
-
class PidFile
|
3
|
-
def exist?
|
4
|
-
File.exist?(path)
|
5
|
-
end
|
6
|
-
|
7
|
-
def path
|
8
|
-
Buildbox.root_path.join("buildbox.pid")
|
9
|
-
end
|
10
|
-
|
11
|
-
def pid
|
12
|
-
File.readlines(path).first.to_i
|
13
|
-
end
|
14
|
-
|
15
|
-
def save
|
16
|
-
File.open(path, 'w+') { |file| file.write(Process.pid.to_s) }
|
17
|
-
end
|
18
|
-
|
19
|
-
def delete
|
20
|
-
value = pid
|
21
|
-
File.delete(path)
|
22
|
-
value
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/lib/buildbox/response.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
module Buildbox
|
2
|
-
class Response
|
3
|
-
attr_reader :payload
|
4
|
-
|
5
|
-
def initialize(response)
|
6
|
-
@response = response
|
7
|
-
|
8
|
-
unless success?
|
9
|
-
raise "API Error: #{@response.code} #{@response.body}"
|
10
|
-
end
|
11
|
-
|
12
|
-
if json?
|
13
|
-
json = JSON.parse(@response.body)
|
14
|
-
|
15
|
-
if json.kind_of?(Array)
|
16
|
-
@payload = json.map { |item| symbolize_keys(item) }
|
17
|
-
else
|
18
|
-
@payload = symbolize_keys(json)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def success?
|
24
|
-
@response.code.to_i == 200
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def json?
|
30
|
-
@response['content-type'] =~ /json/
|
31
|
-
end
|
32
|
-
|
33
|
-
def symbolize_keys(hash)
|
34
|
-
hash.inject({}) do |result, item|
|
35
|
-
key, value = item
|
36
|
-
new_key = case key
|
37
|
-
when String then key.to_sym
|
38
|
-
else key
|
39
|
-
end
|
40
|
-
new_value = case value
|
41
|
-
when Hash then symbolize_keys(value)
|
42
|
-
else value
|
43
|
-
end
|
44
|
-
result[new_key] = new_value
|
45
|
-
result
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
data/lib/buildbox/result.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
module Buildbox
|
2
|
-
class Result
|
3
|
-
require 'securerandom'
|
4
|
-
|
5
|
-
attr_reader :uuid, :command
|
6
|
-
attr_accessor :output, :finished, :exit_status
|
7
|
-
|
8
|
-
def initialize(command)
|
9
|
-
@uuid = SecureRandom.uuid
|
10
|
-
@output = ""
|
11
|
-
@finished = false
|
12
|
-
@command = command
|
13
|
-
end
|
14
|
-
|
15
|
-
def finished?
|
16
|
-
finished
|
17
|
-
end
|
18
|
-
|
19
|
-
def success?
|
20
|
-
exit_status == 0
|
21
|
-
end
|
22
|
-
|
23
|
-
def as_json
|
24
|
-
{ :uuid => @uuid,
|
25
|
-
:command => @command,
|
26
|
-
:output => clean_output,
|
27
|
-
:exit_status => @exit_status }
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def clean_output
|
33
|
-
Buildbox::UTF8.clean(@output).chomp
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Buildbox::Build do
|
4
|
-
let(:build) { Buildbox::Build.new(:uuid => '1234', :repository => "git@github.com:keithpitt/ci-ruby.git", :commit => "67b15b704e0", :command => "rspec") }
|
5
|
-
|
6
|
-
describe "#start" do
|
7
|
-
let(:build_path) { double }
|
8
|
-
let(:root_path) { double(:join => build_path) }
|
9
|
-
let(:command) { double(:run => true, :run! => true) }
|
10
|
-
|
11
|
-
before do
|
12
|
-
Buildbox.stub(:root_path => root_path)
|
13
|
-
Buildbox::Command.stub(:new => command)
|
14
|
-
end
|
15
|
-
|
16
|
-
context "with a new checkout" do
|
17
|
-
before do
|
18
|
-
build_path.stub(:exist? => false, :mkpath => true)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "creates a directory for the build" do
|
22
|
-
build_path.should_receive(:mkpath)
|
23
|
-
|
24
|
-
build.start
|
25
|
-
end
|
26
|
-
|
27
|
-
it "creates a folder for the build" do
|
28
|
-
root_path.should_receive(:join).with('git-github-com-keithpitt-ci-ruby-git')
|
29
|
-
|
30
|
-
build.start
|
31
|
-
end
|
32
|
-
|
33
|
-
it "clones the repo" do
|
34
|
-
command.should_receive(:run!).with(%{git clone "git@github.com:keithpitt/ci-ruby.git" .}).once
|
35
|
-
|
36
|
-
build.start
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context "with an existing checkout" do
|
41
|
-
before do
|
42
|
-
build_path.stub(:exist? => true)
|
43
|
-
end
|
44
|
-
|
45
|
-
it "doesn't checkout the repo again" do
|
46
|
-
command.should_not_receive(:run!).with(%{git clone "git@github.com:keithpitt/ci-ruby.git" .})
|
47
|
-
|
48
|
-
build.start
|
49
|
-
end
|
50
|
-
|
51
|
-
it "cleans, fetches and checks out the commit" do
|
52
|
-
command.should_receive(:run!).with(%{git clean -fd}).ordered
|
53
|
-
command.should_receive(:run!).with(%{git fetch}).ordered
|
54
|
-
command.should_receive(:run!).with(%{git checkout -qf "67b15b704e0"}).ordered
|
55
|
-
|
56
|
-
build.start
|
57
|
-
end
|
58
|
-
|
59
|
-
it "runs the command" do
|
60
|
-
command.should_receive(:run).with(%{rspec})
|
61
|
-
|
62
|
-
build.start
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
data/spec/support/dotenv.rb
DELETED