travis-artifacts 0.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.
@@ -0,0 +1,2 @@
1
+ vendor/bundle
2
+ /log/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,6 @@
1
+ language: 'ruby'
2
+ script: 'bundle exec rspec spec'
3
+ rvm:
4
+ - 1.8.7
5
+ - 1.9.3
6
+ - jruby
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,52 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ travis-artifacts (0.0.1)
5
+ faraday
6
+ faraday_middleware
7
+ fog
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ builder (3.1.4)
13
+ diff-lcs (1.1.3)
14
+ excon (0.16.8)
15
+ faraday (0.8.4)
16
+ multipart-post (~> 1.1)
17
+ faraday_middleware (0.9.0)
18
+ faraday (>= 0.7.4, < 0.9)
19
+ fog (1.7.0)
20
+ builder
21
+ excon (~> 0.14)
22
+ formatador (~> 0.2.0)
23
+ mime-types
24
+ multi_json (~> 1.0)
25
+ net-scp (~> 1.0.4)
26
+ net-ssh (>= 2.1.3)
27
+ nokogiri (~> 1.5.0)
28
+ ruby-hmac
29
+ formatador (0.2.4)
30
+ mime-types (1.19)
31
+ multi_json (1.3.7)
32
+ multipart-post (1.1.5)
33
+ net-scp (1.0.4)
34
+ net-ssh (>= 1.99.1)
35
+ net-ssh (2.6.1)
36
+ nokogiri (1.5.5)
37
+ rspec (2.12.0)
38
+ rspec-core (~> 2.12.0)
39
+ rspec-expectations (~> 2.12.0)
40
+ rspec-mocks (~> 2.12.0)
41
+ rspec-core (2.12.0)
42
+ rspec-expectations (2.12.0)
43
+ diff-lcs (~> 1.1.3)
44
+ rspec-mocks (2.12.0)
45
+ ruby-hmac (0.4.0)
46
+
47
+ PLATFORMS
48
+ ruby
49
+
50
+ DEPENDENCIES
51
+ rspec
52
+ travis-artifacts!
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.expand_path('../../lib', __FILE__)
4
+
5
+ require 'bundler/setup'
6
+ require 'travis/artifacts'
7
+
8
+ Travis::Artifacts::Cli.new(ARGV).start
@@ -0,0 +1,25 @@
1
+ module Travis
2
+ autoload :Client, 'travis/client'
3
+
4
+ module Artifacts
5
+ autoload :Cli, 'travis/artifacts/cli'
6
+ autoload :Uploader, 'travis/artifacts/uploader'
7
+ autoload :Artifact, 'travis/artifacts/artifact'
8
+ autoload :Path, 'travis/artifacts/path'
9
+ autoload :Logger, 'travis/artifacts/logger'
10
+ autoload :Test, 'travis/artifacts/test'
11
+ autoload :ConfigParser, 'travis/artifacts/config_parser'
12
+ autoload :Prefix, 'travis/artifacts/prefix'
13
+
14
+ def self.aws_config
15
+ { :aws_access_key_id => ENV['ARTIFACTS_AWS_ACCESS_KEY_ID'],
16
+ :aws_secret_access_key => ENV['ARTIFACTS_AWS_SECRET_ACCESS_KEY'],
17
+ :region => ENV['ARTIFACTS_AWS_REGION'] || 'us-east-1'
18
+ }
19
+ end
20
+
21
+ def self.bucket_name
22
+ ENV['ARTIFACTS_S3_BUCKET']
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ require 'mime/types'
2
+
3
+ module Travis::Artifacts
4
+ class Artifact < Struct.new(:source, :destination)
5
+ def content_type
6
+ if MIME::Types.type_for(source).any?
7
+ MIME::Types.type_for(source).first.content_type
8
+ else
9
+ 'application/octet-stream'
10
+ end
11
+ end
12
+
13
+ def read
14
+ File.read(source)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,93 @@
1
+ require 'optparse'
2
+
3
+ module Travis::Artifacts
4
+ class Cli
5
+ attr_reader :options, :argv, :paths
6
+ attr_accessor :command, :client
7
+
8
+ VALID_COMMANDS = ['upload']
9
+
10
+ def initialize(argv = nil)
11
+ @argv = argv || ARGV
12
+ @options = { :paths => [] }
13
+ @paths = []
14
+ @client = Travis::Client.new
15
+ end
16
+
17
+ # I would like to use option parser for now, to keep
18
+ # the code super simple and without too much external
19
+ # dependencies, if it grows too much, I may change it
20
+ def start
21
+ parse!
22
+ create_paths
23
+
24
+ execute_command
25
+ end
26
+
27
+ def root
28
+ options[:root] || Dir.pwd
29
+ end
30
+
31
+ def upload
32
+ Uploader.new(paths, options[:target_path]).upload
33
+ end
34
+
35
+ private
36
+
37
+ def execute_command
38
+ if VALID_COMMANDS.include? command
39
+ send(command)
40
+ else
41
+ STDERR.puts 'Could not find command'
42
+ exit 1
43
+ end
44
+ end
45
+
46
+ def fetch_paths
47
+ options[:paths]
48
+ end
49
+
50
+ def create_paths
51
+ fetch_paths.each do |path|
52
+ from, to = path.split(':')
53
+ paths << Path.new(from, to, root)
54
+ end
55
+ end
56
+
57
+ def parse!
58
+ self.command = argv[0]
59
+ parser.parse! argv
60
+ end
61
+
62
+ def parser
63
+ @opt_parser ||= begin
64
+ options = self.options
65
+
66
+ OptionParser.new do |opt|
67
+ opt.banner = 'Usage: travis-uploader COMMAND [OPTIONS]'
68
+ opt.separator ''
69
+ opt.separator 'Commands'
70
+ opt.separator ' upload: upload files to server'
71
+ opt.separator ''
72
+ opt.separator 'Options'
73
+
74
+ opt.on('--path PATH','path(s) to upload to a server') do |path|
75
+ options[:paths] << path
76
+ end
77
+
78
+ opt.on('--target-path TARGET_PATH', 'path to upload files to') do |target_path|
79
+ options[:target_path] = target_path
80
+ end
81
+
82
+ opt.on('--root ROOT', 'root directory for relative paths') do |root|
83
+ options[:root] = root
84
+ end
85
+
86
+ opt.on('-h','--help','help') do
87
+ puts @opt_parser
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,17 @@
1
+ require 'logger'
2
+
3
+ module Travis::Artifacts
4
+ module Logger
5
+ class << self
6
+ attr_accessor :output
7
+ end
8
+ self.output = STDOUT
9
+
10
+
11
+ attr_reader :logger
12
+
13
+ def logger
14
+ @logger ||= ::Logger.new(Travis::Artifacts::Logger.output)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ module Travis::Artifacts
2
+ class Path < Struct.new(:from, :to, :root)
3
+ def fullpath
4
+ if from =~ /^\//
5
+ from
6
+ else
7
+ File.join(root, from)
8
+ end
9
+ end
10
+
11
+ def directory?
12
+ File.directory?(fullpath)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ module Travis::Artifacts
2
+ class Test
3
+ def success?
4
+ ENV['TRAVIS_TEST_RESULT'].to_i == 0
5
+ end
6
+
7
+ def failure?
8
+ !success?
9
+ end
10
+
11
+ def build_number
12
+ ENV['TRAVIS_BUILD_NUMBER']
13
+ end
14
+
15
+ def build_id
16
+ ENV['TRAVIS_BUILD_ID']
17
+ end
18
+
19
+ def job_number
20
+ ENV['TRAVIS_JOB_NUMBER']
21
+ end
22
+
23
+ def job_id
24
+ ENV['TRAVIS_JOB_ID']
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,109 @@
1
+ require 'find'
2
+ require 'fog'
3
+
4
+ module Travis::Artifacts
5
+ class Uploader
6
+ include Travis::Artifacts::Logger
7
+
8
+ attr_reader :paths, :target_path
9
+
10
+ def initialize(paths, target_path = nil)
11
+ @paths = paths
12
+ @test = Test.new
13
+ @target_path = target_path || "artifacts/#{@test.build_number}/#{@test.job_number}"
14
+ end
15
+
16
+ def upload
17
+ files.each do |file|
18
+ upload_file(file)
19
+ end
20
+ end
21
+
22
+ def files
23
+ files = []
24
+
25
+ paths.each do |artifact_path|
26
+ to = artifact_path.to
27
+ from = artifact_path.from
28
+ root = artifact_path.root
29
+
30
+ if artifact_path.directory?
31
+ root = File.join(root, from)
32
+ root << '/' unless root =~ /\/$/
33
+ end
34
+
35
+ Find.find(artifact_path.fullpath) do |path|
36
+ next unless File.file? path
37
+
38
+ relative = path.sub(/#{root}\/?/, '')
39
+
40
+ destination = if to
41
+ artifact_path.directory? ? File.join(to, relative) : to
42
+ else
43
+ relative
44
+ end
45
+
46
+ files << Artifact.new(path, destination)
47
+ end
48
+ end
49
+
50
+ files
51
+ end
52
+
53
+
54
+ def upload_file(file)
55
+ retries = 0
56
+
57
+ begin
58
+ _upload(file)
59
+ rescue StandardError => e
60
+ if retries < 2
61
+ logger.info "Attempt to upload failed, retrying"
62
+ retries += 1
63
+ retry
64
+ else
65
+ if e.respond_to?(:request)
66
+ # we don't want to display sensitive data, make the error message simpler
67
+ request = e.request
68
+ response = e.response
69
+ raise e
70
+ raise e.class.new("Expected(#{request[:expects].inspect}) <=> Actual(#{response.status})")
71
+ else
72
+ raise
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ def _upload(file)
79
+ destination = File.join(target_path, file.destination)
80
+
81
+ logger.info "Uploading file #{file.source} to #{destination}"
82
+
83
+ bucket.files.create({
84
+ :key => destination,
85
+ :public => true,
86
+ :body => file.read,
87
+ :content_type => file.content_type,
88
+ :metadata => { "Cache-Control" => 'public, max-age=315360000'}
89
+ })
90
+ end
91
+
92
+ private
93
+
94
+ def job_id
95
+ test.job_id
96
+ end
97
+
98
+ def bucket
99
+ @bucket ||= s3.directories.get(Travis::Artifacts.bucket_name)
100
+ end
101
+
102
+ def s3
103
+ @s3 ||= begin
104
+ config = { :provider => 'AWS' }.merge Travis::Artifacts.aws_config
105
+ Fog::Storage.new(config)
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,47 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+
4
+ module Travis
5
+ class Client
6
+ attr_reader :connection
7
+
8
+ def initialize
9
+ @connection = create_connection
10
+ end
11
+
12
+ # TODO: this needs to be fixed before going too far, returning body without
13
+ # ability to inspect response or returning nil on any failure are not
14
+ # the best ways to deal with API client
15
+ def fetch_config(job_id)
16
+ response = get("/jobs/#{job_id}")
17
+ if (200..299).include?(response.status)
18
+ response.body['job']['config']
19
+ else
20
+ # TODO: I should probably raise here
21
+ nil
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ http_methods = [:get, :post, :put, :patch, :delete, :head]
28
+ http_methods.each do |method|
29
+
30
+ define_method(method) do |*args, &block|
31
+ path, params, headers = *args
32
+ connection.send(method, path, params, headers, &block)
33
+ end
34
+ end
35
+
36
+ def create_connection
37
+ # TODO: support for pro
38
+ Faraday.new(:url => 'https://api.travis-ci.org') do |faraday|
39
+ faraday.response :json, :content_type => /\bjson$/
40
+
41
+ faraday.adapter :net_http
42
+ end.tap do |connection|
43
+ connection.headers['Accept'] = 'application/vnd.travis-ci.2+json'
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Travis::Client do
4
+ end
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.expand_path('../../lib', __FILE__))
4
+
5
+ require 'bundler/setup'
6
+ require 'irb'
7
+ require 'irb/completion'
8
+ require 'travis/artifacts'
9
+ ARGV.clear
10
+ IRB.start
11
+
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,9 @@
1
+ require 'travis/artifacts'
2
+ require 'fileutils'
3
+
4
+ FileUtils.mkdir_p "log"
5
+ Travis::Artifacts::Logger.output = "log/test.log"
6
+
7
+ RSpec.configure do |config|
8
+ config.expect_with :rspec, :stdlib
9
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+
3
+ module Travis::Artifacts
4
+ describe Artifact do
5
+ end
6
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ module Travis::Artifacts
4
+ describe Cli do
5
+ let(:cli) { described_class.new(argv) }
6
+
7
+
8
+ context 'with multiple paths' do
9
+ before { cli.stub(:upload) }
10
+ let(:argv) { ['upload', '--path', 'path/to/foo', '--path', 'path/to/bar:bar'] }
11
+
12
+ before { cli.start }
13
+
14
+ it 'parses them' do
15
+ cli.options[:paths].should == ['path/to/foo', 'path/to/bar:bar']
16
+ end
17
+
18
+ it 'adds paths to paths array' do
19
+ cli.paths.map { |p| [p.from, p.to] }.should == [['path/to/foo', nil], ['path/to/bar', 'bar']]
20
+ end
21
+ end
22
+
23
+ describe 'upload' do
24
+ let(:argv) { ['upload', '--path', 'foo', '--target-path', 'bar'] }
25
+ it 'calls Uploader with given paths and target_path' do
26
+ uploader = mock('uploader')
27
+ Uploader.should_receive(:new).with([Path.new('foo', nil, Dir.pwd)], 'bar').and_return(uploader)
28
+ uploader.should_receive(:upload)
29
+
30
+ cli.start
31
+ end
32
+ end
33
+
34
+ describe '#root' do
35
+ before { cli.stub(:upload) }
36
+ before { cli.start }
37
+
38
+ context 'with root passed as an argument' do
39
+ let(:argv) { ['upload', '--root', 'foo'] }
40
+ it 'returns passed value' do
41
+ cli.root.should == 'foo'
42
+ end
43
+ end
44
+
45
+ context 'without root passed as an argument' do
46
+ before { cli.stub(:upload) }
47
+ let(:argv) { ['upload'] }
48
+ it 'returns cwd' do
49
+ cli.root.should == Dir.pwd
50
+ end
51
+ end
52
+ end
53
+
54
+ context 'with a command' do
55
+ before { cli.stub(:upload) }
56
+ let(:argv) { ['upload'] }
57
+
58
+ before { cli.start }
59
+
60
+ it 'saves it' do
61
+ cli.command.should == 'upload'
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ module Travis::Artifacts
4
+ describe Uploader do
5
+ let(:uploader) { Uploader.new(paths, 'artifacts/1') }
6
+ let(:paths) { [] }
7
+
8
+ context 'without given target_path' do
9
+ let(:uploader) { Uploader.new(paths, nil) }
10
+
11
+ it 'sets a default' do
12
+ test = mock('test', :job_number => "10.1", :build_number => "10")
13
+ Test.stub(:new => test)
14
+
15
+ uploader.target_path.should == 'artifacts/10/10.1'
16
+ end
17
+ end
18
+
19
+ describe '#upload_file' do
20
+ it 'retries 3 times before giving up' do
21
+ file = Artifact.new('source/file.png', 'destination/file.png')
22
+
23
+ uploader.should_receive(:_upload).exactly(3).times.and_raise(StandardError)
24
+
25
+ expect {
26
+ uploader.upload_file(file)
27
+ }.to raise_error(StandardError)
28
+ end
29
+
30
+ it 'simplifies excon error to not show request data' do
31
+ file = Artifact.new('source/file.png', 'destination/file.png')
32
+
33
+ request = { :expects => 200 }
34
+ response = mock('response', :status => 500)
35
+ error_class = Class.new(Excon::Errors::HTTPStatusError)
36
+ my_error = error_class.new('message', request, response)
37
+ uploader.should_receive(:_upload).exactly(4).times.and_raise(my_error)
38
+
39
+ expect {
40
+ uploader.upload_file(file)
41
+ }.to raise_error { |e|
42
+ e.message.should == 'Expected(200) <=> Actual(500)'
43
+ }
44
+ end
45
+ end
46
+
47
+ describe '#upload' do
48
+ it 'uploads file to S3' do
49
+ files = [
50
+ Artifact.new('source/path.png', 'destination/path.png')
51
+ ]
52
+ files[0].stub(:read => 'contents')
53
+ uploader.stub(:files => files)
54
+
55
+ bucket = mock('bucker')
56
+ bucket_files = mock('bucket_files')
57
+ uploader.stub(:bucket => bucket)
58
+ bucket.stub(:files => bucket_files)
59
+
60
+ bucket_files.should_receive(:create).with({
61
+ :key => 'artifacts/1/destination/path.png',
62
+ :public => true,
63
+ :body => 'contents',
64
+ :content_type => 'image/png',
65
+ :metadata => {'Cache-Control' => 'public, max-age=315360000'}
66
+
67
+ })
68
+
69
+ uploader.upload
70
+ end
71
+ end
72
+
73
+ describe '#files' do
74
+ let(:root) { File.expand_path('../../../fixtures', __FILE__) }
75
+
76
+ context 'with nested files from root' do
77
+ let(:paths) { [Path.new('.', nil, root)] }
78
+
79
+ it 'resolves paths into files to upload' do
80
+ files = [
81
+ 'files/foo/bar/baz.txt',
82
+ 'files/logs/bar.log',
83
+ 'files/logs/foo.log',
84
+ 'files/output.txt'
85
+ ]
86
+ files.map! { |file| Artifact.new(File.join(root, '.', file), file) }
87
+
88
+ uploader.files.sort_by { |o| o.source }.should == files.sort_by { |o| o.source }
89
+ end
90
+ end
91
+
92
+ context 'with destination path and directory' do
93
+ let(:paths) { [Path.new('files/logs', 'logs', root)] }
94
+
95
+ it 'resolves paths into files to upload' do
96
+ files = [
97
+ 'logs/bar.log',
98
+ 'logs/foo.log'
99
+ ]
100
+ files.map! { |file| Artifact.new(File.join(root, 'files', file), "#{file}") }
101
+
102
+ uploader.files.sort_by { |o| o.source }.should == files.sort_by { |o| o.source }
103
+ end
104
+ end
105
+
106
+ context 'with individual files' do
107
+ let(:paths) {
108
+ [Path.new('files/logs/bar.log', nil, root),
109
+ Path.new('files/logs/foo.log', 'new/location/foo.log', root)]
110
+
111
+ }
112
+
113
+ it 'resolves paths into files to upload' do
114
+ file1 = 'files/logs/bar.log'
115
+ file2 = 'files/logs/foo.log'
116
+
117
+ files = [
118
+ Artifact.new(File.join(root, file1), 'files/logs/bar.log'),
119
+ Artifact.new(File.join(root, file2), 'new/location/foo.log')
120
+ ]
121
+
122
+ uploader.files.should == files
123
+ end
124
+ end
125
+
126
+ context 'with multilevel directory and to' do
127
+ let(:paths) {
128
+ [Path.new('files/foo', 'foo1', root)]
129
+ }
130
+
131
+ it 'resolves paths into files to upload' do
132
+ uploader.files.should == [Artifact.new(File.join(root, 'files/foo/bar/baz.txt'), 'foo1/bar/baz.txt')]
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'travis-artifacts'
3
+ s.version = '0.0.1'
4
+
5
+ s.description = 'Travis build artifacts tools'
6
+ s.summary = s.description
7
+
8
+ s.homepage = 'https://github.com/travis-ci/travis-artifacts'
9
+ s.authors = ['admin@travis-ci.org']
10
+ s.email = 'admin@travis-ci.org'
11
+
12
+ s.add_dependency 'fog'
13
+ s.add_dependency 'faraday'
14
+ s.add_dependency 'faraday_middleware'
15
+
16
+ s.add_development_dependency 'rspec'
17
+
18
+ s.files = `git ls-files`.split($/)
19
+ s.executables = s.files.grep(/^bin/).map{|f| File.basename(f) }
20
+ s.test_files = s.files.grep(/^spec/)
21
+ s.require_paths = ['lib']
22
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: travis-artifacts
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - admin@travis-ci.org
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fog
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: faraday
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: faraday_middleware
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: Travis build artifacts tools
79
+ email: admin@travis-ci.org
80
+ executables:
81
+ - travis-artifacts
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - .gitignore
86
+ - .rspec
87
+ - .travis.yml
88
+ - Gemfile
89
+ - Gemfile.lock
90
+ - bin/travis-artifacts
91
+ - lib/travis/artifacts.rb
92
+ - lib/travis/artifacts/artifact.rb
93
+ - lib/travis/artifacts/cli.rb
94
+ - lib/travis/artifacts/logger.rb
95
+ - lib/travis/artifacts/path.rb
96
+ - lib/travis/artifacts/test.rb
97
+ - lib/travis/artifacts/uploader.rb
98
+ - lib/travis/client.rb
99
+ - lib/travis/client_spec.rb
100
+ - script/console
101
+ - spec/fixtures/files/foo/bar/baz.txt
102
+ - spec/fixtures/files/logs/bar.log
103
+ - spec/fixtures/files/logs/foo.log
104
+ - spec/fixtures/files/output.txt
105
+ - spec/spec_helper.rb
106
+ - spec/travis/artifacts/artifact_spec.rb
107
+ - spec/travis/artifacts/cli_spec.rb
108
+ - spec/travis/artifacts/uploader_spec.rb
109
+ - travis-artifacts.gemspec
110
+ homepage: https://github.com/travis-ci/travis-artifacts
111
+ licenses: []
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ! '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ requirements: []
129
+ rubyforge_project:
130
+ rubygems_version: 1.8.24
131
+ signing_key:
132
+ specification_version: 3
133
+ summary: Travis build artifacts tools
134
+ test_files:
135
+ - spec/fixtures/files/foo/bar/baz.txt
136
+ - spec/fixtures/files/logs/bar.log
137
+ - spec/fixtures/files/logs/foo.log
138
+ - spec/fixtures/files/output.txt
139
+ - spec/spec_helper.rb
140
+ - spec/travis/artifacts/artifact_spec.rb
141
+ - spec/travis/artifacts/cli_spec.rb
142
+ - spec/travis/artifacts/uploader_spec.rb