firespring_dev_commands 2.1.21.pre.alpha.9 → 2.1.22.pre.alpha.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/lib/firespring_dev_commands/docker.rb +0 -7
- data/lib/firespring_dev_commands/php.rb +3 -11
- data/lib/firespring_dev_commands/target_process/query.rb +30 -4
- data/lib/firespring_dev_commands/target_process.rb +2 -0
- data/lib/firespring_dev_commands/templates/docker/php/application.rb +1 -4
- data/lib/firespring_dev_commands/version.rb +1 -1
- metadata +2 -5
- data/lib/firespring_dev_commands/coverage/base.rb +0 -13
- data/lib/firespring_dev_commands/coverage/cobertura.rb +0 -86
- data/lib/firespring_dev_commands/coverage/none.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7846bf81995b28016a6f50953c105e3e6ffd5254f840c5d1932d5809d74ec5db
|
4
|
+
data.tar.gz: 398648a97d3b46270bfec9e5d9f954c743bef815f37e8bf2bcae97461e4619aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3feaa407786cb229b54e028f24e3771163ccfd615468a749f830e8a03f79fc0c45178762fff603902df216837ad95a128937e89fff56ffd6238cdd898c0465f1
|
7
|
+
data.tar.gz: ce23794f53be4086d5df5edbcaa2ce99ed506ef098b550d8b68a19a81b11b82549b41c60d4a3d42d59de9c13ad610c95e743df612147381dcc67075e474e1804
|
@@ -138,14 +138,8 @@ 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
|
-
|
146
141
|
# Copies the source path on your local machine to the destination path on the container
|
147
142
|
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)
|
149
143
|
LOG.info "Copying #{source_path} to #{dest_path}... "
|
150
144
|
|
151
145
|
container.archive_in(source_path, dest_path, overwrite: true)
|
@@ -160,7 +154,6 @@ module Dev
|
|
160
154
|
# Copies the source path on the container to the destination path on your local machine
|
161
155
|
# If required is set to true, the command will fail if the source path does not exist on the container
|
162
156
|
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)
|
164
157
|
LOG.info "Copying #{source_path} to #{dest_path}... "
|
165
158
|
|
166
159
|
tar = StringIO.new
|
@@ -8,12 +8,11 @@ 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
|
11
|
+
Config = Struct.new(:container_path, :local_path, :package_file) 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
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
@@ -31,13 +30,12 @@ module Dev
|
|
31
30
|
alias_method :configure, :config
|
32
31
|
end
|
33
32
|
|
34
|
-
attr_accessor :container_path, :local_path, :package_file
|
33
|
+
attr_accessor :container_path, :local_path, :package_file
|
35
34
|
|
36
|
-
def initialize(container_path: nil, local_path: nil, package_file: nil
|
35
|
+
def initialize(container_path: nil, local_path: nil, package_file: nil)
|
37
36
|
@container_path = container_path || self.class.config.container_path
|
38
37
|
@local_path = local_path || self.class.config.local_path
|
39
38
|
@package_file = package_file || self.class.config.package_file
|
40
|
-
@coverage = coverage || Dev::Coverage::None.new
|
41
39
|
end
|
42
40
|
|
43
41
|
# The base npm command that is the starting point for all subsequent commands
|
@@ -95,16 +93,10 @@ module Dev
|
|
95
93
|
def test_command
|
96
94
|
test = []
|
97
95
|
test << './vendor/bin/phpunit'
|
98
|
-
test.concat(coverage.php_options) if coverage
|
99
96
|
test.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
|
100
97
|
test
|
101
98
|
end
|
102
99
|
|
103
|
-
# Run the check to ensure code coverage meets the desired threshold
|
104
|
-
def check_test_coverage(application:)
|
105
|
-
coverage.check(application:)
|
106
|
-
end
|
107
|
-
|
108
100
|
# Build the php fast test command
|
109
101
|
def test_fast_command(processes = 4)
|
110
102
|
test = []
|
@@ -2,12 +2,13 @@ module Dev
|
|
2
2
|
class TargetProcess
|
3
3
|
# Class for writing target process query statements
|
4
4
|
class Query
|
5
|
-
attr_accessor :where, :incl, :take
|
5
|
+
attr_accessor :where, :incl, :take, :empty
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
@where = []
|
9
9
|
@incl = []
|
10
10
|
@take = 250
|
11
|
+
@empty = false
|
11
12
|
end
|
12
13
|
|
13
14
|
# Add a new query clause
|
@@ -33,6 +34,11 @@ module Dev
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
37
|
+
# Check if any of the "in" statements were empty. If so then we don't want to actually run the query
|
38
|
+
def empty?
|
39
|
+
@empty == true
|
40
|
+
end
|
41
|
+
|
36
42
|
# Generate the string representation for this query
|
37
43
|
def generate
|
38
44
|
{}.tap do |clause|
|
@@ -50,22 +56,38 @@ module Dev
|
|
50
56
|
# TODO: Do these need moved to their associated entities?
|
51
57
|
# Add a filter that looks for stories whose id is contained in the list of ids given
|
52
58
|
def filter_by_user_story_ids(user_story_ids)
|
59
|
+
if user_story_ids.nil? || user_story_ids.empty?
|
60
|
+
@empty = true
|
61
|
+
return
|
62
|
+
end
|
53
63
|
self << "(Id in ('#{user_story_ids.join("', '")}'))"
|
54
64
|
end
|
55
65
|
|
56
66
|
# Add a filter that looks for stories whose team id is contained in the list of ids given
|
57
67
|
def filter_by_team_ids(team_ids)
|
58
|
-
|
68
|
+
if team_ids.nil? || team_ids.empty?
|
69
|
+
@empty = true
|
70
|
+
return
|
71
|
+
end
|
72
|
+
self << "(Team.Id in ('#{team_ids.join("', '")}'))"
|
59
73
|
end
|
60
74
|
|
61
75
|
# Add a filter that looks for stories whose project id is contained in the list of ids given
|
62
76
|
def filter_by_project(projects)
|
77
|
+
if projects.nil? || projects.empty?
|
78
|
+
@empty = true
|
79
|
+
return
|
80
|
+
end
|
63
81
|
self << "(Project.Name in ('#{projects.join("', '")}'))"
|
64
82
|
end
|
65
83
|
|
66
84
|
# Add a filter that looks for stories whose state is contained in the list of states given
|
67
85
|
def filter_by_states(states)
|
68
|
-
|
86
|
+
if states.nil? || states.empty?
|
87
|
+
@empty = true
|
88
|
+
return
|
89
|
+
end
|
90
|
+
self << "(EntityState.Name in ('#{states.join("', '")}'))"
|
69
91
|
end
|
70
92
|
|
71
93
|
# Add a filter that looks for stories whose state is set to final
|
@@ -114,7 +136,11 @@ module Dev
|
|
114
136
|
|
115
137
|
# Add a filter that looks for assignable ids which are included in the given array
|
116
138
|
def filter_by_entity_ids(entity_ids)
|
117
|
-
|
139
|
+
if entity_ids.nil? || entity_ids.empty?
|
140
|
+
@empty = true
|
141
|
+
return
|
142
|
+
end
|
143
|
+
self << "(Assignable.Id in ('#{entity_ids.join("', '")}'))"
|
118
144
|
end
|
119
145
|
|
120
146
|
# Add a filter that looks for a custom deploy date between the given dates`
|
@@ -117,6 +117,8 @@ module Dev
|
|
117
117
|
# Call the given block (if present) with each piece of data
|
118
118
|
# Return all pieces of data
|
119
119
|
def get(path, query, &)
|
120
|
+
return [] if query.empty?
|
121
|
+
|
120
122
|
query_string = query.generate
|
121
123
|
url = "/api/v1/#{path}"
|
122
124
|
url << "?#{URI.encode_www_form(query_string)}" unless query_string.empty?
|
@@ -20,12 +20,10 @@ module Dev
|
|
20
20
|
container_path: nil,
|
21
21
|
local_path: nil,
|
22
22
|
start_container_dependencies_on_test: true,
|
23
|
-
coverage: nil,
|
24
23
|
exclude: []
|
25
24
|
)
|
26
|
-
@php = Dev::Php.new(container_path:, local_path
|
25
|
+
@php = Dev::Php.new(container_path:, local_path:)
|
27
26
|
@start_container_dependencies_on_test = start_container_dependencies_on_test
|
28
|
-
|
29
27
|
super(application, exclude:)
|
30
28
|
end
|
31
29
|
|
@@ -135,7 +133,6 @@ module Dev
|
|
135
133
|
options = []
|
136
134
|
options << '-T' if Dev::Common.new.running_codebuild?
|
137
135
|
Dev::Docker::Compose.new(services: application, options:).exec(*php.test_command)
|
138
|
-
php.check_test_coverage(application:)
|
139
136
|
end
|
140
137
|
end
|
141
138
|
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.
|
4
|
+
version: 2.1.22.pre.alpha.1
|
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-
|
11
|
+
date: 2024-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -333,9 +333,6 @@ 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
|
339
336
|
- lib/firespring_dev_commands/daterange.rb
|
340
337
|
- lib/firespring_dev_commands/docker.rb
|
341
338
|
- lib/firespring_dev_commands/docker/compose.rb
|
@@ -1,86 +0,0 @@
|
|
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
|