coverband 6.0.2 → 6.0.3.rc.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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +10 -0
- data/.github/workflows/main.yml +2 -3
- data/.standard.yml +1 -1
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/README.md +3 -2
- data/Rakefile +1 -1
- data/changes.md +1 -1
- data/coverband.gemspec +3 -3
- data/lib/coverband/adapters/base.rb +10 -10
- data/lib/coverband/adapters/file_store.rb +1 -1
- data/lib/coverband/adapters/hash_redis_store.rb +69 -15
- data/lib/coverband/adapters/null_store.rb +1 -1
- data/lib/coverband/adapters/stdout_store.rb +1 -1
- data/lib/coverband/adapters/web_service_store.rb +5 -7
- data/lib/coverband/collectors/route_tracker.rb +1 -1
- data/lib/coverband/collectors/translation_tracker.rb +2 -2
- data/lib/coverband/collectors/view_tracker.rb +1 -1
- data/lib/coverband/configuration.rb +5 -5
- data/lib/coverband/integrations/rack_server_check.rb +1 -3
- data/lib/coverband/reporters/base.rb +7 -7
- data/lib/coverband/reporters/html_report.rb +12 -4
- data/lib/coverband/reporters/json_report.rb +42 -4
- data/lib/coverband/reporters/web.rb +16 -2
- data/lib/coverband/reporters/web_pager.rb +28 -0
- data/lib/coverband/utils/absolute_file_converter.rb +19 -19
- data/lib/coverband/utils/file_hasher.rb +3 -3
- data/lib/coverband/utils/html_formatter.rb +4 -4
- data/lib/coverband/utils/method_definition_scanner.rb +1 -1
- data/lib/coverband/utils/railtie.rb +4 -6
- data/lib/coverband/utils/relative_file_converter.rb +7 -7
- data/lib/coverband/utils/results.rb +1 -5
- data/lib/coverband/utils/source_file.rb +2 -2
- data/lib/coverband/utils/tasks.rb +1 -1
- data/lib/coverband/version.rb +1 -1
- data/lib/coverband.rb +19 -3
- data/public/application.js +35 -0
- data/public/dependencies.js +1 -1
- data/roadmap.md +1 -1
- data/test/benchmarks/benchmark.rake +5 -5
- data/test/coverband/adapters/file_store_test.rb +1 -1
- data/test/coverband/collectors/coverage_test.rb +1 -1
- data/test/coverband/reporters/json_test.rb +1 -1
- data/test/coverband/utils/source_file_test.rb +11 -11
- data/test/fixtures/casting_invitor.rb +1 -1
- data/test/fixtures/sample.rb +2 -2
- data/test/fixtures/skipped_and_executed.rb +1 -1
- data/test/forked/rails_rake_full_stack_test.rb +1 -1
- data/test/test_helper.rb +3 -5
- data/test/unique_files.rb +1 -1
- data/views/file_list.erb +38 -32
- data/views/layout.erb +3 -3
- metadata +12 -136
- data/LICENSE.txt +0 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f25f2799e62201b31472588ed6ee3d00697b6ab8eba5beb04c3a76cb7e52d962
|
|
4
|
+
data.tar.gz: 599a0d1a4ef26b9b353d4ae341db2287f15b5119b9d9d3ed3d2b0e796c6e1fae
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b58f4486c028a9ed4f2e3444ed164a43b620b4cc213f91e9b7aef93c2ef1c394840aade62466b216f29ade57851314989e0ed3f3bca2a7f692deddd106efe7a3
|
|
7
|
+
data.tar.gz: 6569ffaeb15feb24b4eb40d5e0403bcf4fcc6fc381a7fd30e64a9e6a7fee06498e05ffe2832c7a99545c51a8b25a12cf6264daf672ef82485ccf10e03a3895a3
|
data/.github/workflows/main.yml
CHANGED
|
@@ -20,13 +20,12 @@ jobs:
|
|
|
20
20
|
# truffleruby-head,
|
|
21
21
|
# removing jruby again to flaky
|
|
22
22
|
gemfile: [ Gemfile.rails6.0, Gemfile.rails6.1, Gemfile.rails7.0, Gemfile.rails7.1 ]
|
|
23
|
-
# ruby: [2.3, 2.4, 2.5, 2.6, 2.7, "3.0", "3.1", jruby]
|
|
24
23
|
# need to add support for multiple gemfiles
|
|
25
|
-
ruby: ["2.7", "3.0", "3.1", "3.2"]
|
|
24
|
+
ruby: ["2.7", "3.0", "3.1", "3.2", "3.3"]
|
|
26
25
|
redis-version: [4, 5, 6, 7]
|
|
27
26
|
runs-on: ${{ matrix.os }}-latest
|
|
28
27
|
steps:
|
|
29
|
-
- uses: actions/checkout@
|
|
28
|
+
- uses: actions/checkout@v4
|
|
30
29
|
- uses: supercharge/redis-github-action@1.2.0
|
|
31
30
|
with:
|
|
32
31
|
redis-version: ${{ matrix.redis-version }}
|
data/.standard.yml
CHANGED
data/Gemfile
CHANGED
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -79,7 +79,7 @@ run ActionController::Dispatcher.new
|
|
|
79
79
|
|
|
80
80
|

