simplecov-s3 0.1.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.
- data/.gitignore +8 -0
- data/.rspec +1 -0
- data/.travis.yml +24 -0
- data/Gemfile +8 -0
- data/LICENSE +19 -0
- data/README.md +87 -0
- data/Rakefile +9 -0
- data/lib/simplecov-s3.rb +141 -0
- data/lib/simplecov-s3/version.rb +5 -0
- data/simplecov-s3.gemspec +22 -0
- data/spec/a_spec.rb +44 -0
- metadata +108 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--format documentation --colour
|
data/.travis.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
---
|
2
|
+
git:
|
3
|
+
depth: 1
|
4
|
+
|
5
|
+
notifications:
|
6
|
+
email: false
|
7
|
+
webhooks:
|
8
|
+
urls:
|
9
|
+
- https://ensemble.engineyard.com/travis
|
10
|
+
on_success: always
|
11
|
+
on_failure: always
|
12
|
+
on_start: true
|
13
|
+
|
14
|
+
before_script:
|
15
|
+
- echo "--profile --color" > '.rspec' # Report slowest ten tests, make it pretty
|
16
|
+
|
17
|
+
script: bundle exec rake
|
18
|
+
|
19
|
+
env:
|
20
|
+
global:
|
21
|
+
- RUBY_GC_MALLOC_LIMIT=1000000000
|
22
|
+
- RUBY_HEAP_SLOTS_GROWTH_FACTOR=1.25
|
23
|
+
- RUBY_HEAP_MIN_SLOTS=800000
|
24
|
+
- RUBY_FREE_MIN=600000
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2013 Engine Yard
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# Simplecov-S3
|
2
|
+
|
3
|
+
Sample Usage:
|
4
|
+
|
5
|
+
config/environment.rb
|
6
|
+
|
7
|
+
require File.expand_path('../application', __FILE__)
|
8
|
+
|
9
|
+
if Rails.env.test?
|
10
|
+
require File.expand_path("../../spec/coverage_helper", __FILE__)
|
11
|
+
end
|
12
|
+
|
13
|
+
coverage_helper.rb
|
14
|
+
|
15
|
+
unless ENV["SKIP_COVERAGE"]
|
16
|
+
require 'simplecov'
|
17
|
+
SimpleCov.start(:rails)
|
18
|
+
SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
|
19
|
+
SimpleCov.at_exit do
|
20
|
+
SimpleCov.result.format!
|
21
|
+
end
|
22
|
+
SimpleCov.command_name("HAX#{Time.now.to_i}")
|
23
|
+
SimpleCov.merge_timeout 86400
|
24
|
+
end
|
25
|
+
|
26
|
+
Rakefile
|
27
|
+
|
28
|
+
task :coverage do
|
29
|
+
build_units = YAML.load_file(File.expand_path("../build_units.yml",__FILE__)).size
|
30
|
+
require File.expand_path("../spec/coverage_helper", __FILE__)
|
31
|
+
cov = SimpleCov::S3.new(
|
32
|
+
:fog => {
|
33
|
+
:provider => 'AWS',
|
34
|
+
:aws_access_key_id => "XXXXXX",
|
35
|
+
:aws_secret_access_key => "XXXXXXXXXXXXX",
|
36
|
+
:region => "us-east-1",
|
37
|
+
},
|
38
|
+
:project_name => ENV["TRAVIS_REPO_SLUG"],
|
39
|
+
:build_id => ENV["TRAVIS_BUILD_ID"],
|
40
|
+
:job_id => ENV["TRAVIS_JOB_ID"],
|
41
|
+
:build_unit => ENV["BUILD_UNIT"],
|
42
|
+
:build_units => build_units,
|
43
|
+
:bucket_name => "somebucket",
|
44
|
+
:public_url_base => "http://somebucket.s3-website-us-east-1.amazonaws.com/",
|
45
|
+
:assets_url => "http://somebucket.s3-website-us-east-1.amazonaws.com/assets",
|
46
|
+
:shared_secret => "XXXXXXXXXXXX", #used so build units can find each other, and for covereage postback
|
47
|
+
:postback_url => "https://bot.example.org/coverage",
|
48
|
+
)
|
49
|
+
cov.push_partial(:debug => true)
|
50
|
+
cov.pull_merge_and_push_full
|
51
|
+
end
|
52
|
+
|
53
|
+
Sample S3 Bucket policy to allow the "<user>" user of from the Amazon Account ID "<awsaccount>" access to read/write from the "<bucket>" bucket, while the public is allowed read-only:
|
54
|
+
|
55
|
+
{
|
56
|
+
"Version": "2008-10-17",
|
57
|
+
"Id": "Policy123456",
|
58
|
+
"Statement": [
|
59
|
+
{
|
60
|
+
"Sid": "Stmt11111",
|
61
|
+
"Effect": "Allow",
|
62
|
+
"Principal": {
|
63
|
+
"AWS": "arn:aws:iam::<awsaccount>:user/<user>"
|
64
|
+
},
|
65
|
+
"Action": "s3:*",
|
66
|
+
"Resource": "arn:aws:s3:::<bucket>"
|
67
|
+
},
|
68
|
+
{
|
69
|
+
"Sid": "Stmt222222",
|
70
|
+
"Effect": "Allow",
|
71
|
+
"Principal": {
|
72
|
+
"AWS": "arn:aws:iam::<awsaccount>:user/<user>"
|
73
|
+
},
|
74
|
+
"Action": "s3:*",
|
75
|
+
"Resource": "arn:aws:s3:::<bucket>/*"
|
76
|
+
},
|
77
|
+
{
|
78
|
+
"Sid": "Stmt33333",
|
79
|
+
"Effect": "Allow",
|
80
|
+
"Principal": {
|
81
|
+
"AWS": "*"
|
82
|
+
},
|
83
|
+
"Action": "s3:GetObject",
|
84
|
+
"Resource": "arn:aws:s3:::<bucket>/*"
|
85
|
+
}
|
86
|
+
]
|
87
|
+
}
|
data/Rakefile
ADDED
data/lib/simplecov-s3.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'digest'
|
2
|
+
require 'securerandom'
|
3
|
+
require 'excon'
|
4
|
+
require 'fog'
|
5
|
+
require 'simplecov'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
module SimpleCov
|
9
|
+
class S3
|
10
|
+
|
11
|
+
def self.ensured(task_to_invoke, &block)
|
12
|
+
Rake::Task[task_to_invoke].invoke
|
13
|
+
ensure
|
14
|
+
begin
|
15
|
+
yield
|
16
|
+
rescue => e
|
17
|
+
puts e.inspect
|
18
|
+
puts e.backtrace
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Formatter < SimpleCov::Formatter::HTMLFormatter
|
23
|
+
#an ugly partial-copy from: https://github.com/colszowka/simplecov-html/blob/master/lib/simplecov-html.rb
|
24
|
+
def format(result)
|
25
|
+
template('layout').result(binding)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(opts)
|
30
|
+
@connection = Fog::Storage.new(opts[:fog])
|
31
|
+
@public_url_base = opts[:public_url_base]
|
32
|
+
@shared_secret = opts[:shared_secret]
|
33
|
+
@assets_url = opts[:assets_url]
|
34
|
+
@bucket_name = opts[:bucket_name]
|
35
|
+
@build_units = opts[:build_units]
|
36
|
+
@postback_url = opts[:postback_url]
|
37
|
+
@build_unit = opts[:build_unit]
|
38
|
+
@build_id = opts[:build_id]
|
39
|
+
@job_id = opts[:job_id]
|
40
|
+
@project_name = opts[:project_name]
|
41
|
+
end
|
42
|
+
|
43
|
+
def push_partial(opts = {})
|
44
|
+
begin
|
45
|
+
result = SimpleCov::ResultMerger.merged_result
|
46
|
+
data_to_push = result.original_result.merge("BUILD_UNIT" => @build_unit).to_json
|
47
|
+
put_file("#{@project_name}-#{commit_time}-coverageJSON/#{hashed_build_id}/#{@job_id}", data_to_push)
|
48
|
+
rescue => e
|
49
|
+
puts e.inspect
|
50
|
+
puts e.backtrace
|
51
|
+
puts "SOMEHTING WENT WRONG, PUSHING EMPTY COVERAGE FILE"
|
52
|
+
put_file("#{@project_name}-#{commit_time}-coverageJSON/#{hashed_build_id}/#{@job_id}", {}.to_json)
|
53
|
+
end
|
54
|
+
if opts[:debug]
|
55
|
+
debug_folder = "#{@project_name}-#{Time.now.to_i}-coverageDEBUG/#{hashed_build_id}-#{@job_id}"
|
56
|
+
push_coverage_to(debug_folder, gen_body(result))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def pull_merge_and_push_full
|
61
|
+
if(json_files.size < @build_units)
|
62
|
+
puts "Expected to see #{@build_units} files"
|
63
|
+
puts "currently only #{json_files.size}"
|
64
|
+
require 'pp'
|
65
|
+
pp json_files.map(&:key)
|
66
|
+
puts "Assuming some other build unit will be the last to exit, and merge/post full coverage"
|
67
|
+
return false
|
68
|
+
end
|
69
|
+
puts "Coverage combined from #{json_files.size} units"
|
70
|
+
results = []
|
71
|
+
included_units = []
|
72
|
+
json_files.each do |f|
|
73
|
+
parsed = JSON.parse(f.body)
|
74
|
+
included_units << parsed.delete("BUILD_UNIT")
|
75
|
+
results << SimpleCov::Result.new(parsed)
|
76
|
+
end
|
77
|
+
puts "Included units: #{included_units.sort_by(&:to_s).inspect}"
|
78
|
+
merged = {}
|
79
|
+
results.each do |result|
|
80
|
+
merged = result.original_result.merge_resultset(merged)
|
81
|
+
end
|
82
|
+
result = SimpleCov::Result.new(merged)
|
83
|
+
push_coverage_to("#{@project_name}-#{Time.now.to_i}-coverageRESULT/#{SecureRandom.urlsafe_base64(33)}", gen_body(result), result.covered_percent, @postback_url)
|
84
|
+
end
|
85
|
+
|
86
|
+
def push_full
|
87
|
+
result = SimpleCov::ResultMerger.merged_result
|
88
|
+
push_coverage_to("#{@project_name}-#{Time.now.to_i}-coverageRESULT/#{SecureRandom.urlsafe_base64(33)}", gen_body(result), result.covered_percent, @postback_url)
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def put_file(path, data)
|
94
|
+
puts "Putting to #{path} data size #{data.size}"
|
95
|
+
@connection.directories.get(@bucket_name).files.create(:key => path, :body => data, :content_type => "text/html")
|
96
|
+
end
|
97
|
+
|
98
|
+
def json_files
|
99
|
+
expected_dir = "#{@project_name}-#{commit_time}-coverageJSON/#{hashed_build_id}/"
|
100
|
+
@connection.directories.get(@bucket_name, :prefix => expected_dir).files
|
101
|
+
end
|
102
|
+
|
103
|
+
def gen_body(result)
|
104
|
+
Formatter.new.format(result).gsub("./assets",@assets_url)
|
105
|
+
end
|
106
|
+
|
107
|
+
def push_coverage_to(folder, data, covered_percent = nil, postback_url = false)
|
108
|
+
coverage_url = "#{@public_url_base}#{folder}"
|
109
|
+
puts "Pushing full coverage to #{coverage_url}"
|
110
|
+
put_file("#{folder}/index.html", data)
|
111
|
+
if postback_url
|
112
|
+
puts "Postback coverage_url to #{postback_url}"
|
113
|
+
coverage_percentage = "#{covered_percent.round(2)}"
|
114
|
+
travis_id = @build_id
|
115
|
+
signature = Digest::SHA1.hexdigest([coverage_url, coverage_percentage, travis_id, @shared_secret].join("."))
|
116
|
+
post_params = {
|
117
|
+
'coverage_url' => coverage_url,
|
118
|
+
'coverage_percentage' => coverage_percentage,
|
119
|
+
'travis_id' => travis_id,
|
120
|
+
'signature' => signature,
|
121
|
+
}
|
122
|
+
puts "post params: " + post_params.inspect
|
123
|
+
result = Excon.post(postback_url,
|
124
|
+
:body => URI.encode_www_form(post_params),
|
125
|
+
:headers => { "Content-Type" => "application/x-www-form-urlencoded" })
|
126
|
+
puts result.inspect
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def commit_time
|
131
|
+
@commit_time ||= DateTime.parse(`git show | grep Date`.gsub("Date:","").strip).strftime("%s")
|
132
|
+
end
|
133
|
+
|
134
|
+
def hashed_build_id
|
135
|
+
@hashed_build_id ||= begin
|
136
|
+
Digest::SHA1.hexdigest(@build_id + @shared_secret)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "simplecov-s3/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "simplecov-s3"
|
7
|
+
s.version = SimpleCov::S3::VERSION
|
8
|
+
s.authors = ["Jacob"]
|
9
|
+
s.email = ["jacob@engineyard.com"]
|
10
|
+
s.homepage = "https://github.com/engineyard/simplecov-s3"
|
11
|
+
s.summary = %q{Merge simplecov outputs using S3 as shared storage (and publish the results as html to S3)}
|
12
|
+
s.description = %q{Merge simplecov outputs using S3 as shared storage (and publish the results as html to S3) (works best with travis)}
|
13
|
+
|
14
|
+
s.files = (`git ls-files`.split("\n") - `git ls-files -- fake`.split("\n"))
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_development_dependency 'rspec'
|
20
|
+
s.add_dependency "fog"
|
21
|
+
s.add_dependency 'simplecov'
|
22
|
+
end
|
data/spec/a_spec.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'simplecov-s3'
|
2
|
+
require 'rspec'
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
describe SimpleCov::S3 do
|
6
|
+
|
7
|
+
it "is just barely tested" do
|
8
|
+
Fog.mock!
|
9
|
+
def Excon.post(*args)
|
10
|
+
puts "Mocked!"
|
11
|
+
end
|
12
|
+
#TODO: generate some coverage data via SimpleCov.start ?
|
13
|
+
fog_opts = {
|
14
|
+
:provider => 'AWS',
|
15
|
+
:aws_access_key_id => "XXXXXX",
|
16
|
+
:aws_secret_access_key => "XXXXXXXXXXXXX",
|
17
|
+
:region => "us-east-1",
|
18
|
+
}
|
19
|
+
s3conn = Fog::Storage.new(fog_opts)
|
20
|
+
s3conn.directories.create(:key => "somebucket")
|
21
|
+
cov_opts = {
|
22
|
+
:fog => fog_opts,
|
23
|
+
:project_name => "ey/simplecov-s3", #ENV["TRAVIS_REPO_SLUG"],
|
24
|
+
:build_id => "123", #ENV["TRAVIS_BUILD_ID"],
|
25
|
+
:job_id => "456", #ENV["TRAVIS_JOB_ID"],
|
26
|
+
:build_unit => "5", #ENV["BUILD_UNIT"],
|
27
|
+
:build_units => 2,
|
28
|
+
:bucket_name => "somebucket",
|
29
|
+
:public_url_base => "http://somebucket.s3-website-us-east-1.amazonaws.com/",
|
30
|
+
:assets_url => "http://somebucket.s3-website-us-east-1.amazonaws.com/assets",
|
31
|
+
:shared_secret => "XXXXXXXXXXXX", #used so build units can find each other, and for covereage postback
|
32
|
+
:postback_url => "https://bot.example.org/coverage",
|
33
|
+
}
|
34
|
+
cov = SimpleCov::S3.new(cov_opts)
|
35
|
+
cov.push_partial(:debug => true)
|
36
|
+
cov.pull_merge_and_push_full
|
37
|
+
cov2 = SimpleCov::S3.new(cov_opts.merge(:job_id => "457", :build_unit => "6"))
|
38
|
+
cov2.push_partial(:debug => true)
|
39
|
+
cov2.pull_merge_and_push_full
|
40
|
+
cov2.push_full
|
41
|
+
#TODO: assert on the resulting contents of S3?
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simplecov-s3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jacob
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
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: fog
|
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: simplecov
|
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
|
+
description: Merge simplecov outputs using S3 as shared storage (and publish the results
|
63
|
+
as html to S3) (works best with travis)
|
64
|
+
email:
|
65
|
+
- jacob@engineyard.com
|
66
|
+
executables: []
|
67
|
+
extensions: []
|
68
|
+
extra_rdoc_files: []
|
69
|
+
files:
|
70
|
+
- .gitignore
|
71
|
+
- .rspec
|
72
|
+
- .travis.yml
|
73
|
+
- Gemfile
|
74
|
+
- LICENSE
|
75
|
+
- README.md
|
76
|
+
- Rakefile
|
77
|
+
- lib/simplecov-s3.rb
|
78
|
+
- lib/simplecov-s3/version.rb
|
79
|
+
- simplecov-s3.gemspec
|
80
|
+
- spec/a_spec.rb
|
81
|
+
homepage: https://github.com/engineyard/simplecov-s3
|
82
|
+
licenses: []
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 1.8.25
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: Merge simplecov outputs using S3 as shared storage (and publish the results
|
105
|
+
as html to S3)
|
106
|
+
test_files:
|
107
|
+
- spec/a_spec.rb
|
108
|
+
has_rdoc:
|