coverband 3.0.0 → 4.0.0
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/.gitignore +2 -1
- data/.travis.yml +3 -0
- data/Gemfile +1 -0
- data/Gemfile.rails4 +7 -0
- data/Gemfile.rails4.lock +164 -0
- data/README.md +143 -334
- data/changes.md +41 -17
- data/coverband.gemspec +16 -4
- data/lib/coverband/adapters/base.rb +57 -8
- data/lib/coverband/adapters/file_store.rb +4 -22
- data/lib/coverband/adapters/redis_store.rb +7 -27
- data/lib/coverband/collectors/coverage.rb +7 -10
- data/lib/coverband/configuration.rb +27 -13
- data/lib/coverband/integrations/background.rb +26 -1
- data/lib/coverband/integrations/middleware.rb +5 -1
- data/lib/coverband/integrations/rack_server_check.rb +27 -0
- data/lib/coverband/reporters/simple_cov_report.rb +1 -7
- data/lib/coverband/reporters/web.rb +3 -21
- data/lib/coverband/utils/railtie.rb +17 -0
- data/lib/coverband/utils/s3_report.rb +108 -0
- data/lib/coverband/utils/tasks.rb +6 -6
- data/lib/coverband/version.rb +1 -1
- data/lib/coverband.rb +14 -3
- data/test/benchmarks/benchmark.rake +53 -2
- data/test/rails4_dummy/app/controllers/dummy_controller.rb +5 -0
- data/test/rails4_dummy/config/application.rb +15 -0
- data/test/rails4_dummy/config/boot.rb +3 -0
- data/test/rails4_dummy/config/coverband.rb +8 -0
- data/test/rails4_dummy/config/environment.rb +5 -0
- data/test/rails4_dummy/config/routes.rb +3 -0
- data/test/rails4_dummy/config/secrets.yml +3 -0
- data/test/rails4_dummy/config.ru +4 -0
- data/test/rails5_dummy/app/controllers/dummy_controller.rb +5 -0
- data/test/rails5_dummy/config/application.rb +16 -0
- data/test/rails5_dummy/config/coverband.rb +8 -0
- data/test/rails5_dummy/config/environment.rb +2 -0
- data/test/rails5_dummy/config/routes.rb +3 -0
- data/test/rails5_dummy/config.ru +3 -0
- data/test/rails_test_helper.rb +11 -0
- data/test/test_helper.rb +14 -9
- data/test/unit/adapters_base_test.rb +34 -13
- data/test/unit/adapters_file_store_test.rb +8 -4
- data/test/unit/adapters_redis_store_test.rb +7 -13
- data/test/unit/background_test.rb +24 -0
- data/test/unit/collectors_coverage_test.rb +14 -0
- data/test/unit/configuration_test.rb +12 -0
- data/test/unit/coverband_test.rb +26 -0
- data/test/unit/full_stack_test.rb +2 -1
- data/test/unit/middleware_test.rb +19 -0
- data/test/unit/rack_server_checkout_test.rb +24 -0
- data/test/unit/rails_full_stack_test.rb +60 -0
- data/test/unit/reports_base_test.rb +0 -2
- data/test/unit/reports_console_test.rb +1 -0
- data/test/unit/reports_simple_cov_test.rb +1 -10
- data/test/unit/reports_web_test.rb +1 -3
- data/test/unit/utils_s3_report_test.rb +44 -0
- metadata +89 -19
- data/lib/coverband/utils/s3_report_writer.rb +0 -59
- data/test/unit/utils_s3_report_writer_test.rb +0 -30
data/changes.md
CHANGED
|
@@ -23,27 +23,20 @@ Will be the fully modern release that drops maintenance legacy support in favor
|
|
|
23
23
|
- Support for file versions
|
|
24
24
|
- md5 or release tags
|
|
25
25
|
- add coverage timerange support
|
|
26
|
-
- Drop Simplecov dependency
|
|
27
|
-
|
|
28
|
-
### Coverband 3.X
|
|
29
|
-
|
|
30
|
-
Will be a stable and fast release that drops maintenance legacy support in favor of increased performance and maintainability.
|
|
31
|
-
|
|
32
|
-
- expects to drop Tracepoint collection engine
|
|
33
|
-
- expects to drop anything below Ruby 2.3
|
|
34
|
-
- release begins to simplify ease of use
|
|
35
|
-
- drop collectors adapter
|
|
36
|
-
- reduced configuration options
|
|
26
|
+
- Drop Simplecov dependency
|
|
37
27
|
- improved web reporting
|
|
38
28
|
- no longer relying directly on HTML in S3 but dynamically generated from any adapter
|
|
39
29
|
- lists current config options
|
|
40
30
|
- eventually allow updating remote config
|
|
41
31
|
- full theming
|
|
42
|
-
- list redis data dump for debugging
|
|
32
|
+
- list redis data dump for debugging
|
|
43
33
|
- additional adapters: Memcache, S3, and ActiveRecord
|
|
44
|
-
- add additional config / protection options on Coverage clear
|
|
45
|
-
- add memory benchmarks showing memory overhead of coverband
|
|
46
34
|
- add articles / podcasts like prontos readme https://github.com/prontolabs/pronto
|
|
35
|
+
- Add detailed Gem usage report, if we collect and send gem usage we can give percentage of gem code used, which should help application developers know when to remove gem dependencies (0%) or perhaps inline single methods for little usage (using <= 5%) for example.
|
|
36
|
+
- add additional config / protection options on Coverage clear
|
|
37
|
+
- add meta data information first seen last recorded to the coverage report views (probably need to drop simplecov for that).
|
|
38
|
+
- more details in this issue: https://github.com/danmayer/coverband/issues/118
|
|
39
|
+
- Make good video on setup, install, usage
|
|
47
40
|
|
|
48
41
|
### Coverband_jam_session
|
|
49
42
|
|
|
@@ -65,16 +58,47 @@ Feature Ideas:
|
|
|
65
58
|
- tagging of reported Coverage
|
|
66
59
|
- allow only to collect coverage based on route (limiting or scoped coverage)
|
|
67
60
|
- coverage over some other variable like a set of alpha users
|
|
61
|
+
- document how to use this on staging / selenium test suite runs
|
|
62
|
+
- possible add API to pull report at end of run
|
|
68
63
|
|
|
69
64
|
# Alpha
|
|
70
65
|
|
|
71
|
-
### Coverband
|
|
72
|
-
|
|
73
|
-
* ??? ;)
|
|
66
|
+
### Coverband 4.0.0
|
|
74
67
|
|
|
68
|
+
* Add support for Railties integration
|
|
69
|
+
* Reduce configuration options
|
|
70
|
+
* Default to background reporting vs middleware reporting
|
|
71
|
+
* Resolves issue requiring submitting initial coverage data pre-fork
|
|
72
|
+
* Simplified setup with just works sensible defaults for configuration out of the box
|
|
73
|
+
* Fixes on the pilot release of background reporting in 3.0.1
|
|
74
|
+
* Rake tasks automatically configured
|
|
75
|
+
* Updated and simplified documentation
|
|
75
76
|
|
|
76
77
|
# Released
|
|
77
78
|
|
|
79
|
+
### Coverband 3.X
|
|
80
|
+
|
|
81
|
+
Will be a stable and fast release that drops maintenance legacy support in favor of increased performance and maintainability.
|
|
82
|
+
|
|
83
|
+
- expects to drop Tracepoint collection engine
|
|
84
|
+
- drop anything below Ruby 2.3
|
|
85
|
+
- release begins to simplify ease of use
|
|
86
|
+
- drop collectors adapter
|
|
87
|
+
- reduced configuration options
|
|
88
|
+
- add memory benchmarks showing memory overhead of coverband
|
|
89
|
+
- use full stack tests to prove no memory leaks when used in Rails
|
|
90
|
+
|
|
91
|
+
### Coverband 3.0.1
|
|
92
|
+
|
|
93
|
+
* update documentation around verification steps (https://github.com/danmayer/coverband/issues/135), thanks @kbaum
|
|
94
|
+
* resolve coverage drift issue, https://github.com/danmayer/coverband/issues/118, thanks for MD5 hash ideas @dnasseri and @kbaum
|
|
95
|
+
* first version of background thread coverage reporting https://github.com/danmayer/coverband/pull/138, thanks @kbaum
|
|
96
|
+
* auto-detection of Rack & Rails thanks @kbaum
|
|
97
|
+
* improved tests allowing exceptions to raise in tests @kbaum
|
|
98
|
+
* add support for both aws-sdk 1.x and 2.x thanks @jared
|
|
99
|
+
* adds memory test ensuring no memory leaks
|
|
100
|
+
* full stack Rails tests for Rails 4 and 5 thanks @kbaum
|
|
101
|
+
|
|
78
102
|
### Coverband 3.0.0
|
|
79
103
|
|
|
80
104
|
* drops Tracepoint
|
data/coverband.gemspec
CHANGED
|
@@ -19,22 +19,34 @@ Gem::Specification.new do |spec|
|
|
|
19
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
20
20
|
spec.require_paths = ['lib']
|
|
21
21
|
|
|
22
|
+
# to test support for sdk 1, uncomment this line
|
|
23
|
+
# spec.add_development_dependency 'aws-sdk', '~> 1'
|
|
24
|
+
# to test sdk 2 use this one
|
|
22
25
|
spec.add_development_dependency 'aws-sdk', '~> 2'
|
|
26
|
+
spec.add_development_dependency 'benchmark-ips'
|
|
23
27
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
|
28
|
+
spec.add_development_dependency 'm'
|
|
29
|
+
spec.add_development_dependency 'memory_profiler'
|
|
24
30
|
spec.add_development_dependency 'mocha', '~> 0.14.0'
|
|
25
31
|
spec.add_development_dependency 'rack'
|
|
26
32
|
spec.add_development_dependency 'rack-test'
|
|
27
33
|
spec.add_development_dependency 'rake'
|
|
28
34
|
spec.add_development_dependency 'test-unit'
|
|
29
|
-
|
|
30
|
-
spec.add_development_dependency 'benchmark-ips'
|
|
35
|
+
|
|
31
36
|
# used for benchmarking and tests
|
|
32
37
|
spec.add_development_dependency 'classifier-reborn'
|
|
33
38
|
# add when debugging
|
|
34
39
|
# require 'byebug'; byebug
|
|
35
|
-
spec.add_development_dependency 'byebug'
|
|
40
|
+
spec.add_development_dependency 'pry-byebug'
|
|
36
41
|
|
|
37
|
-
#
|
|
42
|
+
# TODO: Remove when other production adapters exist
|
|
43
|
+
# because the default configuration of redis store, we really do require
|
|
44
|
+
# redis now. I was reluctant to add this, but until we offer another production
|
|
45
|
+
# quality adapter, I think this is more honest about requirements and reduces confusion
|
|
46
|
+
# without this there was a race condition on calling coverband configure before redis was loaded
|
|
47
|
+
spec.add_runtime_dependency 'redis'
|
|
48
|
+
# TODO: make an optional dependency for simplecov reports
|
|
38
49
|
# also likely should just require simplecov-html not the whole lib
|
|
50
|
+
# I tried this but it was harder than I thought
|
|
39
51
|
spec.add_runtime_dependency 'simplecov', '> 0.11.1'
|
|
40
52
|
end
|
|
@@ -4,36 +4,70 @@ module Coverband
|
|
|
4
4
|
module Adapters
|
|
5
5
|
class Base
|
|
6
6
|
def initialize
|
|
7
|
-
|
|
7
|
+
@file_hash_cache = {}
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def clear!
|
|
11
11
|
raise 'abstract'
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
# Note: This could lead to slight race on redis
|
|
15
|
+
# where multiple processes pull the old coverage and add to it then push
|
|
16
|
+
# the Coverband 2 had the same issue,
|
|
17
|
+
# and the tradeoff has always been acceptable
|
|
18
|
+
def save_report(report)
|
|
19
|
+
data = report.dup
|
|
20
|
+
merge_reports(data, get_report)
|
|
21
|
+
save_coverage(data)
|
|
16
22
|
end
|
|
17
23
|
|
|
18
24
|
def coverage
|
|
19
|
-
|
|
25
|
+
simple_report(get_report)
|
|
20
26
|
end
|
|
21
27
|
|
|
22
28
|
def covered_files
|
|
29
|
+
coverage.keys || []
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def covered_lines_for_file(file)
|
|
33
|
+
coverage[file] || []
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
protected
|
|
37
|
+
|
|
38
|
+
def save_coverage
|
|
23
39
|
raise 'abstract'
|
|
24
40
|
end
|
|
25
41
|
|
|
26
|
-
def
|
|
42
|
+
def get_report
|
|
27
43
|
raise 'abstract'
|
|
28
44
|
end
|
|
29
45
|
|
|
30
|
-
|
|
46
|
+
def file_hash(file)
|
|
47
|
+
@file_hash_cache[file] ||= Digest::MD5.file(file).hexdigest
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def expand_report(report)
|
|
51
|
+
report_time = Time.now.to_i
|
|
52
|
+
report.each_pair do |key, line_data|
|
|
53
|
+
extended_data = {
|
|
54
|
+
'first_updated_at' => report_time,
|
|
55
|
+
'last_updated_at' => report_time,
|
|
56
|
+
'file_hash' => file_hash(key),
|
|
57
|
+
'data' => line_data
|
|
58
|
+
}
|
|
59
|
+
report[key] = extended_data
|
|
60
|
+
end
|
|
61
|
+
end
|
|
31
62
|
|
|
32
63
|
def merge_reports(new_report, old_report)
|
|
64
|
+
new_report = expand_report(new_report)
|
|
33
65
|
keys = (new_report.keys + old_report.keys).uniq
|
|
34
66
|
keys.each do |file|
|
|
35
|
-
new_report[file] = if new_report[file] &&
|
|
36
|
-
|
|
67
|
+
new_report[file] = if new_report[file] &&
|
|
68
|
+
old_report[file] &&
|
|
69
|
+
new_report[file]['file_hash'] == old_report[file]['file_hash']
|
|
70
|
+
merge_expanded_data(new_report[file], old_report[file])
|
|
37
71
|
elsif new_report[file]
|
|
38
72
|
new_report[file]
|
|
39
73
|
else
|
|
@@ -43,9 +77,24 @@ module Coverband
|
|
|
43
77
|
new_report
|
|
44
78
|
end
|
|
45
79
|
|
|
80
|
+
def merge_expanded_data(new_expanded, old_expanded)
|
|
81
|
+
{
|
|
82
|
+
'first_updated_at' => old_expanded['first_updated_at'],
|
|
83
|
+
'last_updated_at' => new_expanded['last_updated_at'],
|
|
84
|
+
'file_hash' => new_expanded['file_hash'],
|
|
85
|
+
'data' => array_add(new_expanded['data'], old_expanded['data'])
|
|
86
|
+
}
|
|
87
|
+
end
|
|
88
|
+
|
|
46
89
|
def array_add(latest, original)
|
|
47
90
|
latest.map.with_index { |v, i| (v && original[i]) ? v + original[i] : nil }
|
|
48
91
|
end
|
|
92
|
+
|
|
93
|
+
def simple_report(report)
|
|
94
|
+
report.each_with_object({}) do |(key, extended_data), simple|
|
|
95
|
+
simple[key] = extended_data['data']
|
|
96
|
+
end
|
|
97
|
+
end
|
|
49
98
|
end
|
|
50
99
|
end
|
|
51
100
|
end
|
|
@@ -8,9 +8,8 @@ module Coverband
|
|
|
8
8
|
# Not recommended for production deployment
|
|
9
9
|
###
|
|
10
10
|
class FileStore < Base
|
|
11
|
-
attr_accessor :path
|
|
12
|
-
|
|
13
11
|
def initialize(path, _opts = {})
|
|
12
|
+
super()
|
|
14
13
|
@path = path
|
|
15
14
|
|
|
16
15
|
config_dir = File.dirname(@path)
|
|
@@ -21,32 +20,15 @@ module Coverband
|
|
|
21
20
|
File.delete(path) if File.exist?(path)
|
|
22
21
|
end
|
|
23
22
|
|
|
24
|
-
def save_report(report)
|
|
25
|
-
merge_reports(report, coverage)
|
|
26
|
-
save_coverage(report)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def coverage
|
|
30
|
-
existing_data(path)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def covered_files
|
|
34
|
-
report = existing_data(path)
|
|
35
|
-
existing_data(path).merge(report).keys || []
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def covered_lines_for_file(file)
|
|
39
|
-
report = existing_data(path)
|
|
40
|
-
report[file] || []
|
|
41
|
-
end
|
|
42
|
-
|
|
43
23
|
private
|
|
44
24
|
|
|
25
|
+
attr_accessor :path
|
|
26
|
+
|
|
45
27
|
def save_coverage(report)
|
|
46
28
|
File.open(path, 'w') { |f| f.write(report.to_json) }
|
|
47
29
|
end
|
|
48
30
|
|
|
49
|
-
def
|
|
31
|
+
def get_report
|
|
50
32
|
if File.exist?(path)
|
|
51
33
|
JSON.parse(File.read(path))
|
|
52
34
|
else
|
|
@@ -6,9 +6,10 @@ module Coverband
|
|
|
6
6
|
# RedisStore store a merged coverage file to redis
|
|
7
7
|
###
|
|
8
8
|
class RedisStore < Base
|
|
9
|
-
BASE_KEY = '
|
|
9
|
+
BASE_KEY = 'coverband3_1'
|
|
10
10
|
|
|
11
11
|
def initialize(redis, opts = {})
|
|
12
|
+
super()
|
|
12
13
|
@redis = redis
|
|
13
14
|
@ttl = opts[:ttl]
|
|
14
15
|
@redis_namespace = opts[:redis_namespace]
|
|
@@ -18,27 +19,6 @@ module Coverband
|
|
|
18
19
|
@redis.del(base_key)
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
def save_report(report)
|
|
22
|
-
# Note: This could lead to slight races
|
|
23
|
-
# where multiple processes pull the old coverage and add to it then push
|
|
24
|
-
# the Coverband 2 had the same issue,
|
|
25
|
-
# and the tradeoff has always been acceptable
|
|
26
|
-
merge_reports(report, coverage)
|
|
27
|
-
save_coverage(base_key, report)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def coverage
|
|
31
|
-
get_report(base_key)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def covered_files
|
|
35
|
-
coverage.keys
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def covered_lines_for_file(file)
|
|
39
|
-
coverage[file]
|
|
40
|
-
end
|
|
41
|
-
|
|
42
22
|
private
|
|
43
23
|
|
|
44
24
|
attr_reader :redis
|
|
@@ -47,13 +27,13 @@ module Coverband
|
|
|
47
27
|
@base_key ||= [BASE_KEY, @redis_namespace].compact.join('.')
|
|
48
28
|
end
|
|
49
29
|
|
|
50
|
-
def save_coverage(
|
|
51
|
-
redis.set
|
|
52
|
-
redis.expire(
|
|
30
|
+
def save_coverage(data)
|
|
31
|
+
redis.set base_key, data.to_json
|
|
32
|
+
redis.expire(base_key, @ttl) if @ttl
|
|
53
33
|
end
|
|
54
34
|
|
|
55
|
-
def get_report
|
|
56
|
-
data = redis.get
|
|
35
|
+
def get_report
|
|
36
|
+
data = redis.get base_key
|
|
57
37
|
data ? JSON.parse(data) : {}
|
|
58
38
|
end
|
|
59
39
|
end
|
|
@@ -17,23 +17,22 @@ module Coverband
|
|
|
17
17
|
def reset_instance
|
|
18
18
|
@project_directory = File.expand_path(Coverband.configuration.root)
|
|
19
19
|
@file_line_usage = {}
|
|
20
|
-
@ignored_files = Set.new
|
|
21
20
|
@ignore_patterns = Coverband.configuration.ignore + ['internal:prelude', 'schema.rb']
|
|
22
21
|
@reporting_frequency = Coverband.configuration.reporting_frequency
|
|
23
22
|
@store = Coverband.configuration.store
|
|
24
23
|
@verbose = Coverband.configuration.verbose
|
|
25
24
|
@logger = Coverband.configuration.logger
|
|
26
25
|
@current_thread = Thread.current
|
|
26
|
+
@test_env = Coverband.configuration.test_env
|
|
27
|
+
@@previous_results = nil
|
|
27
28
|
Thread.current[:coverband_instance] = nil
|
|
28
29
|
self
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
def report_coverage(force_report = false)
|
|
32
33
|
return if !ready_to_report? && !force_report
|
|
33
|
-
unless @store
|
|
34
|
-
|
|
35
|
-
return
|
|
36
|
-
end
|
|
34
|
+
raise 'no Coverband store set' unless @store
|
|
35
|
+
|
|
37
36
|
new_results = get_new_coverage_results
|
|
38
37
|
add_filtered_files(new_results)
|
|
39
38
|
@store.save_report(files_with_line_usage)
|
|
@@ -44,6 +43,7 @@ module Coverband
|
|
|
44
43
|
@logger.error "error: #{err.inspect} #{err.message}"
|
|
45
44
|
@logger.error err.backtrace
|
|
46
45
|
end
|
|
46
|
+
raise err if @test_env
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
protected
|
|
@@ -58,7 +58,6 @@ module Coverband
|
|
|
58
58
|
|
|
59
59
|
def add_filtered_files(new_results)
|
|
60
60
|
new_results.each_pair do |file, line_counts|
|
|
61
|
-
next if @ignored_files.include?(file)
|
|
62
61
|
next unless track_file?(file)
|
|
63
62
|
add_file(file, line_counts)
|
|
64
63
|
end
|
|
@@ -69,14 +68,12 @@ module Coverband
|
|
|
69
68
|
end
|
|
70
69
|
|
|
71
70
|
def get_new_coverage_results
|
|
72
|
-
|
|
73
|
-
@semaphore.synchronize { coverage_results = new_coverage(::Coverage.peek_result.dup) }
|
|
74
|
-
coverage_results
|
|
71
|
+
@semaphore.synchronize { new_coverage(::Coverage.peek_result.dup) }
|
|
75
72
|
end
|
|
76
73
|
|
|
77
74
|
def files_with_line_usage
|
|
78
75
|
@file_line_usage.select do |_file_name, coverage|
|
|
79
|
-
coverage.any? { |value| value
|
|
76
|
+
coverage.any? { |value| value&.nonzero? }
|
|
80
77
|
end
|
|
81
78
|
end
|
|
82
79
|
|
|
@@ -2,25 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
module Coverband
|
|
4
4
|
class Configuration
|
|
5
|
-
attr_accessor :
|
|
5
|
+
attr_accessor :root_paths, :root,
|
|
6
6
|
:ignore, :additional_files, :verbose,
|
|
7
7
|
:reporter, :reporting_frequency,
|
|
8
|
-
:disable_on_failure_for,
|
|
9
8
|
:redis_namespace, :redis_ttl,
|
|
10
|
-
:safe_reload_files
|
|
9
|
+
:safe_reload_files, :background_reporting_enabled,
|
|
10
|
+
:background_reporting_sleep_seconds, :test_env
|
|
11
11
|
|
|
12
12
|
attr_writer :logger, :s3_region, :s3_bucket, :s3_access_key_id, :s3_secret_access_key
|
|
13
13
|
|
|
14
14
|
def initialize
|
|
15
15
|
@root = Dir.pwd
|
|
16
16
|
@root_paths = []
|
|
17
|
-
@ignore =
|
|
17
|
+
@ignore = %w(vendor .erb$ .slim$)
|
|
18
18
|
@additional_files = []
|
|
19
19
|
@reporting_frequency = 0.0
|
|
20
20
|
@verbose = false
|
|
21
21
|
@reporter = 'scov'
|
|
22
|
-
@logger =
|
|
22
|
+
@logger = nil
|
|
23
23
|
@store = nil
|
|
24
|
+
@background_reporting_enabled = true
|
|
25
|
+
@background_reporting_sleep_seconds = 30
|
|
26
|
+
@test_env = nil
|
|
24
27
|
|
|
25
28
|
# TODO: should we push these to adapter configs
|
|
26
29
|
@s3_region = nil
|
|
@@ -32,7 +35,11 @@ module Coverband
|
|
|
32
35
|
end
|
|
33
36
|
|
|
34
37
|
def logger
|
|
35
|
-
@logger ||=
|
|
38
|
+
@logger ||= if defined?(Rails)
|
|
39
|
+
Rails.logger
|
|
40
|
+
else
|
|
41
|
+
Logger.new(STDOUT)
|
|
42
|
+
end
|
|
36
43
|
end
|
|
37
44
|
|
|
38
45
|
def s3_bucket
|
|
@@ -52,19 +59,26 @@ module Coverband
|
|
|
52
59
|
end
|
|
53
60
|
|
|
54
61
|
def store
|
|
55
|
-
|
|
56
|
-
raise 'no valid store configured'
|
|
62
|
+
@store ||= Coverband::Adapters::RedisStore.new(Redis.new(url: redis_url), redis_store_options)
|
|
57
63
|
end
|
|
58
64
|
|
|
59
65
|
def store=(store)
|
|
60
66
|
if store.is_a?(Coverband::Adapters::Base)
|
|
61
67
|
@store = store
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
redis_namespace: Coverband.configuration.redis_namespace)
|
|
65
|
-
elsif store.is_a?(String)
|
|
66
|
-
@store = Coverband::Adapters::FileStore.new(store)
|
|
68
|
+
else
|
|
69
|
+
raise 'please pass in an subclass of Coverband::Adapters for supported stores'
|
|
67
70
|
end
|
|
68
71
|
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def redis_url
|
|
76
|
+
ENV['COVERBAND_REDIS_URL'] || ENV['REDIS_URL']
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def redis_store_options
|
|
80
|
+
{ ttl: Coverband.configuration.redis_ttl,
|
|
81
|
+
redis_namespace: Coverband.configuration.redis_namespace }
|
|
82
|
+
end
|
|
69
83
|
end
|
|
70
84
|
end
|
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
module Coverband
|
|
4
4
|
class Background
|
|
5
|
-
|
|
5
|
+
@semaphore = Mutex.new
|
|
6
|
+
|
|
7
|
+
def self.start
|
|
8
|
+
return if @background_reporting_running
|
|
9
|
+
|
|
10
|
+
logger = Coverband.configuration.logger
|
|
11
|
+
@semaphore.synchronize do
|
|
12
|
+
return if @background_reporting_running
|
|
13
|
+
logger&.debug('Coverband: Starting background reporting')
|
|
14
|
+
|
|
15
|
+
@background_reporting_running = true
|
|
16
|
+
sleep_seconds = Coverband.configuration.background_reporting_sleep_seconds
|
|
17
|
+
Thread.new do
|
|
18
|
+
loop do
|
|
19
|
+
Coverband::Collectors::Coverage.instance.report_coverage(true)
|
|
20
|
+
logger&.debug("Coverband: Reported coverage via thread. Sleeping #{sleep_seconds}s") if Coverband.configuration.verbose
|
|
21
|
+
sleep(sleep_seconds)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
at_exit do
|
|
26
|
+
Coverband::Collectors::Coverage.instance.report_coverage(true)
|
|
27
|
+
logger&.debug('Coverband: Reported coverage before exit')
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
6
31
|
end
|
|
7
32
|
end
|
|
@@ -9,7 +9,11 @@ module Coverband
|
|
|
9
9
|
def call(env)
|
|
10
10
|
@app.call(env)
|
|
11
11
|
ensure
|
|
12
|
-
Coverband
|
|
12
|
+
if Coverband.configuration.background_reporting_enabled
|
|
13
|
+
Coverband::Background.start
|
|
14
|
+
else
|
|
15
|
+
Coverband::Collectors::Coverage.instance.report_coverage
|
|
16
|
+
end
|
|
13
17
|
end
|
|
14
18
|
end
|
|
15
19
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coverband
|
|
4
|
+
class RackServerCheck
|
|
5
|
+
def self.running?
|
|
6
|
+
new(Kernel.caller_locations).running?
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize(stack)
|
|
10
|
+
@stack = stack
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def running?
|
|
14
|
+
rack_server? || rails_server?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def rack_server?
|
|
18
|
+
@stack.any? { |line| line.path.include?('lib/rack/') }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def rails_server?
|
|
22
|
+
@stack.any? do |location|
|
|
23
|
+
location.path.include?('rails/commands/commands_tasks.rb') && location.label == 'server'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -38,13 +38,7 @@ module Coverband
|
|
|
38
38
|
Coverband.configuration.logger.info "report is ready and viewable: open #{SimpleCov.coverage_dir}/index.html"
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
region: Coverband.configuration.s3_region,
|
|
43
|
-
access_key_id: Coverband.configuration.s3_access_key_id,
|
|
44
|
-
secret_access_key: Coverband.configuration.s3_secret_access_key
|
|
45
|
-
}
|
|
46
|
-
Coverband::Utils::S3ReportWriter.new(Coverband.configuration.s3_bucket,
|
|
47
|
-
s3_writer_options).persist! if Coverband.configuration.s3_bucket
|
|
41
|
+
Coverband::Utils::S3Report.instance.persist! if Coverband.configuration.s3_bucket
|
|
48
42
|
end
|
|
49
43
|
end
|
|
50
44
|
end
|
|
@@ -71,7 +71,7 @@ module Coverband
|
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def show
|
|
74
|
-
html =
|
|
74
|
+
html = Coverband::Utils::S3Report.instance.retrieve
|
|
75
75
|
# HACK: the static HTML assets to link to the path where this was mounted
|
|
76
76
|
html = html.gsub("src='", "src='#{base_path}")
|
|
77
77
|
html = html.gsub("href='", "href='#{base_path}")
|
|
@@ -93,7 +93,7 @@ module Coverband
|
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
def collect_coverage
|
|
96
|
-
Coverband::Collectors::Coverage.instance.report_coverage
|
|
96
|
+
Coverband::Collectors::Coverage.instance.report_coverage(true)
|
|
97
97
|
notice = 'coverband coverage collected'
|
|
98
98
|
[301, { 'Location' => "#{base_path}?notice=#{notice}" }, []]
|
|
99
99
|
end
|
|
@@ -126,30 +126,12 @@ module Coverband
|
|
|
126
126
|
|
|
127
127
|
# This method should get the root mounted endpoint
|
|
128
128
|
# for example if the app is mounted like so:
|
|
129
|
-
# mount Coverband::
|
|
129
|
+
# mount Coverband::Web, at: '/coverage'
|
|
130
130
|
# "/coverage/collect_coverage?" become:
|
|
131
131
|
# /coverage/
|
|
132
132
|
def base_path
|
|
133
133
|
request.path.match("\/.*\/") ? request.path.match("\/.*\/")[0] : '/'
|
|
134
134
|
end
|
|
135
|
-
|
|
136
|
-
def s3
|
|
137
|
-
begin
|
|
138
|
-
require 'aws-sdk'
|
|
139
|
-
rescue StandardError
|
|
140
|
-
Coverband.configuration.logger.error "coverband requires 'aws-sdk' in order use S3ReportWriter."
|
|
141
|
-
return
|
|
142
|
-
end
|
|
143
|
-
@s3 ||= begin
|
|
144
|
-
client_options = {
|
|
145
|
-
region: Coverband.configuration.s3_region,
|
|
146
|
-
access_key_id: Coverband.configuration.s3_access_key_id,
|
|
147
|
-
secret_access_key: Coverband.configuration.s3_secret_access_key
|
|
148
|
-
}
|
|
149
|
-
client_options = {} if client_options.values.any?(&:nil?)
|
|
150
|
-
Aws::S3::Client.new(client_options)
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
135
|
end
|
|
154
136
|
end
|
|
155
137
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coverband
|
|
4
|
+
class Railtie < Rails::Railtie
|
|
5
|
+
initializer 'coverband.configure' do |app|
|
|
6
|
+
app.middleware.use Coverband::Middleware
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
config.after_initialize do
|
|
10
|
+
Coverband::Collectors::Coverage.instance.report_coverage(true)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
rake_tasks do
|
|
14
|
+
load 'coverband/utils/tasks.rb'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|