|
|
81
81
|
|
|
82
|
-
>
|
|
82
|
+
> You can check it out locally by running the [Coverband Demo App](https://github.com/danmayer/coverband_rails_example).
|
|
83
83
|
|
|
84
84
|
- View overall coverage information
|
|
85
85
|
|
|
@@ -438,6 +438,7 @@ If you submit a change please make sure the tests and benchmarks are passing.
|
|
|
438
438
|
- **Coverband, [Elastic APM](https://github.com/elastic/apm-agent-ruby) and resque**
|
|
439
439
|
- In an environment that uses the Elastic APM ruby agent, resque jobs will fail with `Transactions may not be nested. Already inside #<ElasticAPM::Transaction>` if the `elastic-apm` gem is loaded _before_ the `coverband` gem
|
|
440
440
|
- Put `coverage` ahead of `elastic-apm` in your Gemfile
|
|
441
|
+
- **Bootsnap**, The methods used by [bootsnap do not support having coverage enabled](https://github.com/Shopify/bootsnap/blob/main/lib/bootsnap/compile_cache/iseq.rb#L87), so you can either have Coverband or bootsnap, but not both.
|
|
441
442
|
|
|
442
443
|
### Debugging Redis Store
|
|
443
444
|
|
|
@@ -462,4 +463,4 @@ The Coverband logo was created by [Dave Woodall](http://davewoodall.com). Thanks
|
|
|
462
463
|
# License
|
|
463
464
|
|
|
464
465
|
This is a MIT License project...
|
|
465
|
-
See the file
|
|
466
|
+
See the file [LICENSE](LICENSE) for copying permission.
|
data/Rakefile
CHANGED
data/changes.md
CHANGED
|
@@ -135,7 +135,7 @@ __NOTE: the current RCs include below, but this might turn into coverband 6.0__
|
|
|
135
135
|
- added support to download coverage and view data in JSON format
|
|
136
136
|
- documentation about working with environment variables
|
|
137
137
|
- add cache wiggle to avoid Redis CPU spikes (cache stampede on Redis server)
|
|
138
|
-
- make the nocov
|
|
138
|
+
- make the nocov consistent on the data download and html view
|
|
139
139
|
- small performance improvements
|
|
140
140
|
|
|
141
141
|
### Coverband 4.2.3
|
data/coverband.gemspec
CHANGED
|
@@ -18,10 +18,9 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
|
|
19
19
|
spec.files = `git ls-files`.split("\n").reject { |f| f.start_with?("docs") }
|
|
20
20
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
21
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
22
21
|
spec.require_paths = %w[lib]
|
|
23
22
|
|
|
24
|
-
spec.required_ruby_version = ">= 2.
|
|
23
|
+
spec.required_ruby_version = ">= 2.7"
|
|
25
24
|
|
|
26
25
|
spec.metadata = {
|
|
27
26
|
"homepage_uri" => "https://github.com/danmayer/coverband",
|
|
@@ -40,11 +39,12 @@ Gem::Specification.new do |spec|
|
|
|
40
39
|
spec.add_development_dependency "minitest-fork_executor"
|
|
41
40
|
spec.add_development_dependency "minitest-stub-const"
|
|
42
41
|
spec.add_development_dependency "mocha", "~> 1.7.0"
|
|
42
|
+
# spec.add_development_dependency "spy"
|
|
43
43
|
spec.add_development_dependency "rack"
|
|
44
44
|
spec.add_development_dependency "rack-test"
|
|
45
45
|
spec.add_development_dependency "rake"
|
|
46
46
|
spec.add_development_dependency "resque"
|
|
47
|
-
spec.add_development_dependency "standard", "
|
|
47
|
+
spec.add_development_dependency "standard", "~> 1.34.0"
|
|
48
48
|
spec.add_development_dependency "standardrb"
|
|
49
49
|
|
|
50
50
|
spec.add_development_dependency "coveralls"
|
|
@@ -35,7 +35,7 @@ module Coverband
|
|
|
35
35
|
raise ABSTRACT_KEY
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
def coverage(_local_type = nil)
|
|
38
|
+
def coverage(_local_type = nil, opts = {})
|
|
39
39
|
raise ABSTRACT_KEY
|
|
40
40
|
end
|
|
41
41
|
|
|
@@ -51,9 +51,9 @@ module Coverband
|
|
|
51
51
|
raise "abstract"
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
def get_coverage_report
|
|
54
|
+
def get_coverage_report(options = {})
|
|
55
55
|
coverage_cache = {}
|
|
56
|
-
data = Coverband.configuration.store.split_coverage(Coverband::TYPES, coverage_cache)
|
|
56
|
+
data = Coverband.configuration.store.split_coverage(Coverband::TYPES, coverage_cache, options)
|
|
57
57
|
data.merge(Coverband::MERGED_TYPE => Coverband.configuration.store.merged_coverage(Coverband::TYPES, coverage_cache))
|
|
58
58
|
end
|
|
59
59
|
|
|
@@ -67,12 +67,12 @@ module Coverband
|
|
|
67
67
|
|
|
68
68
|
protected
|
|
69
69
|
|
|
70
|
-
def split_coverage(types, coverage_cache)
|
|
70
|
+
def split_coverage(types, coverage_cache, options = {})
|
|
71
71
|
types.reduce({}) do |data, type|
|
|
72
72
|
if type == Coverband::RUNTIME_TYPE && Coverband.configuration.simulate_oneshot_lines_coverage
|
|
73
73
|
data.update(type => coverage_cache[type] ||= simulated_runtime_coverage)
|
|
74
74
|
else
|
|
75
|
-
data.update(type => coverage_cache[type] ||= coverage(type))
|
|
75
|
+
data.update(type => coverage_cache[type] ||= coverage(type, options))
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
end
|
|
@@ -100,7 +100,7 @@ module Coverband
|
|
|
100
100
|
def expand_report(report)
|
|
101
101
|
expanded = {}
|
|
102
102
|
report_time = Time.now.to_i
|
|
103
|
-
updated_time = type == Coverband::EAGER_TYPE ? nil : report_time
|
|
103
|
+
updated_time = (type == Coverband::EAGER_TYPE) ? nil : report_time
|
|
104
104
|
report.each_pair do |key, line_data|
|
|
105
105
|
extended_data = {
|
|
106
106
|
FIRST_UPDATED_KEY => report_time,
|
|
@@ -115,7 +115,7 @@ module Coverband
|
|
|
115
115
|
|
|
116
116
|
def merge_reports(new_report, old_report, options = {})
|
|
117
117
|
# transparently update from RUNTIME_TYPE = nil to RUNTIME_TYPE = :runtime
|
|
118
|
-
# transparent update for format
|
|
118
|
+
# transparent update for format coverband_3_2
|
|
119
119
|
old_report = coverage(nil, override_type: nil) if old_report.nil? && type == Coverband::RUNTIME_TYPE
|
|
120
120
|
new_report = expand_report(new_report) unless options[:skip_expansion]
|
|
121
121
|
keys = (new_report.keys + old_report.keys).uniq
|
|
@@ -145,11 +145,11 @@ module Coverband
|
|
|
145
145
|
# TODO: This should only be 2 cases get our dup / not dups aligned
|
|
146
146
|
def array_add(latest, original)
|
|
147
147
|
if Coverband.configuration.use_oneshot_lines_coverage
|
|
148
|
-
latest.map!.with_index { |v, i| (v + original[i] >= 1 ? 1 : 0) if v && original[i] }
|
|
148
|
+
latest.map!.with_index { |v, i| ((v + original[i] >= 1) ? 1 : 0) if v && original[i] }
|
|
149
149
|
elsif Coverband.configuration.simulate_oneshot_lines_coverage
|
|
150
|
-
latest.map.with_index { |v, i| (v + original[i] >= 1 ? 1 : 0) if v && original[i] }
|
|
150
|
+
latest.map.with_index { |v, i| ((v + original[i] >= 1) ? 1 : 0) if v && original[i] }
|
|
151
151
|
else
|
|
152
|
-
latest.map.with_index { |v, i| v && original[i] ? v + original[i] : nil }
|
|
152
|
+
latest.map.with_index { |v, i| (v && original[i]) ? v + original[i] : nil }
|
|
153
153
|
end
|
|
154
154
|
end
|
|
155
155
|
end
|
|
@@ -34,12 +34,10 @@ module Coverband
|
|
|
34
34
|
else
|
|
35
35
|
if lock!(local_type)
|
|
36
36
|
Thread.new do
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
unlock!(local_type)
|
|
42
|
-
end
|
|
37
|
+
result = yield(deferred_time)
|
|
38
|
+
set(local_type, JSON.generate(result))
|
|
39
|
+
ensure
|
|
40
|
+
unlock!(local_type)
|
|
43
41
|
end
|
|
44
42
|
end
|
|
45
43
|
JSON.parse(cached_result)
|
|
@@ -53,12 +51,22 @@ module Coverband
|
|
|
53
51
|
end
|
|
54
52
|
end
|
|
55
53
|
|
|
54
|
+
protected
|
|
55
|
+
|
|
56
|
+
def split_coverage(types, coverage_cache, options = {})
|
|
57
|
+
if types.is_a?(Array)
|
|
58
|
+
coverage_for_types(types, options)
|
|
59
|
+
else
|
|
60
|
+
super
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
56
64
|
private
|
|
57
65
|
|
|
58
66
|
# sleep in between to avoid holding other redis commands..
|
|
59
67
|
# with a small random offset so runtime and eager types can be processed "at the same time"
|
|
60
68
|
def deferred_time
|
|
61
|
-
rand(
|
|
69
|
+
rand(2.0..3.0)
|
|
62
70
|
end
|
|
63
71
|
|
|
64
72
|
def del(local_type)
|
|
@@ -109,7 +117,7 @@ module Coverband
|
|
|
109
117
|
@relative_file_converter = opts[:relative_file_converter] || Utils::RelativeFileConverter
|
|
110
118
|
|
|
111
119
|
@get_coverage_cache = if opts[:get_coverage_cache]
|
|
112
|
-
key_prefix = [REDIS_STORAGE_FORMAT_VERSION, @redis_namespace].compact.join(".")
|
|
120
|
+
key_prefix = [REDIS_STORAGE_FORMAT_VERSION, @redis_namespace, "v2"].compact.join(".")
|
|
113
121
|
GetCoverageRedisCacheStore.new(redis, key_prefix)
|
|
114
122
|
else
|
|
115
123
|
GetCoverageNullCacheStore
|
|
@@ -130,6 +138,7 @@ module Coverband
|
|
|
130
138
|
file_keys = files_set
|
|
131
139
|
@redis.del(*file_keys) if file_keys.any?
|
|
132
140
|
@redis.del(files_key)
|
|
141
|
+
@redis.del(files_key(type))
|
|
133
142
|
@get_coverage_cache.clear!(type)
|
|
134
143
|
end
|
|
135
144
|
self.type = old_type
|
|
@@ -147,7 +156,7 @@ module Coverband
|
|
|
147
156
|
|
|
148
157
|
def save_report(report)
|
|
149
158
|
report_time = Time.now.to_i
|
|
150
|
-
updated_time = type == Coverband::EAGER_TYPE ? nil : report_time
|
|
159
|
+
updated_time = (type == Coverband::EAGER_TYPE) ? nil : report_time
|
|
151
160
|
keys = []
|
|
152
161
|
report.each_slice(@save_report_batch_size) do |slice|
|
|
153
162
|
files_data = slice.map { |(file, data)|
|
|
@@ -173,12 +182,19 @@ module Coverband
|
|
|
173
182
|
@redis.sadd(files_key, keys) if keys.any?
|
|
174
183
|
end
|
|
175
184
|
|
|
176
|
-
|
|
185
|
+
# TODO: refactor this and the method below and consider removing all the cached results stuff
|
|
186
|
+
def coverage(local_type = nil, opts = {})
|
|
187
|
+
page_size = opts[:page_size] || 250
|
|
177
188
|
cached_results = @get_coverage_cache.fetch(local_type || type) do |sleep_time|
|
|
178
|
-
files_set =
|
|
179
|
-
|
|
189
|
+
files_set = if opts[:page]
|
|
190
|
+
files_set(local_type).each_slice(page_size).to_a[opts[:page] - 1] || {}
|
|
191
|
+
elsif opts[:filename]
|
|
192
|
+
files_set(local_type).select { |filepath| filepath == opts[:filename] } || {}
|
|
193
|
+
else
|
|
194
|
+
files_set(local_type)
|
|
195
|
+
end
|
|
180
196
|
# use batches with a sleep in between to avoid overloading redis
|
|
181
|
-
files_set.each_slice(
|
|
197
|
+
files_set.each_slice(page_size).flat_map do |key_batch|
|
|
182
198
|
sleep sleep_time
|
|
183
199
|
@redis.pipelined do |pipeline|
|
|
184
200
|
key_batch.each do |key|
|
|
@@ -193,6 +209,44 @@ module Coverband
|
|
|
193
209
|
end
|
|
194
210
|
end
|
|
195
211
|
|
|
212
|
+
# NOTE: when using paging we need to ensure we have the same set of files per page in runtime and eager
|
|
213
|
+
def coverage_for_types(types, opts = {})
|
|
214
|
+
page_size = opts[:page_size] || 250
|
|
215
|
+
|
|
216
|
+
local_type = Coverband::RUNTIME_TYPE
|
|
217
|
+
hash_data = {}
|
|
218
|
+
|
|
219
|
+
runtime_file_set = if opts[:page]
|
|
220
|
+
files_set(local_type).each_slice(page_size).to_a[opts[:page] - 1] || {}
|
|
221
|
+
elsif opts[:filename]
|
|
222
|
+
files_set(local_type).select { |filepath| filepath == opts[:filename] } || {}
|
|
223
|
+
else
|
|
224
|
+
files_set(local_type)
|
|
225
|
+
end
|
|
226
|
+
hash_data[Coverband::RUNTIME_TYPE] = runtime_file_set.each_slice(page_size).flat_map do |key_batch|
|
|
227
|
+
@redis.pipelined do |pipeline|
|
|
228
|
+
key_batch.each do |key|
|
|
229
|
+
pipeline.hgetall(key)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
matched_file_set = files_set(Coverband::EAGER_TYPE)
|
|
235
|
+
.select { |filepath| runtime_file_set.include?(filepath) } || {}
|
|
236
|
+
hash_data[Coverband::EAGER_TYPE] = matched_file_set.each_slice(page_size).flat_map do |key_batch|
|
|
237
|
+
@redis.pipelined do |pipeline|
|
|
238
|
+
key_batch.each do |key|
|
|
239
|
+
pipeline.hgetall(key)
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
hash_data
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def file_count(local_type = nil)
|
|
247
|
+
files_set(local_type).count { |filename| !Coverband.configuration.ignore.any? { |i| filename.match(i) } }
|
|
248
|
+
end
|
|
249
|
+
|
|
196
250
|
def raw_store
|
|
197
251
|
@redis
|
|
198
252
|
end
|
|
@@ -215,7 +269,7 @@ module Coverband
|
|
|
215
269
|
|
|
216
270
|
data = coverage_data_from_redis(data_from_redis)
|
|
217
271
|
hash[file] = data_from_redis.select { |meta_data_key, _value| META_DATA_KEYS.include?(meta_data_key) }.merge!("data" => data)
|
|
218
|
-
hash[file][LAST_UPDATED_KEY] = hash[file][LAST_UPDATED_KEY].nil? || hash[file][LAST_UPDATED_KEY] == "" ? nil : hash[file][LAST_UPDATED_KEY].to_i
|
|
272
|
+
hash[file][LAST_UPDATED_KEY] = (hash[file][LAST_UPDATED_KEY].nil? || hash[file][LAST_UPDATED_KEY] == "") ? nil : hash[file][LAST_UPDATED_KEY].to_i
|
|
219
273
|
hash[file].merge!(LAST_UPDATED_KEY => hash[file][LAST_UPDATED_KEY], FIRST_UPDATED_KEY => hash[file][FIRST_UPDATED_KEY].to_i)
|
|
220
274
|
end
|
|
221
275
|
|
|
@@ -223,7 +277,7 @@ module Coverband
|
|
|
223
277
|
max = data_from_redis[FILE_LENGTH_KEY].to_i - 1
|
|
224
278
|
Array.new(max + 1) do |index|
|
|
225
279
|
line_coverage = data_from_redis[index.to_s]
|
|
226
|
-
line_coverage
|
|
280
|
+
line_coverage&.to_i
|
|
227
281
|
end
|
|
228
282
|
end
|
|
229
283
|
|
|
@@ -42,7 +42,7 @@ module Coverband
|
|
|
42
42
|
|
|
43
43
|
###
|
|
44
44
|
# Fetch coverband coverage via the API
|
|
45
|
-
# This would allow one to
|
|
45
|
+
# This would allow one to explore from the service and move back to the open source
|
|
46
46
|
# without having to reset coverage
|
|
47
47
|
###
|
|
48
48
|
def coverage(local_type = nil, opts = {})
|
|
@@ -98,12 +98,10 @@ module Coverband
|
|
|
98
98
|
def retry_failed_reports
|
|
99
99
|
retries = []
|
|
100
100
|
@failed_coverage_reports.any? do
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
retries << report_body
|
|
106
|
-
end
|
|
101
|
+
report_body = @failed_coverage_reports.pop
|
|
102
|
+
send_report_body(report_body)
|
|
103
|
+
rescue
|
|
104
|
+
retries << report_body
|
|
107
105
|
end
|
|
108
106
|
retries.each do |report_body|
|
|
109
107
|
add_retry_message(report_body)
|
|
@@ -65,7 +65,7 @@ module Coverband
|
|
|
65
65
|
|
|
66
66
|
# NOTE: This event was instrumented in Aug 10th 2022, but didn't make the 7.0.4 release and should be in the next release
|
|
67
67
|
# https://github.com/rails/rails/pull/43755
|
|
68
|
-
# Automatic tracking of redirects isn't
|
|
68
|
+
# Automatic tracking of redirects isn't available before Rails 7.1.0 (currently tested against the 7.1.0.alpha)
|
|
69
69
|
# We could consider back porting or patching a solution that works on previous Rails versions
|
|
70
70
|
ActiveSupport::Notifications.subscribe("redirect.action_dispatch") do |name, start, finish, id, payload|
|
|
71
71
|
Coverband.configuration.route_tracker.track_key(payload)
|
|
@@ -36,7 +36,7 @@ module Coverband
|
|
|
36
36
|
app_translation_keys = []
|
|
37
37
|
app_translation_files = ::I18n.load_path.select { |f| f.match(/config\/locales/) }
|
|
38
38
|
app_translation_files.each do |file|
|
|
39
|
-
app_translation_keys += flatten_hash(YAML.load_file(file)).keys
|
|
39
|
+
app_translation_keys += flatten_hash(YAML.load_file(file, aliases: true)).keys
|
|
40
40
|
end
|
|
41
41
|
app_translation_keys.uniq
|
|
42
42
|
else
|
|
@@ -48,7 +48,7 @@ module Coverband
|
|
|
48
48
|
hash.each_with_object({}) do |(k, v), h|
|
|
49
49
|
if v.is_a? Hash
|
|
50
50
|
flatten_hash(v).map do |h_k, h_v|
|
|
51
|
-
h["#{k}.#{h_k}"
|
|
51
|
+
h[:"#{k}.#{h_k}"] = h_v
|
|
52
52
|
end
|
|
53
53
|
else
|
|
54
54
|
h[k] = v
|
|
@@ -81,7 +81,7 @@ module Coverband
|
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
def unused_keys(used_views = nil)
|
|
84
|
-
recently_used_views =
|
|
84
|
+
recently_used_views = used_keys.keys
|
|
85
85
|
unused_views = all_keys - recently_used_views
|
|
86
86
|
# since layouts don't include format we count them used if they match with ANY formats
|
|
87
87
|
unused_views.reject { |view| view.match(/\/layouts\//) && recently_used_views.any? { |used_view| view.include?(used_view) } }
|
|
@@ -93,7 +93,7 @@ module Coverband
|
|
|
93
93
|
@coverband_timeout = nil
|
|
94
94
|
@service_dev_mode = nil
|
|
95
95
|
@service_test_mode = nil
|
|
96
|
-
@
|
|
96
|
+
@process_type = nil
|
|
97
97
|
|
|
98
98
|
@redis_url = nil
|
|
99
99
|
@redis_namespace = nil
|
|
@@ -154,7 +154,7 @@ module Coverband
|
|
|
154
154
|
def background_reporting_sleep_seconds
|
|
155
155
|
@background_reporting_sleep_seconds ||= if service?
|
|
156
156
|
# default to 10m for service
|
|
157
|
-
Coverband.configuration.coverband_env == "production" ? 600 : 60
|
|
157
|
+
(Coverband.configuration.coverband_env == "production") ? 600 : 60
|
|
158
158
|
elsif store.is_a?(Coverband::Adapters::HashRedisStore)
|
|
159
159
|
# Default to 5 minutes if using the hash redis store
|
|
160
160
|
300
|
|
@@ -180,7 +180,7 @@ module Coverband
|
|
|
180
180
|
def store=(store)
|
|
181
181
|
raise "Pass in an instance of Coverband::Adapters" unless store.is_a?(Coverband::Adapters::Base)
|
|
182
182
|
raise "invalid configuration: only coverband service expects an API Key" if api_key && store.class.to_s != "Coverband::Adapters::WebServiceStore"
|
|
183
|
-
raise "invalid configuration: coverband service shouldn't have redis url set" if ENV["COVERBAND_REDIS_URL"] && store.
|
|
183
|
+
raise "invalid configuration: coverband service shouldn't have redis url set" if ENV["COVERBAND_REDIS_URL"] && store.instance_of?(::Coverband::Adapters::WebServiceStore)
|
|
184
184
|
|
|
185
185
|
@store = store
|
|
186
186
|
end
|
|
@@ -262,11 +262,11 @@ module Coverband
|
|
|
262
262
|
end
|
|
263
263
|
|
|
264
264
|
def coverband_env
|
|
265
|
-
ENV["RACK_ENV"] || ENV["RAILS_ENV"] || (defined?(Rails) && Rails.respond_to?(:env) ? Rails.env : "unknown")
|
|
265
|
+
ENV["RACK_ENV"] || ENV["RAILS_ENV"] || ((defined?(Rails) && Rails.respond_to?(:env)) ? Rails.env : "unknown")
|
|
266
266
|
end
|
|
267
267
|
|
|
268
268
|
def coverband_timeout
|
|
269
|
-
@coverband_timeout ||= coverband_env == "development" ? 5 : 2
|
|
269
|
+
@coverband_timeout ||= (coverband_env == "development") ? 5 : 2
|
|
270
270
|
end
|
|
271
271
|
|
|
272
272
|
def service_dev_mode
|
|
@@ -20,10 +20,8 @@ module Coverband
|
|
|
20
20
|
|
|
21
21
|
def rails_server?
|
|
22
22
|
@stack.any? do |location|
|
|
23
|
-
(
|
|
24
|
-
location.path.include?("rails/commands/commands_tasks.rb") && location.label == "server" ||
|
|
23
|
+
location.path.include?("rails/commands/commands_tasks.rb") && location.label == "server" ||
|
|
25
24
|
location.path.include?("rails/commands/server/server_command.rb") && location.label == "perform"
|
|
26
|
-
)
|
|
27
25
|
end
|
|
28
26
|
end
|
|
29
27
|
end
|
|
@@ -4,15 +4,15 @@ module Coverband
|
|
|
4
4
|
module Reporters
|
|
5
5
|
###
|
|
6
6
|
# This is the base clase for report generation
|
|
7
|
-
# it helps with filtering, normalization, etc for final
|
|
7
|
+
# it helps with filtering, normalization, etc for final report generation
|
|
8
8
|
###
|
|
9
9
|
class Base
|
|
10
10
|
class << self
|
|
11
11
|
DATA_KEY = "data"
|
|
12
12
|
|
|
13
|
-
def report(store,
|
|
13
|
+
def report(store, options = {})
|
|
14
14
|
all_roots = Coverband.configuration.all_root_paths
|
|
15
|
-
|
|
15
|
+
get_current_scov_data_imp(store, all_roots, options)
|
|
16
16
|
|
|
17
17
|
# These are extremelhy verbose but useful during coverband development, not generally for users
|
|
18
18
|
# Only available by uncommenting this mode is never released
|
|
@@ -20,7 +20,6 @@ module Coverband
|
|
|
20
20
|
# # msg = "report:\n #{scov_style_report.inspect}"
|
|
21
21
|
# # Coverband.configuration.logger.debug msg
|
|
22
22
|
# end
|
|
23
|
-
scov_style_report
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
###
|
|
@@ -71,7 +70,7 @@ module Coverband
|
|
|
71
70
|
# > [nil,0,0,1,0,1]
|
|
72
71
|
def merge_arrays(first, second)
|
|
73
72
|
merged = []
|
|
74
|
-
longest = first.length > second.length ? first : second
|
|
73
|
+
longest = (first.length > second.length) ? first : second
|
|
75
74
|
|
|
76
75
|
longest.each_with_index do |_line, index|
|
|
77
76
|
merged[index] = if first[index] || second[index]
|
|
@@ -86,12 +85,13 @@ module Coverband
|
|
|
86
85
|
# why do we need to merge covered files data?
|
|
87
86
|
# basically because paths on machines or deployed hosts could be different, so
|
|
88
87
|
# two different keys could point to the same filename or `line_key`
|
|
88
|
+
# this happens when deployment has a dynmaic path or the path change during deployment (hot code reload)
|
|
89
89
|
# TODO: think we are filtering based on ignore while sending to the store
|
|
90
90
|
# and as we also pull it out here
|
|
91
91
|
###
|
|
92
|
-
def get_current_scov_data_imp(store, roots)
|
|
92
|
+
def get_current_scov_data_imp(store, roots, options = {})
|
|
93
93
|
scov_style_report = {}
|
|
94
|
-
store.get_coverage_report.each_pair do |name, data|
|
|
94
|
+
store.get_coverage_report(options).each_pair do |name, data|
|
|
95
95
|
data.each_pair do |key, line_data|
|
|
96
96
|
next if Coverband.configuration.ignore.any? { |i| key.match(i) }
|
|
97
97
|
next unless line_data
|
|
@@ -4,17 +4,23 @@ module Coverband
|
|
|
4
4
|
module Reporters
|
|
5
5
|
class HTMLReport < Base
|
|
6
6
|
attr_accessor :filtered_report_files, :open_report, :notice,
|
|
7
|
-
:base_path, :filename
|
|
7
|
+
:base_path, :filename, :page
|
|
8
8
|
|
|
9
9
|
def initialize(store, options = {})
|
|
10
|
-
|
|
10
|
+
self.page = options.fetch(:page) { nil }
|
|
11
11
|
self.open_report = options.fetch(:open_report) { true }
|
|
12
12
|
# TODO: refactor notice out to top level of web only
|
|
13
13
|
self.notice = options.fetch(:notice) { nil }
|
|
14
14
|
self.base_path = options.fetch(:base_path) { "./" }
|
|
15
15
|
self.filename = options.fetch(:filename) { nil }
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
coverband_reports = Coverband::Reporters::Base.report(store, options)
|
|
18
|
+
# NOTE: at the moment the optimization around paging and filenames only works for hash redis store
|
|
19
|
+
self.filtered_report_files = if (page || filename) && store.is_a?(Coverband::Adapters::HashRedisStore)
|
|
20
|
+
coverband_reports
|
|
21
|
+
else
|
|
22
|
+
self.class.fix_reports(coverband_reports)
|
|
23
|
+
end
|
|
18
24
|
end
|
|
19
25
|
|
|
20
26
|
def file_details
|
|
@@ -36,12 +42,14 @@ module Coverband
|
|
|
36
42
|
def report_dynamic_html
|
|
37
43
|
Coverband::Utils::HTMLFormatter.new(filtered_report_files,
|
|
38
44
|
base_path: base_path,
|
|
39
|
-
notice: notice
|
|
45
|
+
notice: notice,
|
|
46
|
+
page: page).format_dynamic_html!
|
|
40
47
|
end
|
|
41
48
|
|
|
42
49
|
def report_dynamic_data
|
|
43
50
|
Coverband::Utils::HTMLFormatter.new(filtered_report_files,
|
|
44
51
|
base_path: base_path,
|
|
52
|
+
page: page,
|
|
45
53
|
notice: notice).format_dynamic_data!
|
|
46
54
|
end
|
|
47
55
|
end
|