buildbox 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0f89d17b118fdfeae221ddd724997ad6892fdb4c
4
- data.tar.gz: f12dab225a000454649464200d544c9e00a39b92
3
+ metadata.gz: 17c1b2a9d1b7bc186af0aa5a3d93d7dea50e9864
4
+ data.tar.gz: dd7a3713cfed6a4f8f04eeb77fece760132833cd
5
5
  SHA512:
6
- metadata.gz: c2ef1cc4e717256591146dec6b118c2bd76caf97d3cc64143616699ae50809aa4d21a1039d72f15c9e7f98a27444500ca97fbfb8068109e50eec27cf63fc3b6e
7
- data.tar.gz: d255170edfba8f35bd03bff55e8f2687584cf3b52375c9a3c31e98b51e5e9a6503d1b0f0a7580b42519ff381725045f0bee2e46411399565a8696b692c4f1c24
6
+ metadata.gz: b15ed4fb9913f0e48dae8b18d05695b556f0714cf9a042b7f08ffec7773945e2cee92554a0f8f7a4af8870ccdbc92b0159c16df970dcd94f80a3bd16b1260a44
7
+ data.tar.gz: b266bba36f25497145ff582886caae1aa0da899119092deda3d4a304a24d4e35abc0c4caaca0a518859e19999038901c527f6bad9443ef83d6cb3c6d38af4356
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- buildbox (0.3.2)
4
+ buildbox (0.3.3)
5
5
  celluloid (~> 0.14)
6
6
  childprocess (~> 0.3)
7
7
  faraday (~> 0.8)
@@ -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?
@@ -7,6 +7,10 @@ module Buildbox
7
7
  exit_status == 0
8
8
  end
9
9
 
10
+ def cancelling?
11
+ cancel_started == true
12
+ end
13
+
10
14
  def started?
11
15
  !started_at.nil?
12
16
  end
@@ -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
@@ -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 = [ *runner, *@arguments ].compact.map(&:to_s) # all arguments must be a string
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 tim
48
- read_pipe, write_pipe = IO.pipe
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
- if e.is_a?(EOFError)
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
@@ -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
- @api.update_build(build) if build.started? || build.finished?
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 3 # 3 seconds seems reasonable for now
32
+ sleep 2 # 2 seconds seems reasonable for now
25
33
  end
26
34
  end
27
35
  end
@@ -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
 
@@ -1,3 +1,3 @@
1
1
  module Buildbox
2
- VERSION = "0.3.2"
2
+ VERSION = "0.3.3"
3
3
  end
@@ -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(%{ruby -e "puts STDOUT.tty?"})
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 "redirects stdout to stderr" do
21
- result = Buildbox::Command.run('echo hello world 1>&2')
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 == "hello world"
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('(exit 1)')
28
+ result = Buildbox::Command.run('bash', '-c', 'exit 123')
29
29
 
30
- result.exit_status.should_not == 0
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("rspec #{FIXTURES_PATH.join('rspec', 'test_spec.rb')}") do |chunk|
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(:spawn).and_raise(RuntimeError.new)
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
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  3.times do |i|
4
- puts i
4
+ puts "test #{i}"
5
5
  sleep 1
6
6
  end
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.2
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-09 00:00:00.000000000 Z
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
@@ -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