firespring_dev_commands 2.1.22 → 2.1.23

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e072ae981046f7bdcd86b078617c9503a5d72ac2b21c2fdfce1c5c51ee8eae5b
4
- data.tar.gz: b98bf6d2bb8c8c9598e5a124f9f10ba0c9c94c384e6065a7dafa1a9cefb5aff2
3
+ metadata.gz: e63ba948a4c8c755d644d4e651f14cd354b0b8086447134da735c9dfb1425b3d
4
+ data.tar.gz: 4ffa7a76482a10e277f0c2be17f28dcbabe4eb9f9dbf21f49420d11329444beb
5
5
  SHA512:
6
- metadata.gz: 17ded1bd8523d1d695935404d604f66d724c9b032585f4d36d16f30a51485d73154438d8d37c2eb9a38a1a48c1d7e95bd21bb76290f893c9a43f4926b886bdf5
7
- data.tar.gz: a971fca800581cd4ee592e9da0605c9f7c3c43702ce22ae7070c81f27ff796553eea5a8ce083d2380421019999d6af768c5df44aa9eaf73affe20d7c54817126
6
+ metadata.gz: 842d17d7290d5a1537766d76bb3c6935b57b19826fa70387af69730af796f684c50a05a85faebc04522da83a7368b128bf433ea6bd3d51c043da8472143f4233
7
+ data.tar.gz: ffb4634e2a02c33ea2e16fb53785d0c72eec929ce439c86bea9b9ea98adb8e75689e25c614d495e5857b6e6fa8f7725621ac9bf9f430c38a5094653de8aaff64
@@ -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
@@ -0,0 +1,86 @@
1
+ module Dev
2
+ # Module containing different classes for interfacing with coverage files
3
+ module Coverage
4
+ # Class for checking code coverage using cobertura
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()
10
+
11
+ @filename = filename
12
+ @local_filename = File.join(local_path || '.', @filename)
13
+ @container_filename = File.join(container_path || '.', @filename)
14
+ @threshold = threshold
15
+ @exclude = (exclude || []).map do |it|
16
+ next it if it.is_a?(Regex)
17
+
18
+ Regex.new(it)
19
+ end
20
+ end
21
+
22
+ # Remove any previous versions of the local file that will be output
23
+ # return the phpunit options needed to regenerate the cobertura xml file
24
+ def php_options
25
+ # Remove any previous coverage info
26
+ FileUtils.rm_f(local_filename, verbose: true)
27
+
28
+ # Return the needed php commands to generate the cobertura report
29
+ %W(--coverage-cobertura #{container_filename})
30
+ end
31
+
32
+ # Parse the cobertura file and check the lines missed against the desired threshold
33
+ def check(application: nil)
34
+ # If an application has been specified and the file does not exist locally, attempt to copy it back from the docker container
35
+ if application && !File.exist?(local_filename)
36
+ container = Dev::Docker::Compose.new.container_by_name(application)
37
+ Dev::Docker.new.copy_from_container(container, container_filename, local_filename, required: true)
38
+ end
39
+
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?
62
+ end
63
+ total = lines_processed.length
64
+
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})"
83
+ end
84
+ end
85
+ end
86
+ 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
@@ -138,8 +138,14 @@ module Dev
138
138
  Docker::Compose.new.mapped_public_port(name, private_port)
139
139
  end
140
140
 
141
+ # Gets the default working dir of the container
142
+ def working_dir(container)
143
+ container.json['Config']['WorkingDir']
144
+ end
145
+
141
146
  # Copies the source path on your local machine to the destination path on the container
142
147
  def copy_to_container(container, source_path, dest_path)
148
+ dest_path = File.join(working_dir(container), dest_path) unless dest_path.start_with?(File::SEPARATOR)
143
149
  LOG.info "Copying #{source_path} to #{dest_path}... "
144
150
 
145
151
  container.archive_in(source_path, dest_path, overwrite: true)
@@ -154,6 +160,7 @@ module Dev
154
160
  # Copies the source path on the container to the destination path on your local machine
155
161
  # If required is set to true, the command will fail if the source path does not exist on the container
156
162
  def copy_from_container(container, source_path, dest_path, required: true)
163
+ source_path = File.join(working_dir(container), source_path) unless source_path.start_with?(File::SEPARATOR)
157
164
  LOG.info "Copying #{source_path} to #{dest_path}... "
158
165
 
159
166
  tar = StringIO.new
@@ -8,11 +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) 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 = nil
16
17
  end
17
18
  end
18
19
 
@@ -30,12 +31,14 @@ module Dev
30
31
  alias_method :configure, :config
31
32
  end
32
33
 
33
- attr_accessor :container_path, :local_path, :package_file
34
+ attr_accessor :container_path, :local_path, :package_file, :coverage
34
35
 
35
- def initialize(container_path: nil, local_path: nil, package_file: nil)
36
+ def initialize(container_path: nil, local_path: nil, package_file: nil, coverage: nil)
36
37
  @container_path = container_path || self.class.config.container_path
37
38
  @local_path = local_path || self.class.config.local_path
38
39
  @package_file = package_file || self.class.config.package_file
40
+ @coverage = coverage || Dev::Coverage::None.new
41
+ raise 'coverage must be an instance of the base class' unless @coverage.is_a?(Dev::Coverage::Base)
39
42
  end
40
43
 
41
44
  # The base npm command that is the starting point for all subsequent commands
@@ -93,10 +96,16 @@ module Dev
93
96
  def test_command
94
97
  test = []
95
98
  test << './vendor/bin/phpunit'
99
+ test.concat(coverage.php_options) if coverage
96
100
  test.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
97
101
  test
98
102
  end
99
103
 
104
+ # Run the check to ensure code coverage meets the desired threshold
105
+ def check_test_coverage(application:)
106
+ coverage.check(application:)
107
+ end
108
+
100
109
  # Build the php fast test command
101
110
  def test_fast_command(processes = 4)
102
111
  test = []
@@ -20,10 +20,12 @@ module Dev
20
20
  container_path: nil,
21
21
  local_path: nil,
22
22
  start_container_dependencies_on_test: true,
23
+ coverage: nil,
23
24
  exclude: []
24
25
  )
25
- @php = Dev::Php.new(container_path:, local_path:)
26
+ @php = Dev::Php.new(container_path:, local_path:, coverage:)
26
27
  @start_container_dependencies_on_test = start_container_dependencies_on_test
28
+
27
29
  super(application, exclude:)
28
30
  end
29
31
 
@@ -133,6 +135,7 @@ module Dev
133
135
  options = []
134
136
  options << '-T' if Dev::Common.new.running_codebuild?
135
137
  Dev::Docker::Compose.new(services: application, options:).exec(*php.test_command)
138
+ php.check_test_coverage(application:)
136
139
  end
137
140
  end
138
141
  end
@@ -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.22'.freeze
9
+ VERSION = '2.1.23'.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.22
4
+ version: 2.1.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Firespring
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-04 00:00:00.000000000 Z
11
+ date: 2024-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -333,6 +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
337
+ - lib/firespring_dev_commands/coverage/cobertura.rb
338
+ - lib/firespring_dev_commands/coverage/none.rb
336
339
  - lib/firespring_dev_commands/daterange.rb
337
340
  - lib/firespring_dev_commands/docker.rb
338
341
  - lib/firespring_dev_commands/docker/compose.rb