buildbox 0.6.beta2 → 0.6.beta3
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 +0 -1
- data/lib/buildbox/agent.rb +3 -4
- data/lib/buildbox/api.rb +2 -2
- data/lib/buildbox/artifact.rb +16 -48
- data/lib/buildbox/artifact/collector.rb +63 -0
- data/lib/buildbox/artifact/poster.rb +51 -0
- data/lib/buildbox/artifact/uploader.rb +32 -0
- data/lib/buildbox/server.rb +1 -1
- data/lib/buildbox/version.rb +1 -1
- data/spec/buildbox/buildbox/artifact/collector_spec.rb +45 -0
- metadata +7 -5
- data/lib/buildbox/uploader.rb +0 -58
- data/spec/buildbox/buildbox/artifact_spec.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d0de360c32f22ab29259e472e4ecba54dc326aa
|
4
|
+
data.tar.gz: 12631903e7780f9d7fea9ea16964fb09402e30de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 211edbd383cb6b699ceef9187c18d12374ada689dbf13210b87117efdccad1bf261a8f4b7e3dcfe3bb2ea8d83c9b936dfc75a4a19a548e996cbceb49cef05f85
|
7
|
+
data.tar.gz: 77e43c81f73e764bdcf432b815df5dde9d5acb92ac3c7edea20bb195cd90cb07d3f7900790ae5c03231d0456417cb8e320e06fc8a2b7ad3ddfe93b2ce3e24e38
|
data/Gemfile.lock
CHANGED
data/lib/buildbox.rb
CHANGED
data/lib/buildbox/agent.rb
CHANGED
@@ -42,13 +42,12 @@ module Buildbox
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def upload_artifacts_from(build_directory, artifact_path)
|
45
|
-
|
45
|
+
artifacts = Artifact::Collector.collect_and_copy(build_directory, artifact_path)
|
46
46
|
|
47
|
-
|
48
|
-
Celluloid::Actor[:uploader_pool].async.upload(@api, @access_token, @current_build, relative_path, absolute_path)
|
49
|
-
end
|
47
|
+
Artifact::Uploader.new(@api, @access_token, @current_build, artifacts).async.prepare_and_upload
|
50
48
|
rescue => e
|
51
49
|
error "There was an error uploading artifacts for path: #{artifact_path} (#{e.class.name}: #{e.message})"
|
50
|
+
|
52
51
|
e.backtrace[0..3].each { |line| error(line) }
|
53
52
|
end
|
54
53
|
end
|
data/lib/buildbox/api.rb
CHANGED
@@ -54,8 +54,8 @@ module Buildbox
|
|
54
54
|
put("#{access_token}/builds/#{build.id}", options)
|
55
55
|
end
|
56
56
|
|
57
|
-
def
|
58
|
-
post("#{access_token}/builds/#{build.id}/artifacts",
|
57
|
+
def create_artifacts(access_token, build, artifacts)
|
58
|
+
post("#{access_token}/builds/#{build.id}/artifacts", :artifacts => artifacts.map(&:as_json))
|
59
59
|
end
|
60
60
|
|
61
61
|
def update_artifact(access_token, build, artifact_id, options)
|
data/lib/buildbox/artifact.rb
CHANGED
@@ -1,62 +1,30 @@
|
|
1
|
-
require '
|
2
|
-
require 'tempfile'
|
1
|
+
require 'securerandom'
|
3
2
|
|
4
3
|
module Buildbox
|
5
4
|
class Artifact
|
6
|
-
|
5
|
+
autoload :Poster, "buildbox/artifact/poster"
|
6
|
+
autoload :Collector, "buildbox/artifact/collector"
|
7
|
+
autoload :Uploader, "buildbox/artifact/uploader"
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
end
|
9
|
+
attr_reader :id, :name, :path
|
10
|
+
attr_accessor :remote_id, :upload_instructions
|
11
11
|
|
12
|
-
def
|
13
|
-
|
14
|
-
@glob = glob
|
12
|
+
def self.create(name, path)
|
13
|
+
new(SecureRandom.uuid, name, path)
|
15
14
|
end
|
16
15
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
copy_files_to_upload(tmpdir).each do |file|
|
22
|
-
path_to_absolute[relativize_to_dir(file, tmpdir)] = file
|
23
|
-
end
|
24
|
-
|
25
|
-
path_to_absolute
|
16
|
+
def initialize(id, name, path)
|
17
|
+
@id = id
|
18
|
+
@name = name
|
19
|
+
@path = path
|
26
20
|
end
|
27
21
|
|
28
|
-
|
29
|
-
|
30
|
-
def copy_files_to_upload(dir)
|
31
|
-
expanded_directory = File.expand_path(@build_directory)
|
32
|
-
absolute_glob = File.expand_path(@glob, expanded_directory)
|
33
|
-
|
34
|
-
target_files = Dir.glob(absolute_glob)
|
35
|
-
|
36
|
-
target_files.each do |file|
|
37
|
-
relative_path = relativize_to_dir(file, expanded_directory)
|
38
|
-
copy_to = File.join(dir, relative_path)
|
39
|
-
|
40
|
-
if File.file?(file)
|
41
|
-
FileUtils.mkdir_p(File.dirname(copy_to))
|
42
|
-
FileUtils.cp(file, copy_to)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Grab all the files we're going to upload.
|
47
|
-
Dir.glob(File.join(dir, "**", "*")).reject { |file| File.directory?(file) }
|
22
|
+
def basename
|
23
|
+
File.basename(@path)
|
48
24
|
end
|
49
25
|
|
50
|
-
|
51
|
-
|
52
|
-
def relativize_to_dir(path, directory)
|
53
|
-
if path.to_s.index(directory.to_s) == 0
|
54
|
-
parts = path.to_s.split(directory.to_s)
|
55
|
-
parts.shift
|
56
|
-
parts.join(directory.to_s)
|
57
|
-
else
|
58
|
-
path
|
59
|
-
end
|
26
|
+
def as_json
|
27
|
+
{ :id => @id, :name => @name, :path => @path, :file_size => File.size(@path) }
|
60
28
|
end
|
61
29
|
end
|
62
30
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module Buildbox
|
5
|
+
class Artifact::Collector
|
6
|
+
include Celluloid::Logger
|
7
|
+
|
8
|
+
MAX_ARTIFACT_LIMIT = 500
|
9
|
+
|
10
|
+
class TooManyArtifactsError < RuntimeError; end
|
11
|
+
|
12
|
+
def self.collect_and_copy(build_directory, glob)
|
13
|
+
new(build_directory, glob).collect_and_copy
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(build_directory, glob)
|
17
|
+
@build_directory = build_directory
|
18
|
+
@glob = glob
|
19
|
+
end
|
20
|
+
|
21
|
+
def collect_and_copy
|
22
|
+
index = 0
|
23
|
+
artifacts = []
|
24
|
+
tmpdir = Dir.mktmpdir
|
25
|
+
|
26
|
+
globbed_files.each do |file|
|
27
|
+
raise TooManyArtifactsError if index > MAX_ARTIFACT_LIMIT
|
28
|
+
|
29
|
+
absolute_path = File.expand_path(file, @build_directory)
|
30
|
+
copy_to_path = File.join(tmpdir, file)
|
31
|
+
|
32
|
+
if File.file?(absolute_path)
|
33
|
+
artifacts << Artifact.create(file, copy_to_path)
|
34
|
+
|
35
|
+
FileUtils.mkdir_p(File.dirname(copy_to_path))
|
36
|
+
FileUtils.cp(absolute_path, copy_to_path)
|
37
|
+
end
|
38
|
+
|
39
|
+
index += 1
|
40
|
+
end
|
41
|
+
|
42
|
+
artifacts
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def glob_path
|
48
|
+
Pathname.new(@glob)
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_directory_path
|
52
|
+
Pathname.new(@build_directory)
|
53
|
+
end
|
54
|
+
|
55
|
+
def globbed_files
|
56
|
+
if glob_path.relative?
|
57
|
+
Dir.chdir(build_directory_path.expand_path) { Dir.glob(glob_path) }
|
58
|
+
else
|
59
|
+
Dir.glob(glob_path)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'celluloid'
|
2
|
+
require 'mime/types'
|
3
|
+
|
4
|
+
module Buildbox
|
5
|
+
class Artifact::Poster
|
6
|
+
include Celluloid
|
7
|
+
include Celluloid::Logger
|
8
|
+
|
9
|
+
def post(api, access_token, build, artifact)
|
10
|
+
upload_action = artifact.upload_instructions['action']
|
11
|
+
form_data = artifact.upload_instructions['data'].to_hash.dup
|
12
|
+
|
13
|
+
connection = Faraday.new(:url => upload_action['url']) do |faraday|
|
14
|
+
faraday.request :multipart
|
15
|
+
|
16
|
+
faraday.response :raise_error
|
17
|
+
|
18
|
+
faraday.options[:timeout] = 60
|
19
|
+
faraday.options[:open_timeout] = 60
|
20
|
+
|
21
|
+
faraday.adapter Faraday.default_adapter
|
22
|
+
end
|
23
|
+
|
24
|
+
mime_type = MIME::Types.type_for(artifact.path)[0].to_s
|
25
|
+
|
26
|
+
file_input_key = upload_action['file_input']
|
27
|
+
form_data[file_input_key] = Faraday::UploadIO.new(artifact.path, mime_type)
|
28
|
+
|
29
|
+
api.update_artifact(access_token, build, artifact.remote_id, :state => 'uploading')
|
30
|
+
|
31
|
+
upload_exception = nil
|
32
|
+
response = nil
|
33
|
+
|
34
|
+
begin
|
35
|
+
response = connection.post(upload_action['path'], form_data)
|
36
|
+
rescue => e
|
37
|
+
upload_exception = e
|
38
|
+
end
|
39
|
+
|
40
|
+
if upload_exception
|
41
|
+
error "Error uploading #{artifact.basename} with a status of (#{upload_exception.class.name}: #{upload_exception.message})"
|
42
|
+
finished_state = 'error'
|
43
|
+
else
|
44
|
+
info "Finished uploading #{artifact.basename} with a status of #{response.status}"
|
45
|
+
finished_state = 'finished'
|
46
|
+
end
|
47
|
+
|
48
|
+
api.update_artifact(access_token, build, artifact.remote_id, :state => finished_state)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'celluloid'
|
2
|
+
require 'mime/types'
|
3
|
+
|
4
|
+
module Buildbox
|
5
|
+
class Artifact::Uploader
|
6
|
+
include Celluloid
|
7
|
+
include Celluloid::Logger
|
8
|
+
|
9
|
+
def initialize(api, access_token, build, artifacts)
|
10
|
+
@api = api
|
11
|
+
@access_token = access_token
|
12
|
+
@build = build
|
13
|
+
@artifacts = artifacts
|
14
|
+
end
|
15
|
+
|
16
|
+
def prepare_and_upload
|
17
|
+
info "Preparing #{@artifacts.count} artifacts for upload"
|
18
|
+
|
19
|
+
responses = @api.create_artifacts(@access_token, @build, @artifacts)
|
20
|
+
responses.each do |response|
|
21
|
+
artifact = @artifacts.find { |artifact| artifact.id == response['id'] }
|
22
|
+
|
23
|
+
artifact.remote_id = response['artifact']['id']
|
24
|
+
artifact.upload_instructions = response['artifact']['uploader']
|
25
|
+
end
|
26
|
+
|
27
|
+
@artifacts.each do |artifact|
|
28
|
+
Celluloid::Actor[:artifact_poster_pool].async.post(@api, @access_token, @build, artifact)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/buildbox/server.rb
CHANGED
@@ -12,7 +12,7 @@ module Buildbox
|
|
12
12
|
|
13
13
|
def start
|
14
14
|
Celluloid.logger = @logger
|
15
|
-
Celluloid::Actor[:
|
15
|
+
Celluloid::Actor[:artifact_poster_pool] = Artifact::Poster.pool
|
16
16
|
|
17
17
|
agent_access_tokens.each do |access_token|
|
18
18
|
@supervisors << Buildbox::Agent.supervise(access_token)
|
data/lib/buildbox/version.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Buildbox::Artifact::Collector do
|
4
|
+
let(:directory) { File.join(FIXTURES_PATH, "artifact-globber") }
|
5
|
+
|
6
|
+
def test_for_files(files, expected)
|
7
|
+
expected.each do |path|
|
8
|
+
expect(files.map(&:name)).to include(path)
|
9
|
+
expect(File.exist?(files.find{ |f| f.name == path }.path)).to be_true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#collect_and_copy" do
|
14
|
+
it "handles specific files" do
|
15
|
+
files = Buildbox::Artifact::Collector.collect_and_copy(directory, "foo.txt")
|
16
|
+
|
17
|
+
expect(files.length).to eql(1)
|
18
|
+
test_for_files(files, %w(foo.txt))
|
19
|
+
end
|
20
|
+
|
21
|
+
it "handles globs" do
|
22
|
+
files = Buildbox::Artifact::Collector.collect_and_copy(directory, "bar/**/*.txt")
|
23
|
+
|
24
|
+
expect(files.length).to eql(4)
|
25
|
+
test_for_files(files, %w(bar/bang.txt bar/bang1.txt bar/bang2.txt bar/inside-bar/bang3.txt))
|
26
|
+
end
|
27
|
+
|
28
|
+
it "handles absolute globs" do
|
29
|
+
files = Buildbox::Artifact::Collector.collect_and_copy(directory, File.join(File.expand_path(directory), "**/*.txt"))
|
30
|
+
expected_files = %w(foo.txt bar/bang.txt bar/bang1.txt bar/bang2.txt bar/inside-bar/bang3.txt).map do |file|
|
31
|
+
File.join(directory, file)
|
32
|
+
end
|
33
|
+
|
34
|
+
expect(files.length).to eql(5)
|
35
|
+
test_for_files(files, expected_files)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "handles specifying everything under a folder" do
|
39
|
+
files = Buildbox::Artifact::Collector.collect_and_copy(directory, "coverage/**/*")
|
40
|
+
|
41
|
+
expect(files.length).to eql(25)
|
42
|
+
test_for_files(files, %w(coverage/index.html coverage/assets/0.8.0/application.js))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
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.6.
|
4
|
+
version: 0.6.beta3
|
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-11-
|
11
|
+
date: 2013-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -185,6 +185,9 @@ files:
|
|
185
185
|
- lib/buildbox/agent.rb
|
186
186
|
- lib/buildbox/api.rb
|
187
187
|
- lib/buildbox/artifact.rb
|
188
|
+
- lib/buildbox/artifact/collector.rb
|
189
|
+
- lib/buildbox/artifact/poster.rb
|
190
|
+
- lib/buildbox/artifact/uploader.rb
|
188
191
|
- lib/buildbox/build.rb
|
189
192
|
- lib/buildbox/canceler.rb
|
190
193
|
- lib/buildbox/cli.rb
|
@@ -194,13 +197,12 @@ files:
|
|
194
197
|
- lib/buildbox/platform.rb
|
195
198
|
- lib/buildbox/runner.rb
|
196
199
|
- lib/buildbox/server.rb
|
197
|
-
- lib/buildbox/uploader.rb
|
198
200
|
- lib/buildbox/utf8.rb
|
199
201
|
- lib/buildbox/version.rb
|
200
202
|
- lib/certs/cacert.pem
|
201
203
|
- spec/buildbox/buildbox/agent_spec.rb
|
202
204
|
- spec/buildbox/buildbox/api_spec.rb
|
203
|
-
- spec/buildbox/buildbox/
|
205
|
+
- spec/buildbox/buildbox/artifact/collector_spec.rb
|
204
206
|
- spec/buildbox/buildbox/build_spec.rb
|
205
207
|
- spec/buildbox/buildbox/cli_spec.rb
|
206
208
|
- spec/buildbox/buildbox/command_spec.rb
|
@@ -297,7 +299,7 @@ summary: Ruby agent for buildbox
|
|
297
299
|
test_files:
|
298
300
|
- spec/buildbox/buildbox/agent_spec.rb
|
299
301
|
- spec/buildbox/buildbox/api_spec.rb
|
300
|
-
- spec/buildbox/buildbox/
|
302
|
+
- spec/buildbox/buildbox/artifact/collector_spec.rb
|
301
303
|
- spec/buildbox/buildbox/build_spec.rb
|
302
304
|
- spec/buildbox/buildbox/cli_spec.rb
|
303
305
|
- spec/buildbox/buildbox/command_spec.rb
|
data/lib/buildbox/uploader.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'celluloid'
|
2
|
-
require 'mime/types'
|
3
|
-
|
4
|
-
module Buildbox
|
5
|
-
class Uploader
|
6
|
-
include Celluloid
|
7
|
-
include Celluloid::Logger
|
8
|
-
|
9
|
-
def upload(api, access_token, current_build, relative_path, absolute_path)
|
10
|
-
info "Uploading #{absolute_path}"
|
11
|
-
|
12
|
-
artifact = api.create_artifact(access_token, current_build,
|
13
|
-
:path => relative_path,
|
14
|
-
:file_size => File.size(absolute_path))
|
15
|
-
|
16
|
-
|
17
|
-
upload_action = artifact[:uploader][:action]
|
18
|
-
form_data = artifact[:uploader][:data].to_hash.dup
|
19
|
-
|
20
|
-
connection = Faraday.new(:url => upload_action[:url]) do |faraday|
|
21
|
-
faraday.request :multipart
|
22
|
-
|
23
|
-
faraday.response :raise_error
|
24
|
-
|
25
|
-
faraday.options[:timeout] = 60
|
26
|
-
faraday.options[:open_timeout] = 60
|
27
|
-
|
28
|
-
faraday.adapter Faraday.default_adapter
|
29
|
-
end
|
30
|
-
|
31
|
-
mime_type = MIME::Types.type_for(absolute_path)[0].to_s
|
32
|
-
|
33
|
-
file_input_key = upload_action[:file_input]
|
34
|
-
form_data[file_input_key] = Faraday::UploadIO.new(absolute_path, mime_type)
|
35
|
-
|
36
|
-
api.update_artifact(access_token, current_build, artifact[:id], :state => 'uploading')
|
37
|
-
|
38
|
-
upload_exception = nil
|
39
|
-
response = nil
|
40
|
-
|
41
|
-
begin
|
42
|
-
response = connection.post(upload_action[:path], form_data)
|
43
|
-
rescue => e
|
44
|
-
upload_exception = e
|
45
|
-
end
|
46
|
-
|
47
|
-
if upload_exception
|
48
|
-
error "Error uploading #{File.basename(absolute_path)} with a status of (#{upload_exception.class.name}: #{upload_exception.message})"
|
49
|
-
finished_state = 'error'
|
50
|
-
else
|
51
|
-
info "Finished uploading #{File.basename(absolute_path)} with a status of #{response.status}"
|
52
|
-
finished_state = 'finished'
|
53
|
-
end
|
54
|
-
|
55
|
-
api.update_artifact(access_token, current_build, artifact[:id], :state => finished_state)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Buildbox::Artifact do
|
4
|
-
let(:directory) { File.join(FIXTURES_PATH, "artifact-globber") }
|
5
|
-
|
6
|
-
def test_for_files(files, expected)
|
7
|
-
expected.each do |path|
|
8
|
-
expect(files.keys).to include(path)
|
9
|
-
expect(File.exist?(files[path])).to be_true
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
describe "#files_to_upload" do
|
14
|
-
it "handles specific files" do
|
15
|
-
files = Buildbox::Artifact.files_to_upload(directory, "foo.txt")
|
16
|
-
|
17
|
-
expect(files.length).to eql(1)
|
18
|
-
test_for_files(files, %w(/foo.txt))
|
19
|
-
end
|
20
|
-
|
21
|
-
it "handles globs" do
|
22
|
-
files = Buildbox::Artifact.files_to_upload(directory, "bar/**/*.txt")
|
23
|
-
|
24
|
-
expect(files.length).to eql(4)
|
25
|
-
test_for_files(files, %w(/bar/bang.txt /bar/bang1.txt /bar/bang2.txt /bar/inside-bar/bang3.txt))
|
26
|
-
end
|
27
|
-
|
28
|
-
it "handles absolute globs" do
|
29
|
-
files = Buildbox::Artifact.files_to_upload(directory, File.join(File.expand_path(directory), "**/*.txt"))
|
30
|
-
|
31
|
-
expect(files.length).to eql(5)
|
32
|
-
test_for_files(files, %w(/foo.txt /bar/bang.txt /bar/bang1.txt /bar/bang2.txt /bar/inside-bar/bang3.txt))
|
33
|
-
end
|
34
|
-
|
35
|
-
it "handles specifying everything under a folder" do
|
36
|
-
files = Buildbox::Artifact.files_to_upload(directory, "coverage/**/*")
|
37
|
-
|
38
|
-
expect(files.length).to eql(25)
|
39
|
-
test_for_files(files, %w(/coverage/index.html /coverage/assets/0.8.0/application.js))
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|