firespring_dev_commands 2.1.21.pre.alpha.7 → 2.1.21.pre.alpha.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8854ab66747e26c22780c4e6756df86dac09bc5a8029fae51f1382d29d18c27f
4
- data.tar.gz: ca3ddd354a8faddb180d827891886ce78483accb7e7f1e2e5b5b9d6bcc9d36f7
3
+ metadata.gz: 4189e443ce57ccf4e992178ad2dd0de137017a8d78f6d63a4e4f7b55f76fe61b
4
+ data.tar.gz: ab87b579efff5fe40edfad306c6088504b176b61f4d0997e8ab8804f65a61177
5
5
  SHA512:
6
- metadata.gz: 4aace4ef89ab6ec98008184ffb58d71febc920bcc85195a3fe2fa645a4109f8523348cdfae5e281a731d6ce6ddac3769a101800ee7b6e63ad31f4efcfa2f84c4
7
- data.tar.gz: c700fd928018dc384757fddeae412eb4990323b94b47a16026736738d43e4a8ff12202b15014ebd0b92d30f5705dcffeab439a78e61ea711e0074ecff22d6cec
6
+ metadata.gz: 329dc4520ff98700950aef5c5b67920e8f8b520d6f8eba693150526e7144c962b55c31924e0d956b108fe8914777d4d21daf14c20393bb3f61902c19dd92a315
7
+ data.tar.gz: 873fcd5623d4e007cd2018285656caa029fdbf9dc34714b64df4223a10cb118b95919bbc428176ee7d68b29da6aea130163881a5480cd0fe2db7a033795af8ae
@@ -0,0 +1,13 @@
1
+ module Dev
2
+ module Coverage
3
+ class Base
4
+ def php_options
5
+ raise 'not implemented'
6
+ end
7
+
8
+ def check(*)
9
+ raise 'not implemented'
10
+ end
11
+ end
12
+ end
13
+ end
@@ -2,14 +2,21 @@ module Dev
2
2
  # Module containing different classes for interfacing with coverage files
3
3
  module Coverage
4
4
  # Class for checking code coverage using cobertura
5
- class Cobertura
6
- attr_reader :local_filename, :container_filename, :filename, :threshold
5
+ class Cobertura < Base
6
+ attr_reader :local_filename, :container_filename, :filename, :threshold, :exclude
7
+
8
+ def initialize(filename: File.join('coverage', 'cobertura.xml'), threshold: nil, container_path: nil, local_path: nil, exclude: nil)
9
+ super()
7
10
 
8
- def initialize(filename: File.join('coverage', 'cobertura.xml'), threshold: nil, container_path: nil, local_path: nil)
9
11
  @filename = filename
10
12
  @local_filename = File.join(local_path || '.', @filename)
11
13
  @container_filename = File.join(container_path || '.', @filename)
12
14
  @threshold = threshold
15
+ @exclude = (exclude || []).map do |it|
16
+ next it if it.is_a?(Regex)
17
+
18
+ Regex.new(it)
19
+ end
13
20
  end
14
21
 
15
22
  # Remove any previous versions of the local file that will be output
