travis-artifacts 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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