buildbox 0.3.2 → 0.3.3
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/Gemfile.lock +1 -1
- data/lib/buildbox.rb +1 -4
- data/lib/buildbox/build.rb +4 -0
- data/lib/buildbox/canceler.rb +18 -0
- data/lib/buildbox/command.rb +20 -20
- data/lib/buildbox/monitor.rb +10 -2
- data/lib/buildbox/runner.rb +2 -1
- data/lib/buildbox/version.rb +1 -1
- data/spec/buildbox/buildbox/command_spec.rb +17 -17
- data/spec/fixtures/sleep_script +1 -1
- metadata +3 -4
- data/bin/buildbox-pty +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17c1b2a9d1b7bc186af0aa5a3d93d7dea50e9864
|
4
|
+
data.tar.gz: dd7a3713cfed6a4f8f04eeb77fece760132833cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b15ed4fb9913f0e48dae8b18d05695b556f0714cf9a042b7f08ffec7773945e2cee92554a0f8f7a4af8870ccdbc92b0159c16df970dcd94f80a3bd16b1260a44
|
7
|
+
data.tar.gz: b266bba36f25497145ff582886caae1aa0da899119092deda3d4a304a24d4e35abc0c4caaca0a518859e19999038901c527f6bad9443ef83d6cb3c6d38af4356
|
data/Gemfile.lock
CHANGED
data/lib/buildbox.rb
CHANGED
@@ -5,6 +5,7 @@ module Buildbox
|
|
5
5
|
autoload :API, "buildbox/api"
|
6
6
|
autoload :Build, "buildbox/build"
|
7
7
|
autoload :Command, "buildbox/command"
|
8
|
+
autoload :Canceler, "buildbox/canceler"
|
8
9
|
autoload :CLI, "buildbox/cli"
|
9
10
|
autoload :Configuration, "buildbox/configuration"
|
10
11
|
autoload :Monitor, "buildbox/monitor"
|
@@ -28,10 +29,6 @@ module Buildbox
|
|
28
29
|
@logger = logger
|
29
30
|
end
|
30
31
|
|
31
|
-
def self.gem_root
|
32
|
-
path = File.expand_path(File.join(__FILE__, "..", ".."))
|
33
|
-
end
|
34
|
-
|
35
32
|
def self.root_path
|
36
33
|
path = Pathname.new File.join(ENV['HOME'], ".buildbox")
|
37
34
|
path.mkpath unless path.exist?
|
data/lib/buildbox/build.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Buildbox
|
2
|
+
class Canceler
|
3
|
+
def self.cancel(build)
|
4
|
+
new(build).cancel
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(build)
|
8
|
+
@build = build
|
9
|
+
end
|
10
|
+
|
11
|
+
def cancel
|
12
|
+
@build.cancel_started = true
|
13
|
+
|
14
|
+
# Kill that damn process, yo!
|
15
|
+
Process.kill 'INT', @build.pid
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/buildbox/command.rb
CHANGED
@@ -13,7 +13,7 @@ module Buildbox
|
|
13
13
|
# the given timeout.
|
14
14
|
class TimeoutExceeded < StandardError; end
|
15
15
|
|
16
|
-
attr_reader :output, :exit_status
|
16
|
+
attr_reader :pid, :output, :exit_status
|
17
17
|
|
18
18
|
def self.run(*args, &block)
|
19
19
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
@@ -36,7 +36,7 @@ module Buildbox
|
|
36
36
|
timeout = @options[:timeout]
|
37
37
|
|
38
38
|
# Build the command we're going to run
|
39
|
-
arguments = [
|
39
|
+
arguments = [ *@arguments ].compact.map(&:to_s) # all arguments must be a string
|
40
40
|
|
41
41
|
# Build the ChildProcess
|
42
42
|
@logger.info("Starting process: #{arguments}")
|
@@ -44,8 +44,15 @@ module Buildbox
|
|
44
44
|
process = ChildProcess.build(*arguments)
|
45
45
|
process.cwd = File.expand_path(@options[:directory] || Dir.pwd)
|
46
46
|
|
47
|
-
# Create the pipes so we can read the output in real
|
48
|
-
|
47
|
+
# Create the pipes so we can read the output in real time. PTY
|
48
|
+
# isn't avaible on all platforms (heroku) so we just fallback to IO.pipe
|
49
|
+
# if it's not presetnt.
|
50
|
+
read_pipe, write_pipe = begin
|
51
|
+
PTY.open
|
52
|
+
rescue
|
53
|
+
IO.pipe
|
54
|
+
end
|
55
|
+
|
49
56
|
process.io.stdout = write_pipe
|
50
57
|
process.io.stderr = write_pipe
|
51
58
|
process.duplex = true
|
@@ -70,6 +77,9 @@ module Buildbox
|
|
70
77
|
write_pipe.close
|
71
78
|
end
|
72
79
|
|
80
|
+
# Store the process id for later cancelling!
|
81
|
+
@pid = process.pid
|
82
|
+
|
73
83
|
# Record the start time for timeout purposes
|
74
84
|
start_time = Time.now.to_i
|
75
85
|
|
@@ -97,7 +107,7 @@ module Buildbox
|
|
97
107
|
next if data.empty?
|
98
108
|
|
99
109
|
output << cleaned_data = UTF8.clean(data)
|
100
|
-
yield cleaned_data if block_given?
|
110
|
+
yield self, cleaned_data if block_given?
|
101
111
|
end
|
102
112
|
end
|
103
113
|
|
@@ -130,7 +140,7 @@ module Buildbox
|
|
130
140
|
# If there's some that we missed
|
131
141
|
if extra_data != ""
|
132
142
|
output << cleaned_data = UTF8.clean(extra_data)
|
133
|
-
yield cleaned_data if block_given?
|
143
|
+
yield self, cleaned_data if block_given?
|
134
144
|
end
|
135
145
|
|
136
146
|
if RUBY_PLATFORM == "java"
|
@@ -145,18 +155,6 @@ module Buildbox
|
|
145
155
|
|
146
156
|
private
|
147
157
|
|
148
|
-
# on heroku, tty isn't avaiable. so we result to just running command through
|
149
|
-
# bash. the downside to this, is that stuff colors aren't outputted because
|
150
|
-
# processes don't think they're being in a terminal.
|
151
|
-
def runner
|
152
|
-
require 'pty'
|
153
|
-
PTY.spawn('whoami')
|
154
|
-
|
155
|
-
[ File.join(Buildbox.gem_root, "bin", "buildbox-pty") ]
|
156
|
-
rescue
|
157
|
-
[ "bash", "-c" ]
|
158
|
-
end
|
159
|
-
|
160
158
|
# Reads data from an IO object while it can, returning the data it reads.
|
161
159
|
# When it encounters a case when it can't read anymore, it returns the
|
162
160
|
# data.
|
@@ -190,7 +188,9 @@ module Buildbox
|
|
190
188
|
# since we use some Ruby 1.9 specific exceptions.
|
191
189
|
|
192
190
|
breakable = false
|
193
|
-
|
191
|
+
|
192
|
+
# EOFError from OSX, EIO is raised by ubuntu
|
193
|
+
if e.is_a?(EOFError) || e.is_a?(Errno::EIO)
|
194
194
|
# An `EOFError` means this IO object is done!
|
195
195
|
breakable = true
|
196
196
|
elsif defined?(IO::WaitReadable) && e.is_a?(IO::WaitReadable)
|
@@ -200,7 +200,7 @@ module Buildbox
|
|
200
200
|
# IO object is not ready to be read from yet. No problem,
|
201
201
|
# we read as much as we can, so we break.
|
202
202
|
breakable = true
|
203
|
-
elsif e.is_a?(Errno::EAGAIN)
|
203
|
+
elsif e.is_a?(Errno::EAGAIN) || e.is_a?(Errno::EWOULDBLOCK)
|
204
204
|
# Otherwise, we just look for the EAGAIN error which should be
|
205
205
|
# all that IO::WaitReadable does in Ruby 1.9.
|
206
206
|
breakable = true
|
data/lib/buildbox/monitor.rb
CHANGED
@@ -16,12 +16,20 @@ module Buildbox
|
|
16
16
|
# update_build http call, and breaking. So to make sure we're using the
|
17
17
|
# same build object throughout this call, we can just deep dup it.
|
18
18
|
build = Marshal.load(Marshal.dump(@build))
|
19
|
-
|
19
|
+
|
20
|
+
if build.started? || build.finished?
|
21
|
+
new_build = @api.update_build(build)
|
22
|
+
|
23
|
+
# Try and cancel the build if we haven't tried already
|
24
|
+
if new_build.state == 'canceled' && !@build.cancelling?
|
25
|
+
Buildbox::Canceler.cancel(@build)
|
26
|
+
end
|
27
|
+
end
|
20
28
|
|
21
29
|
if build.finished?
|
22
30
|
break
|
23
31
|
else
|
24
|
-
sleep
|
32
|
+
sleep 2 # 2 seconds seems reasonable for now
|
25
33
|
end
|
26
34
|
end
|
27
35
|
end
|
data/lib/buildbox/runner.rb
CHANGED
@@ -25,7 +25,8 @@ module Buildbox
|
|
25
25
|
@build.started_at = Time.now.utc
|
26
26
|
|
27
27
|
build.output = ""
|
28
|
-
result = Command.run(script_path, :environment => @build.env, :directory => directory_path) do |chunk|
|
28
|
+
result = Command.run(script_path, :environment => @build.env, :directory => directory_path) do |command, chunk|
|
29
|
+
build.pid = command.pid
|
29
30
|
build.output << chunk
|
30
31
|
end
|
31
32
|
|
data/lib/buildbox/version.rb
CHANGED
@@ -5,34 +5,34 @@ require "spec_helper"
|
|
5
5
|
describe Buildbox::Command do
|
6
6
|
describe "#run" do
|
7
7
|
it "is run within a tty" do
|
8
|
-
result = Buildbox::Command.run(
|
8
|
+
result = Buildbox::Command.run("ruby", "-e", "puts STDOUT.tty?")
|
9
9
|
|
10
10
|
result.output.should == "true"
|
11
11
|
end
|
12
12
|
|
13
13
|
it "successfully runs and returns the output from a simple comment" do
|
14
|
-
result = Buildbox::Command.run('echo hello world')
|
14
|
+
result = Buildbox::Command.run('echo', 'hello world')
|
15
15
|
|
16
16
|
result.exit_status.should == 0
|
17
17
|
result.output.should == "hello world"
|
18
18
|
end
|
19
19
|
|
20
|
-
it "
|
21
|
-
result = Buildbox::Command.run(
|
20
|
+
it "includes stderr" do
|
21
|
+
result = Buildbox::Command.run("ruby", "-e", "STDERR.puts 'stderr lol'")
|
22
22
|
|
23
23
|
result.exit_status.should == 0
|
24
|
-
result.output.should == "
|
24
|
+
result.output.should == "stderr lol"
|
25
25
|
end
|
26
26
|
|
27
27
|
it "handles commands that fail and returns the correct status" do
|
28
|
-
result = Buildbox::Command.run('
|
28
|
+
result = Buildbox::Command.run('bash', '-c', 'exit 123')
|
29
29
|
|
30
|
-
result.exit_status.
|
30
|
+
result.exit_status.should == 123
|
31
31
|
result.output.should == ''
|
32
32
|
end
|
33
33
|
|
34
34
|
it "handles running malformed commands" do
|
35
|
-
result = Buildbox::Command.run('if (')
|
35
|
+
result = Buildbox::Command.run('bash', '-c', 'if (')
|
36
36
|
|
37
37
|
result.exit_status.should_not == 0
|
38
38
|
# bash 3.2.48 prints "syntax error" in lowercase.
|
@@ -45,7 +45,7 @@ describe Buildbox::Command do
|
|
45
45
|
|
46
46
|
it "can collect output in chunks" do
|
47
47
|
chunked_output = ''
|
48
|
-
result = Buildbox::Command.run('echo hello world') do |chunk|
|
48
|
+
result = Buildbox::Command.run('echo', 'hello world') do |command, chunk|
|
49
49
|
unless chunk.nil?
|
50
50
|
chunked_output += chunk
|
51
51
|
end
|
@@ -60,8 +60,8 @@ describe Buildbox::Command do
|
|
60
60
|
result = nil
|
61
61
|
second_result = nil
|
62
62
|
thread = Thread.new do
|
63
|
-
result = Buildbox::Command.run('sillycommandlololol')
|
64
|
-
second_result = Buildbox::Command.run('export FOO=bar; doesntexist.rb')
|
63
|
+
result = Buildbox::Command.run('bash', '-c', 'sillycommandlololol')
|
64
|
+
second_result = Buildbox::Command.run('bash', '-c', 'export FOO=bar; doesntexist.rb')
|
65
65
|
end
|
66
66
|
thread.join
|
67
67
|
|
@@ -76,7 +76,7 @@ describe Buildbox::Command do
|
|
76
76
|
|
77
77
|
it "captures color'd output from a command" do
|
78
78
|
chunked_output = ''
|
79
|
-
result = Buildbox::Command.run(
|
79
|
+
result = Buildbox::Command.run('rspec', FIXTURES_PATH.join('rspec', 'test_spec.rb')) do |command, chunk|
|
80
80
|
chunked_output += chunk unless chunk.nil?
|
81
81
|
end
|
82
82
|
|
@@ -87,7 +87,7 @@ describe Buildbox::Command do
|
|
87
87
|
|
88
88
|
it "runs scripts in a tty" do
|
89
89
|
chunked_output = ''
|
90
|
-
result = Buildbox::Command.run(FIXTURES_PATH.join('tty_script')) do |chunk|
|
90
|
+
result = Buildbox::Command.run(FIXTURES_PATH.join('tty_script')) do |command, chunk|
|
91
91
|
chunked_output += chunk unless chunk.nil?
|
92
92
|
end
|
93
93
|
|
@@ -96,8 +96,8 @@ describe Buildbox::Command do
|
|
96
96
|
end
|
97
97
|
|
98
98
|
it "still runs even if pty isn't available" do
|
99
|
-
PTY.should_receive(:
|
100
|
-
result = Buildbox::Command.run('echo hello world')
|
99
|
+
PTY.should_receive(:open).and_raise(RuntimeError.new)
|
100
|
+
result = Buildbox::Command.run('echo', 'hello world')
|
101
101
|
|
102
102
|
result.exit_status.should == 0
|
103
103
|
result.output.should == "hello world"
|
@@ -115,11 +115,11 @@ describe Buildbox::Command do
|
|
115
115
|
it "can collect chunks from within a thread" do
|
116
116
|
chunks = []
|
117
117
|
|
118
|
-
result = Buildbox::Command.run(FIXTURES_PATH.join('sleep_script')) do |chunk|
|
118
|
+
result = Buildbox::Command.run(FIXTURES_PATH.join('sleep_script')) do |command, chunk|
|
119
119
|
chunks << chunk
|
120
120
|
end
|
121
121
|
|
122
|
-
chunks.should == ["0\r\n", "1\r\n", "2\r\n"]
|
122
|
+
chunks.should == ["test 0\r\n", "test 1\r\n", "test 2\r\n"]
|
123
123
|
end
|
124
124
|
end
|
125
125
|
end
|
data/spec/fixtures/sleep_script
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: buildbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keith Pitt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -99,7 +99,6 @@ email:
|
|
99
99
|
- me@keithpitt.com
|
100
100
|
executables:
|
101
101
|
- buildbox
|
102
|
-
- buildbox-pty
|
103
102
|
extensions: []
|
104
103
|
extra_rdoc_files: []
|
105
104
|
files:
|
@@ -111,12 +110,12 @@ files:
|
|
111
110
|
- README.md
|
112
111
|
- Rakefile
|
113
112
|
- bin/buildbox
|
114
|
-
- bin/buildbox-pty
|
115
113
|
- buildbox-ruby.gemspec
|
116
114
|
- lib/buildbox.rb
|
117
115
|
- lib/buildbox/agent.rb
|
118
116
|
- lib/buildbox/api.rb
|
119
117
|
- lib/buildbox/build.rb
|
118
|
+
- lib/buildbox/canceler.rb
|
120
119
|
- lib/buildbox/cli.rb
|
121
120
|
- lib/buildbox/command.rb
|
122
121
|
- lib/buildbox/configuration.rb
|
data/bin/buildbox-pty
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# Disable stdout,stderr buffering
|
4
|
-
STDERR.sync = STDOUT.sync = true
|
5
|
-
|
6
|
-
require 'pty'
|
7
|
-
|
8
|
-
# spawn the process in a pseudo terminal so colors out outputted
|
9
|
-
read_io, write_io, pid = PTY.spawn("bash", "-c", ARGV.join(" "))
|
10
|
-
|
11
|
-
# we don't need to write to the spawned io
|
12
|
-
write_io.close
|
13
|
-
|
14
|
-
loop do
|
15
|
-
fds, = IO.select([read_io], nil, nil, 1)
|
16
|
-
if fds
|
17
|
-
# should have some data to read
|
18
|
-
begin
|
19
|
-
print read_io.read_nonblock(10240)
|
20
|
-
rescue Errno::EAGAIN, Errno::EWOULDBLOCK
|
21
|
-
# do select again
|
22
|
-
rescue EOFError, Errno::EIO # EOFError from OSX, EIO is raised by ubuntu
|
23
|
-
break
|
24
|
-
end
|
25
|
-
end
|
26
|
-
# if fds are empty, timeout expired - run another iteration
|
27
|
-
end
|
28
|
-
|
29
|
-
# we're done reading, yay!
|
30
|
-
read_io.close
|
31
|
-
|
32
|
-
# just wait until its finally finished closing
|
33
|
-
Process.waitpid(pid)
|
34
|
-
|
35
|
-
# exit with the status code that the process returned
|
36
|
-
exit $?.exitstatus
|