@@ -22,7 +29,7 @@ module Dev
22
29
  %W(--coverage-cobertura #{container_filename})
23
30
  end
24
31
 
25
- # Parse the cobertura file as a hash and check the total coverage against the desired threshold
32
+ # Parse the cobertura file and check the lines missed against the desired threshold
26
33
  def check(application: nil)
27
34
  # If an application has been specified and the file does not exist locally, attempt to copy it back from the docker container
28
35
  if application && !File.exist?(local_filename)
@@ -30,26 +37,49 @@ module Dev
30
37
  Dev::Docker.new.copy_from_container(container, container_filename, local_filename, required: true)
31
38
  end
32
39
 
33
- # Load the file from disk and parse with ox
34
- report = Ox.load(File.read(local_filename), mode: :hash)
35
- _, _, files = report[:coverage]
36
-
37
- covered = missed = 0
38
- files.dig(:packages, :package)&.each do |_attrs, packages|
39
- _, _, lines = *packages&.dig(:classes, :class)
40
- lines&.dig(:lines, :line)&.each do |it|
41
- it = it&.first if it.is_a?(Array)
42
- if it&.dig(:hits).to_i.positive?
43
- covered += 1
44
- else
45
- missed += 1
46
- end
47
- end
40
+ report = Ox.load(File.read(local_filename))
41
+ total_missed = report.coverage.locate('packages/package').sum { |package| parse_package_missed(package) }
42
+ puts "Lines missing coverage was #{total_missed}"
43
+ puts "Configured threshold was #{threshold}" if threshold
44
+ raise 'Code coverage not met' if threshold && total_missed > threshold
45
+ end
46
+
47
+ # Go through the package and add up all of the lines that were missed
48
+ # Ignore if the file was in the exlude list
49
+ private def parse_package_missed(package)
50
+ filename = package.attributes[:name]
51
+ return if exclude.any? { |it| it.match(filename) }
52
+
53
+ missed = 0
54
+ lines_processed = Set.new
55
+ package.locate('classes/class/lines/line').each do |line|
56
+ # Don't count lines multiple times
57
+ line_number = line.attributes[:number]
58
+ next if lines_processed.include?(line_number)
59
+
60
+ lines_processed << line_number
61
+ missed += 1 unless line.attributes[:hits].to_i.positive?
48
62
  end
63
+ total = lines_processed.length
49
64
 
50
- puts "Lines missing coverage was #{missed}"
51
- puts "Configured threshold was #{threshold}" if threshold
52
- raise 'Code coverage not met' if threshold && missed > threshold
65
+ sanity_check_coverage_against_cobertura_values(package, missed, total)
66
+ missed
67
+ end
68
+
69
+ # Calculate the coverage percent based off the numbers we got and compare to the
70
+ # value cobertura reported. This is meant as a sanity check that we are reading the data correctly
71
+ # TODO: This should be removed after the above logic has been vetted
72
+ private def sanity_check_coverage_against_cobertura_values(package, missed, total)
73
+ line_rate = package.attributes[:'line-rate']
74
+ cobertura_reported_coverage = line_rate.to_f
75
+ cobertura_reported_precision = line_rate.split('.').last.length
76
+
77
+ file_coverage = 0.0
78
+ file_coverage = ((total - missed).to_f / total).round(cobertura_reported_precision) if total.positive?
79
+ return if file_coverage == cobertura_reported_coverage
80
+
81
+ filename = package.attributes[:name]
82
+ puts "WARNINNG: #{filename} coverage (#{file_coverage}) differed from what cobertura reported (#{cobertura_reported_coverage})"
53
83
  end
54
84
  end
55
85
  end
@@ -0,0 +1,17 @@
1
+ module Dev
2
+ module Coverage
3
+ class None < Base
4
+ def initialize(*)
5
+ super()
6
+ end
7
+
8
+ def php_options
9
+ []
10
+ end
11
+
12
+ def check(*)
13
+ puts 'Coverage not configured'
14
+ end
15
+ end
16
+ end
17
+ end
@@ -8,12 +8,12 @@ module Dev
8
8
  DEFAULT_PACKAGE_FILE = 'composer.json'.freeze
9
9
 
10
10
  # Config object for setting top level git config options
11
- Config = Struct.new(:container_path, :local_path, :package_file, :coverage_threshold) do
11
+ Config = Struct.new(:container_path, :local_path, :package_file, :coverage) do
12
12
  def initialize
13
13
  self.container_path = DEFAULT_PATH
14
14
  self.local_path = DEV_COMMANDS_ROOT_DIR
15
15
  self.package_file = DEFAULT_PACKAGE_FILE
16
- self.coverage_threshold = nil
16
+ self.coverage = nil
17
17
  end
18
18
  end
19
19
 
@@ -33,11 +33,11 @@ module Dev
33
33
 
34
34
  attr_accessor :container_path, :local_path, :package_file, :coverage
35
35
 
36
- def initialize(container_path: nil, local_path: nil, package_file: nil, coverage_threshold: nil)
36
+ def initialize(container_path: nil, local_path: nil, package_file: nil, coverage: nil)
37
37
  @container_path = container_path || self.class.config.container_path
38
38
  @local_path = local_path || self.class.config.local_path
39
39
  @package_file = package_file || self.class.config.package_file
40
- @coverage = Dev::Coverage::Cobertura.new(container_path:, local_path:, threshold: coverage_threshold)
40
+ @coverage = coverage || Dev::Coverage::None.new
41
41
  end
42
42
 
43
43
  # The base npm command that is the starting point for all subsequent commands
@@ -95,7 +95,7 @@ module Dev
95
95
  def test_command
96
96
  test = []
97
97
  test << './vendor/bin/phpunit'
98
- test << coverage.php_options if coverage
98
+ test.concat(coverage.php_options) if coverage
99
99
  test.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
100
100
  test
101
101
  end
@@ -20,10 +20,10 @@ module Dev
20
20
  container_path: nil,
21
21
  local_path: nil,
22
22
  start_container_dependencies_on_test: true,
23
- coverage_threshold: nil,
23
+ coverage: nil,
24
24
  exclude: []
25
25
  )
26
- @php = Dev::Php.new(container_path:, local_path:, coverage_threshold:)
26
+ @php = Dev::Php.new(container_path:, local_path:, coverage:)
27
27
  @start_container_dependencies_on_test = start_container_dependencies_on_test
28
28
 
29
29
  super(application, exclude:)
@@ -6,6 +6,6 @@ module Dev
6
6
  # Use 'v.v.v.pre.alpha.v' for pre-release vesions
7
7
  # Use 'v.v.v.beta.v for beta versions
8
8
  # Use semantic versioning for any releases (https://semver.org/)
9
- VERSION = '2.1.21.pre.alpha.7'.freeze
9
+ VERSION = '2.1.21.pre.alpha.9'.freeze
10
10
  end
11
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: firespring_dev_commands
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.21.pre.alpha.7
4
+ version: 2.1.21.pre.alpha.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Firespring
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-21 00:00:00.000000000 Z
11
+ date: 2024-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -333,7 +333,9 @@ files:
333
333
  - lib/firespring_dev_commands/bloom_growth/user.rb
334
334
  - lib/firespring_dev_commands/boolean.rb
335
335
  - lib/firespring_dev_commands/common.rb
336
+ - lib/firespring_dev_commands/coverage/base.rb
336
337
  - lib/firespring_dev_commands/coverage/cobertura.rb
338
+ - lib/firespring_dev_commands/coverage/none.rb
337
339
  - lib/firespring_dev_commands/daterange.rb
338
340
  - lib/firespring_dev_commands/docker.rb
339
341
  - lib/firespring_dev_commands/docker/compose.rb