coverband 4.2.6 → 5.0.0.rc.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.standard.yml +26 -0
- data/.travis.yml +2 -1
- data/Gemfile +5 -7
- data/Gemfile.rails4 +0 -3
- data/Gemfile.rails6 +0 -3
- data/README.md +24 -77
- data/Rakefile +17 -17
- data/changes.md +30 -28
- data/config.ru +1 -1
- data/coverband.gemspec +31 -34
- data/lib/alternative_coverband_patch.rb +5 -0
- data/lib/coverband.rb +68 -44
- data/lib/coverband/adapters/base.rb +17 -18
- data/lib/coverband/adapters/file_store.rb +38 -6
- data/lib/coverband/adapters/hash_redis_store.rb +24 -21
- data/lib/coverband/adapters/redis_store.rb +12 -12
- data/lib/coverband/adapters/stdout_store.rb +41 -0
- data/lib/coverband/adapters/web_service_store.rb +155 -0
- data/lib/coverband/at_exit.rb +1 -1
- data/lib/coverband/collectors/coverage.rb +15 -27
- data/lib/coverband/collectors/delta.rb +29 -9
- data/lib/coverband/collectors/view_tracker.rb +10 -10
- data/lib/coverband/collectors/view_tracker_service.rb +59 -0
- data/lib/coverband/configuration.rb +150 -113
- data/lib/coverband/integrations/background.rb +6 -6
- data/lib/coverband/integrations/rack_server_check.rb +3 -3
- data/lib/coverband/integrations/resque.rb +13 -1
- data/lib/coverband/reporters/base.rb +11 -12
- data/lib/coverband/reporters/console_report.rb +1 -1
- data/lib/coverband/reporters/html_report.rb +10 -30
- data/lib/coverband/reporters/web.rb +55 -50
- data/lib/coverband/utils/absolute_file_converter.rb +6 -6
- data/lib/coverband/utils/html_formatter.rb +32 -61
- data/lib/coverband/utils/railtie.rb +23 -6
- data/lib/coverband/utils/relative_file_converter.rb +2 -2
- data/lib/coverband/utils/result.rb +6 -11
- data/lib/coverband/utils/results.rb +0 -10
- data/lib/coverband/utils/source_file.rb +21 -30
- data/lib/coverband/utils/tasks.rb +8 -11
- data/lib/coverband/version.rb +1 -1
- data/public/application.js +0 -30
- data/test/benchmarks/benchmark.rake +97 -92
- data/test/benchmarks/dog.rb +1 -1
- data/test/benchmarks/init_rails.rake +4 -4
- data/test/coverband/adapters/base_test.rb +29 -30
- data/test/coverband/adapters/file_store_test.rb +19 -20
- data/test/coverband/adapters/hash_redis_store_test.rb +57 -57
- data/test/coverband/adapters/redis_store_test.rb +26 -26
- data/test/coverband/adapters/web_service_store_test.rb +56 -0
- data/test/coverband/at_exit_test.rb +2 -2
- data/test/coverband/collectors/coverage_test.rb +33 -47
- data/test/coverband/collectors/delta_test.rb +52 -23
- data/test/coverband/collectors/view_tracker_test.rb +35 -35
- data/test/coverband/configuration_test.rb +61 -48
- data/test/coverband/coverband_test.rb +11 -11
- data/test/coverband/integrations/background_middleware_test.rb +10 -10
- data/test/coverband/integrations/background_test.rb +17 -5
- data/test/coverband/integrations/rack_server_check_test.rb +7 -7
- data/test/coverband/integrations/report_middleware_test.rb +9 -9
- data/test/coverband/integrations/resque_worker_test.rb +9 -9
- data/test/coverband/integrations/test_resque_job.rb +1 -1
- data/test/coverband/reporters/base_test.rb +9 -9
- data/test/coverband/reporters/console_test.rb +6 -6
- data/test/coverband/reporters/html_test.rb +36 -48
- data/test/coverband/reporters/web_test.rb +16 -18
- data/test/coverband/utils/absolute_file_converter_test.rb +22 -22
- data/test/coverband/utils/file_hasher_test.rb +6 -12
- data/test/coverband/utils/file_list_test.rb +13 -13
- data/test/coverband/utils/html_formatter_test.rb +9 -23
- data/test/coverband/utils/lines_classifier_test.rb +29 -29
- data/test/coverband/utils/relative_file_converter_test.rb +13 -13
- data/test/coverband/utils/result_test.rb +18 -18
- data/test/coverband/utils/results_test.rb +17 -17
- data/test/coverband/utils/source_file_line_test.rb +46 -46
- data/test/coverband/utils/source_file_test.rb +38 -88
- data/test/dog.rb +1 -1
- data/test/fake_app/basic_rack.rb +2 -2
- data/test/fixtures/app/controllers/sample_controller.rb +1 -1
- data/test/fixtures/app/models/user.rb +1 -1
- data/test/fixtures/sample.rb +1 -1
- data/test/fixtures/utf-8.rb +0 -2
- data/test/forked/rails_full_stack_test.rb +24 -27
- data/test/forked/rails_rake_full_stack_test.rb +7 -26
- data/test/integration/full_stack_test.rb +11 -22
- data/test/jruby_check.rb +2 -3
- data/test/rails4_dummy/Rakefile +1 -1
- data/test/rails4_dummy/config.ru +1 -1
- data/test/rails4_dummy/config/application.rb +4 -4
- data/test/rails4_dummy/config/boot.rb +2 -2
- data/test/rails4_dummy/config/coverband.rb +1 -1
- data/test/rails4_dummy/config/coverband_missing_redis.rb +1 -1
- data/test/rails4_dummy/config/environment.rb +1 -1
- data/test/rails4_dummy/config/routes.rb +2 -2
- data/test/rails5_dummy/Rakefile +1 -1
- data/test/rails5_dummy/config.ru +1 -1
- data/test/rails5_dummy/config/application.rb +3 -3
- data/test/rails5_dummy/config/coverband.rb +8 -8
- data/test/rails5_dummy/config/coverband_missing_redis.rb +8 -8
- data/test/rails5_dummy/config/environment.rb +1 -1
- data/test/rails5_dummy/config/routes.rb +2 -2
- data/test/rails6_dummy/Rakefile +1 -1
- data/test/rails6_dummy/config.ru +1 -1
- data/test/rails6_dummy/config/application.rb +4 -4
- data/test/rails6_dummy/config/boot.rb +2 -2
- data/test/rails6_dummy/config/coverband.rb +1 -1
- data/test/rails6_dummy/config/coverband_missing_redis.rb +1 -1
- data/test/rails6_dummy/config/environment.rb +1 -1
- data/test/rails6_dummy/config/routes.rb +2 -2
- data/test/rails_test_helper.rb +11 -11
- data/test/test_helper.rb +44 -34
- data/test/unique_files.rb +10 -10
- data/views/layout.erb +2 -12
- metadata +29 -34
- data/.rubocop.yml +0 -84
- data/lib/coverband/integrations/bundler.rb +0 -8
- data/lib/coverband/utils/file_groups.rb +0 -53
- data/lib/coverband/utils/gem_list.rb +0 -31
- data/lib/coverband/utils/s3_report.rb +0 -105
- data/test/coverband/utils/file_groups_test.rb +0 -61
- data/test/coverband/utils/gem_list_test.rb +0 -48
- data/test/coverband/utils/s3_report_test.rb +0 -44
- data/views/gem_list.erb +0 -63
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coverband
|
4
|
+
module Adapters
|
5
|
+
###
|
6
|
+
# StdoutStore is for testing and development
|
7
|
+
#
|
8
|
+
# Usage:
|
9
|
+
# config.store = Coverband::Adapters::StdoutStore.new
|
10
|
+
###
|
11
|
+
class StdoutStore < Base
|
12
|
+
def initialize(_opts = {})
|
13
|
+
super()
|
14
|
+
end
|
15
|
+
|
16
|
+
def clear!
|
17
|
+
# NOOP
|
18
|
+
end
|
19
|
+
|
20
|
+
def size
|
21
|
+
0
|
22
|
+
end
|
23
|
+
|
24
|
+
def migrate!
|
25
|
+
raise NotImplementedError, "StdoutStore doesn't support migrations"
|
26
|
+
end
|
27
|
+
|
28
|
+
def coverage(_local_type = nil)
|
29
|
+
{}
|
30
|
+
end
|
31
|
+
|
32
|
+
def save_report(report)
|
33
|
+
$stdout.puts(report.to_json)
|
34
|
+
end
|
35
|
+
|
36
|
+
def raw_store
|
37
|
+
raise NotImplementedError, "StdoutStore doesn't support raw_store"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coverband
|
4
|
+
module Adapters
|
5
|
+
###
|
6
|
+
# WebServiceStore: store a checkpoint of coverage to a remote service
|
7
|
+
###
|
8
|
+
class WebServiceStore < Base
|
9
|
+
attr_reader :coverband_url, :process_type, :runtime_env, :hostname, :pid
|
10
|
+
|
11
|
+
def initialize(coverband_url, opts = {})
|
12
|
+
super()
|
13
|
+
require "socket"
|
14
|
+
require "securerandom"
|
15
|
+
@coverband_url = coverband_url
|
16
|
+
@process_type = opts.fetch(:process_type) { $PROGRAM_NAME&.split("/")&.last || Coverband.configuration.process_type }
|
17
|
+
@hostname = opts.fetch(:hostname) { ENV["DYNO"] || Socket.gethostname.force_encoding("utf-8").encode }
|
18
|
+
@hostname = @hostname.delete("'", "").delete("’", "")
|
19
|
+
@runtime_env = opts.fetch(:runtime_env) { Coverband.configuration.coverband_env }
|
20
|
+
@failed_coverage_reports = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def logger
|
24
|
+
Coverband.configuration.logger
|
25
|
+
end
|
26
|
+
|
27
|
+
def clear!
|
28
|
+
# done via service UI
|
29
|
+
raise "not supported via service"
|
30
|
+
end
|
31
|
+
|
32
|
+
def clear_file!(filename)
|
33
|
+
# done via service UI
|
34
|
+
raise "not supported via service"
|
35
|
+
end
|
36
|
+
|
37
|
+
# NOTE: Should support nil to mean not supported
|
38
|
+
# the size feature doesn't really makde sense for the service
|
39
|
+
def size
|
40
|
+
0
|
41
|
+
end
|
42
|
+
|
43
|
+
###
|
44
|
+
# Fetch coverband coverage via the API
|
45
|
+
# This would allow one to expore from the service and move back to the open source
|
46
|
+
# without having to reset coverage
|
47
|
+
###
|
48
|
+
def coverage(local_type = nil, opts = {})
|
49
|
+
return if Coverband.configuration.service_disabled_dev_test_env?
|
50
|
+
|
51
|
+
local_type ||= opts.key?(:override_type) ? opts[:override_type] : type
|
52
|
+
env_filter = opts.key?(:env_filter) ? opts[:env_filter] : "production"
|
53
|
+
uri = URI("#{coverband_url}/api/coverage?type=#{local_type}&env_filter=#{env_filter}")
|
54
|
+
req = Net::HTTP::Get.new(uri, "Content-Type" => "application/json", "Coverband-Token" => Coverband.configuration.api_key)
|
55
|
+
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
|
56
|
+
http.request(req)
|
57
|
+
end
|
58
|
+
JSON.parse(res.body)
|
59
|
+
rescue => e
|
60
|
+
logger&.error "Coverband: Error while retrieving coverage #{e}" if Coverband.configuration.verbose || Coverband.configuration.service_dev_mode
|
61
|
+
end
|
62
|
+
|
63
|
+
def save_report(report)
|
64
|
+
return if report.empty?
|
65
|
+
|
66
|
+
# We set here vs initialize to avoid setting on the primary process vs child processes
|
67
|
+
@pid ||= ::Process.pid
|
68
|
+
|
69
|
+
# TODO: do we need dup
|
70
|
+
# TODO: we don't need upstream timestamps, server will track first_seen
|
71
|
+
Thread.new do
|
72
|
+
data = expand_report(report.dup)
|
73
|
+
full_package = {
|
74
|
+
collection_type: "coverage_delta",
|
75
|
+
collection_data: {
|
76
|
+
tags: {
|
77
|
+
process_type: process_type,
|
78
|
+
app_loading: type == Coverband::EAGER_TYPE,
|
79
|
+
runtime_env: runtime_env,
|
80
|
+
pid: pid,
|
81
|
+
hostname: hostname
|
82
|
+
},
|
83
|
+
file_coverage: data
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
save_coverage(full_package)
|
88
|
+
retry_failed_reports
|
89
|
+
end&.join
|
90
|
+
end
|
91
|
+
|
92
|
+
def raw_store
|
93
|
+
raise "not supported via service"
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def retry_failed_reports
|
99
|
+
retries = []
|
100
|
+
@failed_coverage_reports.any? do
|
101
|
+
begin
|
102
|
+
report_body = @failed_coverage_reports.pop
|
103
|
+
send_report_body(report_body)
|
104
|
+
rescue
|
105
|
+
retries << report_body
|
106
|
+
end
|
107
|
+
end
|
108
|
+
retries.each do |report_body|
|
109
|
+
add_retry_message(report_body)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def add_retry_message(report_body)
|
114
|
+
if @failed_coverage_reports.length > 5
|
115
|
+
logger&.info "Coverband: The errored reporting queue has reached 5. Subsequent reports will not be transmitted"
|
116
|
+
else
|
117
|
+
@failed_coverage_reports << report_body
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def save_coverage(data)
|
122
|
+
if Coverband.configuration.api_key.nil?
|
123
|
+
puts "Coverband: Error: no Coverband API key was found!"
|
124
|
+
return
|
125
|
+
end
|
126
|
+
|
127
|
+
coverage_body = {remote_uuid: SecureRandom.uuid, data: data}.to_json
|
128
|
+
send_report_body(coverage_body)
|
129
|
+
rescue => e
|
130
|
+
add_retry_message(coverage_body)
|
131
|
+
logger&.info "Coverband: Error while saving coverage #{e}" if Coverband.configuration.verbose || Coverband.configuration.service_dev_mode
|
132
|
+
end
|
133
|
+
|
134
|
+
def send_report_body(coverage_body)
|
135
|
+
uri = URI("#{coverband_url}/api/collector")
|
136
|
+
req = ::Net::HTTP::Post.new(uri, "Content-Type" => "application/json", "Coverband-Token" => Coverband.configuration.api_key)
|
137
|
+
req.body = coverage_body
|
138
|
+
logger&.info "Coverband: saving (#{uri}) #{req.body}" if Coverband.configuration.verbose
|
139
|
+
res = ::Net::HTTP.start(
|
140
|
+
uri.hostname,
|
141
|
+
uri.port,
|
142
|
+
open_timeout: Coverband.configuration.coverband_timeout,
|
143
|
+
read_timeout: Coverband.configuration.coverband_timeout,
|
144
|
+
ssl_timeout: Coverband.configuration.coverband_timeout,
|
145
|
+
use_ssl: uri.scheme == "https"
|
146
|
+
) do |http|
|
147
|
+
http.request(req)
|
148
|
+
end
|
149
|
+
if res.code.to_i >= 500
|
150
|
+
add_retry_message(coverage_body)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
data/lib/coverband/at_exit.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require_relative
|
3
|
+
require "singleton"
|
4
|
+
require_relative "delta"
|
5
5
|
|
6
6
|
module Coverband
|
7
7
|
module Collectors
|
@@ -25,7 +25,6 @@ module Coverband
|
|
25
25
|
@verbose = Coverband.configuration.verbose
|
26
26
|
@logger = Coverband.configuration.logger
|
27
27
|
@test_env = Coverband.configuration.test_env
|
28
|
-
@track_gems = Coverband.configuration.track_gems
|
29
28
|
Delta.reset
|
30
29
|
self
|
31
30
|
end
|
@@ -49,53 +48,42 @@ module Coverband
|
|
49
48
|
|
50
49
|
def report_coverage
|
51
50
|
@semaphore.synchronize do
|
52
|
-
raise
|
51
|
+
raise "no Coverband store set" unless @store
|
53
52
|
|
54
53
|
files_with_line_usage = filtered_files(Delta.results)
|
55
54
|
@store.save_report(files_with_line_usage)
|
56
55
|
end
|
57
|
-
rescue
|
58
|
-
@logger&.error
|
56
|
+
rescue => e
|
57
|
+
@logger&.error "coverage failed to store"
|
59
58
|
@logger&.error "Coverband Error: #{e.inspect} #{e.message}"
|
60
59
|
e.backtrace.each { |line| @logger&.error line } if @verbose
|
61
60
|
raise e if @test_env
|
62
61
|
end
|
63
62
|
|
64
|
-
protected
|
65
|
-
|
66
|
-
###
|
67
|
-
# Normally I would break this out into additional methods
|
68
|
-
# and improve the readability but this is in a tight loop
|
69
|
-
# on the critical performance path, and any refactoring I come up with
|
70
|
-
# would slow down the performance.
|
71
|
-
###
|
72
|
-
def track_file?(file)
|
73
|
-
@ignore_patterns.none? do |pattern|
|
74
|
-
file.match(pattern)
|
75
|
-
end && (file.start_with?(@project_directory) ||
|
76
|
-
(@track_gems &&
|
77
|
-
Coverband.configuration.gem_paths.any? { |path| file.start_with?(path) }))
|
78
|
-
end
|
79
|
-
|
80
63
|
private
|
81
64
|
|
82
65
|
def filtered_files(new_results)
|
83
|
-
new_results.select! { |
|
66
|
+
new_results.select! { |_file, coverage| coverage.any? { |value| value&.nonzero? } }
|
84
67
|
new_results
|
85
68
|
end
|
86
69
|
|
87
70
|
def initialize
|
88
71
|
@semaphore = Mutex.new
|
89
|
-
raise NotImplementedError,
|
72
|
+
raise NotImplementedError, "Coverage needs Ruby > 2.3.0" if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.3.0")
|
90
73
|
|
91
|
-
require
|
74
|
+
require "coverage"
|
75
|
+
if RUBY_PLATFORM == "java"
|
76
|
+
unless ::Coverage.respond_to?(:line_stub)
|
77
|
+
require "coverband/utils/jruby_ext"
|
78
|
+
end
|
79
|
+
end
|
92
80
|
if defined?(SimpleCov) && defined?(Rails) && defined?(Rails.env) && Rails.env.test?
|
93
81
|
puts "Coverband: detected SimpleCov in test Env, allowing it to start Coverage"
|
94
82
|
puts "Coverband: to ensure no error logs or missing Coverage call `SimpleCov.start` prior to requiring Coverband"
|
95
83
|
else
|
96
|
-
if Coverage.ruby_version_greater_than_or_equal_to?(
|
84
|
+
if Coverage.ruby_version_greater_than_or_equal_to?("2.6.0")
|
97
85
|
::Coverage.start(oneshot_lines: Coverband.configuration.use_oneshot_lines_coverage) unless ::Coverage.running?
|
98
|
-
elsif Coverage.ruby_version_greater_than_or_equal_to?(
|
86
|
+
elsif Coverage.ruby_version_greater_than_or_equal_to?("2.5.0")
|
99
87
|
::Coverage.start unless ::Coverage.running?
|
100
88
|
else
|
101
89
|
::Coverage.start
|
@@ -39,23 +39,33 @@ module Coverband
|
|
39
39
|
|
40
40
|
def self.reset
|
41
41
|
@@previous_coverage = {}
|
42
|
+
@@project_directory = File.expand_path(Coverband.configuration.root)
|
43
|
+
@@ignore_patterns = Coverband.configuration.ignore
|
42
44
|
end
|
43
45
|
|
44
46
|
private
|
45
47
|
|
46
48
|
def generate
|
47
|
-
# TODO: if we filtered before doing this we would avoid calculating the line diff on a ton of files
|
48
|
-
# This would be a fairly noticeable perf win
|
49
49
|
current_coverage.each_with_object({}) do |(file, line_counts), new_results|
|
50
|
+
###
|
51
|
+
# Eager filter:
|
52
|
+
# Normally I would break this out into additional methods
|
53
|
+
# and improve the readability but this is in a tight loop
|
54
|
+
# on the critical performance path, and any refactoring I come up with
|
55
|
+
# would slow down the performance.
|
56
|
+
###
|
57
|
+
next unless @@ignore_patterns.none? { |pattern| file.match(pattern) } &&
|
58
|
+
file.start_with?(@@project_directory)
|
59
|
+
|
50
60
|
# This handles Coverage branch support, setup by default in
|
51
61
|
# simplecov 0.18.x
|
52
62
|
arr_line_counts = line_counts.is_a?(Hash) ? line_counts[:lines] : line_counts
|
53
63
|
new_results[file] = if @@previous_coverage && @@previous_coverage[file]
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
64
|
+
prev_line_counts = @@previous_coverage[file].is_a?(Hash) ? @@previous_coverage[file][:lines] : @@previous_coverage[file]
|
65
|
+
array_diff(arr_line_counts, prev_line_counts)
|
66
|
+
else
|
67
|
+
arr_line_counts
|
68
|
+
end
|
59
69
|
end
|
60
70
|
end
|
61
71
|
|
@@ -67,10 +77,20 @@ module Coverband
|
|
67
77
|
|
68
78
|
def transform_oneshot_lines_results(results)
|
69
79
|
results.each_with_object({}) do |(file, coverage), new_results|
|
80
|
+
###
|
81
|
+
# Eager filter:
|
82
|
+
# Normally I would break this out into additional methods
|
83
|
+
# and improve the readability but this is in a tight loop
|
84
|
+
# on the critical performance path, and any refactoring I come up with
|
85
|
+
# would slow down the performance.
|
86
|
+
###
|
87
|
+
next unless @@ignore_patterns.none? { |pattern| file.match(pattern) } &&
|
88
|
+
file.start_with?(@@project_directory)
|
89
|
+
|
70
90
|
@@stubs[file] ||= ::Coverage.line_stub(file)
|
71
|
-
transformed_line_counts = coverage[:oneshot_lines].each_with_object(@@stubs[file].dup)
|
91
|
+
transformed_line_counts = coverage[:oneshot_lines].each_with_object(@@stubs[file].dup) { |line_number, line_counts|
|
72
92
|
line_counts[line_number - 1] = 1
|
73
|
-
|
93
|
+
}
|
74
94
|
new_results[file] = transformed_line_counts
|
75
95
|
end
|
76
96
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "singleton"
|
4
4
|
|
5
5
|
module Coverband
|
6
6
|
module Collectors
|
@@ -14,12 +14,12 @@ module Coverband
|
|
14
14
|
# TODO: test and ensure slim, haml, and other support
|
15
15
|
###
|
16
16
|
class ViewTracker
|
17
|
-
DEFAULT_TARGET = Dir.glob(
|
17
|
+
DEFAULT_TARGET = Dir.glob("app/views/**/*.html.erb").reject { |file| file.match(/(_mailer)/) }
|
18
18
|
attr_accessor :target, :logged_views, :views_to_record
|
19
19
|
attr_reader :logger, :roots, :store, :ignore_patterns
|
20
20
|
|
21
21
|
def initialize(options = {})
|
22
|
-
raise NotImplementedError,
|
22
|
+
raise NotImplementedError, "View Tracker requires Rails 4 or greater" unless self.class.supported_version?
|
23
23
|
|
24
24
|
@project_directory = File.expand_path(Coverband.configuration.root)
|
25
25
|
@ignore_patterns = Coverband.configuration.ignore
|
@@ -28,7 +28,7 @@ module Coverband
|
|
28
28
|
@target = options.fetch(:target) { DEFAULT_TARGET }
|
29
29
|
|
30
30
|
@roots = options.fetch(:roots) { Coverband.configuration.all_root_patterns }
|
31
|
-
@roots = @roots.split(
|
31
|
+
@roots = @roots.split(",") if @roots.is_a?(String)
|
32
32
|
@one_time_timestamp = false
|
33
33
|
|
34
34
|
@logged_views = []
|
@@ -65,7 +65,7 @@ module Coverband
|
|
65
65
|
normalized_views = {}
|
66
66
|
views.each_pair do |view, time|
|
67
67
|
roots.each do |root|
|
68
|
-
view = view.gsub(/#{root}/,
|
68
|
+
view = view.gsub(/#{root}/, "")
|
69
69
|
end
|
70
70
|
normalized_views[view] = time
|
71
71
|
end
|
@@ -90,7 +90,7 @@ module Coverband
|
|
90
90
|
if (tracking_time = redis_store.get(tracker_time_key))
|
91
91
|
Time.at(tracking_time.to_i).iso8601
|
92
92
|
else
|
93
|
-
|
93
|
+
"N/A"
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
@@ -115,14 +115,14 @@ module Coverband
|
|
115
115
|
redis_store.hset(tracker_key, file, reported_time)
|
116
116
|
end
|
117
117
|
self.views_to_record = []
|
118
|
-
rescue
|
118
|
+
rescue => e
|
119
119
|
# we don't want to raise errors if Coverband can't reach redis.
|
120
120
|
# This is a nice to have not a bring the system down
|
121
121
|
logger&.error "Coverband: view_tracker failed to store, error #{e.class.name}"
|
122
122
|
end
|
123
123
|
|
124
124
|
def self.supported_version?
|
125
|
-
defined?(Rails) && defined?(Rails::VERSION) && Rails::VERSION::STRING.split(
|
125
|
+
defined?(Rails) && defined?(Rails::VERSION) && Rails::VERSION::STRING.split(".").first.to_i >= 4
|
126
126
|
end
|
127
127
|
|
128
128
|
protected
|
@@ -154,11 +154,11 @@ module Coverband
|
|
154
154
|
end
|
155
155
|
|
156
156
|
def tracker_key
|
157
|
-
|
157
|
+
"render_tracker_2"
|
158
158
|
end
|
159
159
|
|
160
160
|
def tracker_time_key
|
161
|
-
|
161
|
+
"render_tracker_time"
|
162
162
|
end
|
163
163
|
end
|
164
164
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coverband
|
4
|
+
module Collectors
|
5
|
+
###
|
6
|
+
# This class extends view tracker to support web service reporting
|
7
|
+
###
|
8
|
+
class ViewTrackerService < ViewTracker
|
9
|
+
def report_views_tracked
|
10
|
+
reported_time = Time.now.to_i
|
11
|
+
if views_to_record.any?
|
12
|
+
relative_views = views_to_record.map! do |view|
|
13
|
+
roots.each do |root|
|
14
|
+
view = view.gsub(/#{root}/, "")
|
15
|
+
end
|
16
|
+
view
|
17
|
+
end
|
18
|
+
save_tracked_views(views: relative_views, reported_time: reported_time)
|
19
|
+
end
|
20
|
+
self.views_to_record = []
|
21
|
+
rescue => e
|
22
|
+
# we don't want to raise errors if Coverband can't reach the service
|
23
|
+
logger&.error "Coverband: view_tracker failed to store, error #{e.class.name}" if Coverband.configuration.verbose || Coverband.configuration.service_dev_mode
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.supported_version?
|
27
|
+
defined?(Rails) && defined?(Rails::VERSION) && Rails::VERSION::STRING.split(".").first.to_i >= 4
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def logger
|
33
|
+
Coverband.configuration.logger
|
34
|
+
end
|
35
|
+
|
36
|
+
def save_tracked_views(views:, reported_time:)
|
37
|
+
uri = URI("#{Coverband.configuration.service_url}/api/collector")
|
38
|
+
req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json", "Coverband-Token" => Coverband.configuration.api_key)
|
39
|
+
data = {
|
40
|
+
collection_type: "view_tracker_delta",
|
41
|
+
collection_data: {
|
42
|
+
tags: {
|
43
|
+
runtime_env: Coverband.configuration.coverband_env
|
44
|
+
},
|
45
|
+
collection_time: reported_time,
|
46
|
+
tracked_views: views
|
47
|
+
}
|
48
|
+
}
|
49
|
+
# puts "sending #{data}"
|
50
|
+
req.body = {remote_uuid: SecureRandom.uuid, data: data}.to_json
|
51
|
+
Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
|
52
|
+
http.request(req)
|
53
|
+
end
|
54
|
+
rescue => e
|
55
|
+
logger&.error "Coverband: Error while saving coverage #{e}" if Coverband.configuration.verbose || Coverband.configuration.service_dev_mode
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|