danger-jacoco-instacart 0.1.14 → 0.1.16
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/.rubocop.yml +1 -1
- data/README.md +6 -0
- data/lib/jacoco/gem_version.rb +1 -1
- data/lib/jacoco/plugin.rb +69 -14
- data/spec/jacoco_spec.rb +73 -1
- data/spec/spec_helper.rb +0 -2
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: df299fa783dd834367d27d1d6eda84b2f233c5a1fa52126de5f72bfda735a556
|
|
4
|
+
data.tar.gz: add2beee08b15e8468291eb2413edb5db0d6320c19b8dcddbd273410076b030a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a9608c3ee2de69007df925218e7ab510d33f8bceec9e379ec16d5af3b4dc64f219bf45a1d398feee9f5d7b636f73a11c3d1be50881dfa09809ca8779a1169d03
|
|
7
|
+
data.tar.gz: 92a726b45f38ad97d9f4a917c2eea152be65b4d94991ca28a0ded329302c321cff37a7e4b46e49b1abf604a414a4a86aef8744e277be331873ea02e042976315
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
|
@@ -35,5 +35,11 @@ to your `Dangerfile`
|
|
|
35
35
|
1. Clone this repo
|
|
36
36
|
2. Run `bundle install` to setup dependencies.
|
|
37
37
|
3. Run `bundle exec rake spec` to run the tests.
|
|
38
|
+
4. Run `bundle exec rubocop -A` to fix in-place what's fixable
|
|
38
39
|
4. Use `bundle exec guard` to automatically have tests run as you make changes.
|
|
39
40
|
5. Make your changes.
|
|
41
|
+
|
|
42
|
+
### How to release new version
|
|
43
|
+
1. Bump version in `lib/jacoco/gem_version.rb - X.Y.Z`
|
|
44
|
+
2. `rake build`
|
|
45
|
+
3. `gem push pkg/danger-jacoco-instacart-X.Y.Z.gem`
|
data/lib/jacoco/gem_version.rb
CHANGED
data/lib/jacoco/plugin.rb
CHANGED
|
@@ -31,7 +31,7 @@ module Danger
|
|
|
31
31
|
setup_texts
|
|
32
32
|
@files_to_check = [] unless files_to_check
|
|
33
33
|
@files_extension = ['.kt', '.java'] unless files_extension
|
|
34
|
-
@file_to_create_on_failure = 'danger_jacoco_failure_status_file.
|
|
34
|
+
@file_to_create_on_failure = 'danger_jacoco_failure_status_file.json' unless file_to_create_on_failure
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
# Initialize the plugin with configured optional texts
|
|
@@ -99,20 +99,61 @@ module Danger
|
|
|
99
99
|
report_markdown.insert(header.length, "#### #{subtitle}\n")
|
|
100
100
|
markdown(report_markdown)
|
|
101
101
|
|
|
102
|
-
report_fails(class_coverage_above_minimum, total_covered)
|
|
102
|
+
report_fails(parser, report_url, class_coverage_above_minimum, total_covered)
|
|
103
103
|
end
|
|
104
104
|
# rubocop:enable Style/AbcSize
|
|
105
105
|
|
|
106
106
|
def classes(delimiter)
|
|
107
107
|
class_to_file_path_hash = {}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
# Initialize files_extension if it's nil
|
|
109
|
+
@files_extension = ['.kt', '.java'] if @files_extension.nil?
|
|
110
|
+
|
|
111
|
+
filtered_files_to_check.each do |file| # "src/java/com/example/CachedRepository.java"
|
|
112
|
+
# Get the package path
|
|
113
|
+
package_path = file.split('.').first.split(delimiter)[1] # "com/example/CachedRepository"
|
|
114
|
+
next unless package_path
|
|
115
|
+
|
|
116
|
+
# Add the primary class (filename-based class)
|
|
117
|
+
class_to_file_path_hash[package_path] = file
|
|
118
|
+
|
|
119
|
+
# For Kotlin files, we need to look for multiple classes/interfaces in the same file
|
|
120
|
+
add_kotlin_declarations(file, package_path, class_to_file_path_hash) if file.end_with?('.kt')
|
|
121
|
+
end
|
|
113
122
|
class_to_file_path_hash
|
|
114
123
|
end
|
|
115
124
|
|
|
125
|
+
# Returns files that match the configured file extensions
|
|
126
|
+
def filtered_files_to_check
|
|
127
|
+
files_to_check.select { |file| @files_extension.reduce(false) { |state, el| state || file.end_with?(el) } }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Scans a Kotlin file for additional class/interface declarations and adds them to the hash
|
|
131
|
+
def add_kotlin_declarations(file, package_path, class_to_file_path_hash)
|
|
132
|
+
return unless File.exist?(file)
|
|
133
|
+
|
|
134
|
+
file_content = File.read(file)
|
|
135
|
+
|
|
136
|
+
# Look for class and interface declarations in the file
|
|
137
|
+
# Regex catches class/interface/object declarations with modifiers and generics
|
|
138
|
+
regex = /\b(?:(?:data|sealed|abstract|open|internal|private|protected|public|inline)\s+)*
|
|
139
|
+
(?:class|interface|object)\s+([A-Za-z0-9_]+)(?:<.*?>)?/x
|
|
140
|
+
declarations = file_content.scan(regex).flatten
|
|
141
|
+
|
|
142
|
+
# For each additional class/interface found (excluding the one matching the filename)
|
|
143
|
+
declarations.each do |class_name|
|
|
144
|
+
# Skip if it matches the primary class name (already added)
|
|
145
|
+
next if package_path.end_with?("/#{class_name}")
|
|
146
|
+
|
|
147
|
+
# Create full class path by replacing the last part with the class name
|
|
148
|
+
parts = package_path.split('/')
|
|
149
|
+
parts[-1] = class_name
|
|
150
|
+
additional_class_path = parts.join('/')
|
|
151
|
+
|
|
152
|
+
# Add to hash
|
|
153
|
+
class_to_file_path_hash[additional_class_path] = file
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
116
157
|
# It returns a specific class code coverage and an emoji status as well
|
|
117
158
|
def report_class(jacoco_class, file_path)
|
|
118
159
|
report_result = {
|
|
@@ -223,13 +264,13 @@ module Danger
|
|
|
223
264
|
end
|
|
224
265
|
|
|
225
266
|
# rubocop:disable Style/SignalException
|
|
226
|
-
def report_fails(class_coverage_above_minimum, total_covered)
|
|
267
|
+
def report_fails(parser, report_url, class_coverage_above_minimum, total_covered)
|
|
227
268
|
if total_covered[:covered] < minimum_project_coverage_percentage
|
|
228
269
|
# fail danger if total coverage is smaller than minimum_project_coverage_percentage
|
|
229
270
|
covered = total_covered[:covered]
|
|
230
271
|
fail("Total coverage of #{covered}%. Improve this to at least #{minimum_project_coverage_percentage}%")
|
|
231
272
|
# rubocop:disable Lint/UnreachableCode (rubocop mistakenly thinks that this line is unreachable since priorly called "fail" raises an error, but in fact "fail" is caught and handled)
|
|
232
|
-
create_status_file_on_failure if class_coverage_above_minimum
|
|
273
|
+
create_status_file_on_failure(parser, report_url) if class_coverage_above_minimum
|
|
233
274
|
# rubocop:enable Lint/UnreachableCode
|
|
234
275
|
end
|
|
235
276
|
|
|
@@ -237,13 +278,20 @@ module Danger
|
|
|
237
278
|
|
|
238
279
|
fail("Class coverage is below minimum. Improve to at least #{minimum_class_coverage_percentage}%")
|
|
239
280
|
# rubocop:disable Lint/UnreachableCode (rubocop mistakenly thinks that this line is unreachable since priorly called "fail" raises an error, but in fact "fail" is caught and handled)
|
|
240
|
-
create_status_file_on_failure
|
|
281
|
+
create_status_file_on_failure(parser, report_url)
|
|
241
282
|
# rubocop:enable Lint/UnreachableCode
|
|
242
283
|
end
|
|
243
284
|
# rubocop:enable Style/SignalException
|
|
244
285
|
|
|
245
|
-
def create_status_file_on_failure
|
|
246
|
-
|
|
286
|
+
def create_status_file_on_failure(parser, report_url)
|
|
287
|
+
data = []
|
|
288
|
+
parser.classes.each do |jacoco_class|
|
|
289
|
+
data.push({ 'name' => jacoco_class.name, 'path' => report_filepath(jacoco_class.name, report_url) })
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
File.open(file_to_create_on_failure, 'w') do |f|
|
|
293
|
+
f.write({ 'failures' => data }.to_json)
|
|
294
|
+
end
|
|
247
295
|
end
|
|
248
296
|
|
|
249
297
|
def markdown_class(parser, report_markdown, report_url, class_to_file_path_hash)
|
|
@@ -265,8 +313,15 @@ module Danger
|
|
|
265
313
|
if report_url.empty?
|
|
266
314
|
"`#{class_name}`"
|
|
267
315
|
else
|
|
268
|
-
|
|
269
|
-
|
|
316
|
+
"[`#{class_name}`](#{report_url + report_filepath(class_name, report_url)})"
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def report_filepath(class_name, report_url)
|
|
321
|
+
if report_url.empty?
|
|
322
|
+
class_name
|
|
323
|
+
else
|
|
324
|
+
"#{class_name.gsub(%r{/(?=[^/]*/.)}, '.')}.html"
|
|
270
325
|
end
|
|
271
326
|
end
|
|
272
327
|
end
|
data/spec/jacoco_spec.rb
CHANGED
|
@@ -58,7 +58,7 @@ module Danger
|
|
|
58
58
|
@my_plugin.files_to_check = ['src/java/com/example/CachedRepository.java', 'src/java/io/sample/UseCase.java']
|
|
59
59
|
@my_plugin.minimum_class_coverage_percentage = 60
|
|
60
60
|
|
|
61
|
-
expect(File).to receive(:open).with('danger_jacoco_failure_status_file.
|
|
61
|
+
expect(File).to receive(:open).with('danger_jacoco_failure_status_file.json', 'w')
|
|
62
62
|
@my_plugin.report path_a
|
|
63
63
|
end
|
|
64
64
|
|
|
@@ -384,6 +384,78 @@ module Danger
|
|
|
384
384
|
expect(@dangerfile.status_report[:markdowns][0].message).to include('| `com/example/CachedRepository` | 50% | 55% | :warning: |')
|
|
385
385
|
end
|
|
386
386
|
end
|
|
387
|
+
|
|
388
|
+
it 'test with kotlin multiples classes in same file' do
|
|
389
|
+
path_a = "#{File.dirname(__FILE__)}/fixtures/output_a.xml"
|
|
390
|
+
|
|
391
|
+
# Mock the Kotlin file with multiple classes
|
|
392
|
+
kotlin_file_path = 'src/kotlin/com/example/MultiClass.kt'
|
|
393
|
+
kotlin_file_content = <<~KOTLIN
|
|
394
|
+
package com.example
|
|
395
|
+
|
|
396
|
+
class MultiClass {
|
|
397
|
+
// some code
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
data class DataClass(val property: String) {
|
|
401
|
+
// some code
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
sealed class SealedClass {
|
|
405
|
+
// some code
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
private class PrivateClass {
|
|
409
|
+
// some code
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
abstract class AbstractClass {
|
|
413
|
+
// some code
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
class GenericClass<T> {
|
|
417
|
+
// some code
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
interface SomeInterface {
|
|
421
|
+
// some code
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
object SingletonObject {
|
|
425
|
+
// some code
|
|
426
|
+
}
|
|
427
|
+
KOTLIN
|
|
428
|
+
|
|
429
|
+
allow(File).to receive(:exist?).and_call_original
|
|
430
|
+
allow(File).to receive(:exist?).with(kotlin_file_path).and_return(true)
|
|
431
|
+
allow(File).to receive(:read).and_call_original
|
|
432
|
+
allow(File).to receive(:read).with(kotlin_file_path).and_return(kotlin_file_content)
|
|
433
|
+
|
|
434
|
+
@my_plugin.files_to_check = [kotlin_file_path]
|
|
435
|
+
@my_plugin.minimum_project_coverage_percentage = 0 # Avoid project coverage errors
|
|
436
|
+
|
|
437
|
+
# Use a block to capture the key-value pairs passed to classes
|
|
438
|
+
expect { |b| @my_plugin.classes(%r{/kotlin/}).each(&b) }.to yield_control.at_least(8).times
|
|
439
|
+
|
|
440
|
+
# Call report
|
|
441
|
+
@my_plugin.report path_a
|
|
442
|
+
|
|
443
|
+
# Check the class-to-file hash from SAXParser
|
|
444
|
+
class_file_hash = @my_plugin.classes(%r{/kotlin/})
|
|
445
|
+
expect(class_file_hash.keys).to include('com/example/MultiClass')
|
|
446
|
+
expect(class_file_hash.keys).to include('com/example/DataClass')
|
|
447
|
+
expect(class_file_hash.keys).to include('com/example/SealedClass')
|
|
448
|
+
expect(class_file_hash.keys).to include('com/example/PrivateClass')
|
|
449
|
+
expect(class_file_hash.keys).to include('com/example/AbstractClass')
|
|
450
|
+
expect(class_file_hash.keys).to include('com/example/GenericClass')
|
|
451
|
+
expect(class_file_hash.keys).to include('com/example/SomeInterface')
|
|
452
|
+
expect(class_file_hash.keys).to include('com/example/SingletonObject')
|
|
453
|
+
|
|
454
|
+
# All keys should map to the same file path
|
|
455
|
+
class_file_hash.each_value do |file_path|
|
|
456
|
+
expect(file_path).to eq(kotlin_file_path)
|
|
457
|
+
end
|
|
458
|
+
end
|
|
387
459
|
end
|
|
388
460
|
end
|
|
389
461
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -29,7 +29,6 @@ require 'danger_plugin'
|
|
|
29
29
|
# it comes with an extra function `.string` which will
|
|
30
30
|
# strip all ANSI colours from the string.
|
|
31
31
|
|
|
32
|
-
# rubocop:disable Lint/NestedMethodDefinition
|
|
33
32
|
def testing_ui
|
|
34
33
|
@output = StringIO.new
|
|
35
34
|
def @output.winsize
|
|
@@ -42,7 +41,6 @@ def testing_ui
|
|
|
42
41
|
end
|
|
43
42
|
cork
|
|
44
43
|
end
|
|
45
|
-
# rubocop:enable Lint/NestedMethodDefinition
|
|
46
44
|
|
|
47
45
|
# Example environment (ENV) that would come from
|
|
48
46
|
# running a PR on TravisCI
|
metadata
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: danger-jacoco-instacart
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.16
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Anton Malinskiy
|
|
8
8
|
- Alexander Bezverhni
|
|
9
|
-
autorequire:
|
|
9
|
+
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2025-11-10 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: danger-plugin-api
|
|
@@ -217,7 +217,7 @@ homepage: https://github.com/alexanderbezverhni/danger-jacoco
|
|
|
217
217
|
licenses:
|
|
218
218
|
- MIT
|
|
219
219
|
metadata: {}
|
|
220
|
-
post_install_message:
|
|
220
|
+
post_install_message:
|
|
221
221
|
rdoc_options: []
|
|
222
222
|
require_paths:
|
|
223
223
|
- lib
|
|
@@ -232,8 +232,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
232
232
|
- !ruby/object:Gem::Version
|
|
233
233
|
version: '0'
|
|
234
234
|
requirements: []
|
|
235
|
-
rubygems_version: 3.
|
|
236
|
-
signing_key:
|
|
235
|
+
rubygems_version: 3.5.3
|
|
236
|
+
signing_key:
|
|
237
237
|
specification_version: 4
|
|
238
238
|
summary: A longer description of danger-jacoco.
|
|
239
239
|
test_files:
|