firespring_dev_commands 2.1.21.pre.alpha.9 → 2.1.22.pre.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|