polyrun 1.1.0 → 1.3.0
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/CHANGELOG.md +19 -0
- data/README.md +1 -1
- data/lib/polyrun/cli/ci_shard_run_command.rb +97 -2
- data/lib/polyrun/cli/ci_shard_run_parse.rb +68 -0
- data/lib/polyrun/cli/config_command.rb +42 -0
- data/lib/polyrun/cli/default_run.rb +115 -0
- data/lib/polyrun/cli/help.rb +54 -0
- data/lib/polyrun/cli/helpers.rb +4 -31
- data/lib/polyrun/cli/plan_command.rb +22 -12
- data/lib/polyrun/cli/prepare_command.rb +2 -2
- data/lib/polyrun/cli/queue_command.rb +46 -19
- data/lib/polyrun/cli/run_shards_command.rb +62 -5
- data/lib/polyrun/cli/run_shards_plan_boot_phases.rb +1 -1
- data/lib/polyrun/cli/run_shards_plan_options.rb +1 -1
- data/lib/polyrun/cli/run_shards_planning.rb +8 -8
- data/lib/polyrun/cli/run_shards_run.rb +4 -2
- data/lib/polyrun/cli/start_bootstrap.rb +2 -6
- data/lib/polyrun/cli.rb +46 -50
- data/lib/polyrun/config/dotted_path.rb +21 -0
- data/lib/polyrun/config/effective.rb +72 -0
- data/lib/polyrun/config/resolver.rb +78 -0
- data/lib/polyrun/config.rb +7 -0
- data/lib/polyrun/coverage/collector.rb +15 -9
- data/lib/polyrun/coverage/collector_finish.rb +2 -0
- data/lib/polyrun/coverage/collector_fragment_meta.rb +57 -0
- data/lib/polyrun/partition/paths.rb +83 -2
- data/lib/polyrun/quick/runner.rb +26 -17
- data/lib/polyrun/templates/ci_matrix.polyrun.yml +3 -2
- data/lib/polyrun/version.rb +1 -1
- metadata +9 -1
|
@@ -8,6 +8,7 @@ require_relative "formatter"
|
|
|
8
8
|
require_relative "merge"
|
|
9
9
|
require_relative "result"
|
|
10
10
|
require_relative "track_files"
|
|
11
|
+
require_relative "collector_fragment_meta"
|
|
11
12
|
require_relative "../debug"
|
|
12
13
|
|
|
13
14
|
module Polyrun
|
|
@@ -24,7 +25,7 @@ module Polyrun
|
|
|
24
25
|
|
|
25
26
|
# @param root [String] project root (absolute or relative)
|
|
26
27
|
# @param reject_patterns [Array<String>] path substrings to drop (like SimpleCov add_filter)
|
|
27
|
-
# @param output_path [String, nil] default
|
|
28
|
+
# @param output_path [String, nil] default see {.fragment_default_basename_from_env}
|
|
28
29
|
# @param minimum_line_percent [Float, nil] exit 1 if below (when strict)
|
|
29
30
|
# @param strict [Boolean] whether to exit non-zero on threshold failure (default true when minimum set)
|
|
30
31
|
# @param track_under [Array<String>] when +track_files+ is nil, only keep coverage keys under these dirs relative to +root+. Default +["lib"]+.
|
|
@@ -34,18 +35,25 @@ module Polyrun
|
|
|
34
35
|
# @param formatter [Object, nil] Object responding to +format(result, output_dir:, basename:)+ like SimpleCov formatters (e.g. {Formatter.multi} or {Formatter::MultiFormatter})
|
|
35
36
|
# @param report_output_dir [String, nil] directory for +formatter+ outputs (default +coverage/+ under +root+)
|
|
36
37
|
# @param report_basename [String] file prefix for formatter outputs (default +polyrun-coverage+)
|
|
38
|
+
# See {CollectorFragmentMeta.fragment_default_basename_from_env}.
|
|
39
|
+
def self.fragment_default_basename_from_env(env = ENV)
|
|
40
|
+
CollectorFragmentMeta.fragment_default_basename_from_env(env)
|
|
41
|
+
end
|
|
42
|
+
|
|
37
43
|
def start!(root:, reject_patterns: [], track_under: ["lib"], track_files: nil, groups: nil, output_path: nil, minimum_line_percent: nil, strict: nil, meta: {}, formatter: nil, report_output_dir: nil, report_basename: "polyrun-coverage")
|
|
38
44
|
return if disabled?
|
|
39
45
|
|
|
40
46
|
root = File.expand_path(root)
|
|
41
|
-
|
|
42
|
-
output_path ||= File.join(root, "coverage", "polyrun-fragment-#{
|
|
47
|
+
basename = fragment_default_basename_from_env
|
|
48
|
+
output_path ||= File.join(root, "coverage", "polyrun-fragment-#{basename}.json")
|
|
43
49
|
strict = if minimum_line_percent.nil?
|
|
44
50
|
false
|
|
45
51
|
else
|
|
46
52
|
strict.nil? || strict
|
|
47
53
|
end
|
|
48
54
|
|
|
55
|
+
fragment_meta = CollectorFragmentMeta.fragment_meta_from_env(basename)
|
|
56
|
+
|
|
49
57
|
@config = {
|
|
50
58
|
root: root,
|
|
51
59
|
track_under: Array(track_under).map(&:to_s),
|
|
@@ -59,7 +67,8 @@ module Polyrun
|
|
|
59
67
|
formatter: formatter,
|
|
60
68
|
report_output_dir: report_output_dir,
|
|
61
69
|
report_basename: report_basename,
|
|
62
|
-
shard_total_at_start: ENV["POLYRUN_SHARD_TOTAL"].to_i
|
|
70
|
+
shard_total_at_start: ENV["POLYRUN_SHARD_TOTAL"].to_i,
|
|
71
|
+
fragment_meta: fragment_meta
|
|
63
72
|
}
|
|
64
73
|
|
|
65
74
|
unless ::Coverage.running?
|
|
@@ -110,11 +119,7 @@ module Polyrun
|
|
|
110
119
|
end
|
|
111
120
|
|
|
112
121
|
def self.finish_debug_time_label
|
|
113
|
-
|
|
114
|
-
"worker pid=#{$$} shard=#{ENV.fetch("POLYRUN_SHARD_INDEX", "?")} Coverage::Collector.finish (write fragment)"
|
|
115
|
-
else
|
|
116
|
-
"Coverage::Collector.finish (write fragment)"
|
|
117
|
-
end
|
|
122
|
+
CollectorFragmentMeta.finish_debug_time_label
|
|
118
123
|
end
|
|
119
124
|
|
|
120
125
|
def build_meta(cfg)
|
|
@@ -123,6 +128,7 @@ module Polyrun
|
|
|
123
128
|
m["timestamp"] ||= Time.now.to_i
|
|
124
129
|
m["command_name"] ||= "rspec"
|
|
125
130
|
m["polyrun_coverage_root"] = cfg[:root].to_s
|
|
131
|
+
CollectorFragmentMeta.merge_fragment_meta!(m, cfg[:fragment_meta])
|
|
126
132
|
if cfg[:groups]
|
|
127
133
|
m["polyrun_coverage_groups"] = cfg[:groups].transform_keys(&:to_s).transform_values(&:to_s)
|
|
128
134
|
end
|
|
@@ -12,6 +12,8 @@ module Polyrun
|
|
|
12
12
|
collector_finish: "start",
|
|
13
13
|
polyrun_shard_index: ENV["POLYRUN_SHARD_INDEX"],
|
|
14
14
|
polyrun_shard_total: ENV["POLYRUN_SHARD_TOTAL"],
|
|
15
|
+
polyrun_shard_matrix_index: ENV["POLYRUN_SHARD_MATRIX_INDEX"],
|
|
16
|
+
polyrun_shard_matrix_total: ENV["POLYRUN_SHARD_MATRIX_TOTAL"],
|
|
15
17
|
output_path: cfg[:output_path]
|
|
16
18
|
)
|
|
17
19
|
Polyrun::Debug.time(Collector.finish_debug_time_label) do
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Polyrun
|
|
2
|
+
module Coverage
|
|
3
|
+
# Shard / worker naming for coverage JSON fragments (N×M CI vs run-shards).
|
|
4
|
+
module CollectorFragmentMeta
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
# Default fragment basename (no extension) for +coverage/polyrun-fragment-<basename>.json+.
|
|
8
|
+
def fragment_default_basename_from_env(env = ENV)
|
|
9
|
+
local = env.fetch("POLYRUN_SHARD_INDEX", "0")
|
|
10
|
+
mt = env["POLYRUN_SHARD_MATRIX_TOTAL"].to_i
|
|
11
|
+
if mt > 1
|
|
12
|
+
mi = env.fetch("POLYRUN_SHARD_MATRIX_INDEX", "0")
|
|
13
|
+
"shard#{mi}-worker#{local}"
|
|
14
|
+
elsif env["POLYRUN_SHARD_TOTAL"].to_i > 1
|
|
15
|
+
"worker#{local}"
|
|
16
|
+
else
|
|
17
|
+
local
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def finish_debug_time_label
|
|
22
|
+
mt = ENV["POLYRUN_SHARD_MATRIX_TOTAL"].to_i
|
|
23
|
+
if mt > 1
|
|
24
|
+
"worker pid=#{$$} shard(matrix)=#{ENV.fetch("POLYRUN_SHARD_MATRIX_INDEX", "?")} worker(local)=#{ENV.fetch("POLYRUN_SHARD_INDEX", "?")} Coverage::Collector.finish (write fragment)"
|
|
25
|
+
elsif ENV["POLYRUN_SHARD_TOTAL"].to_i > 1
|
|
26
|
+
"worker pid=#{$$} worker=#{ENV.fetch("POLYRUN_SHARD_INDEX", "?")} Coverage::Collector.finish (write fragment)"
|
|
27
|
+
else
|
|
28
|
+
"Coverage::Collector.finish (write fragment)"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def fragment_meta_from_env(basename)
|
|
33
|
+
mt = ENV["POLYRUN_SHARD_MATRIX_TOTAL"].to_i
|
|
34
|
+
{
|
|
35
|
+
basename: basename,
|
|
36
|
+
worker_index: ENV.fetch("POLYRUN_SHARD_INDEX", "0"),
|
|
37
|
+
shard_matrix_index: shard_matrix_index_value(mt)
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def shard_matrix_index_value(matrix_total)
|
|
42
|
+
return nil if matrix_total <= 1
|
|
43
|
+
|
|
44
|
+
ENV.fetch("POLYRUN_SHARD_MATRIX_INDEX", "0")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def merge_fragment_meta!(m, fm)
|
|
48
|
+
return m if fm.nil?
|
|
49
|
+
|
|
50
|
+
m["polyrun_fragment_basename"] = fm[:basename].to_s if fm[:basename]
|
|
51
|
+
m["polyrun_worker_index"] = fm[:worker_index].to_s if fm[:worker_index]
|
|
52
|
+
m["polyrun_shard_matrix_index"] = fm[:shard_matrix_index].to_s if fm[:shard_matrix_index]
|
|
53
|
+
m
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -8,9 +8,45 @@ module Polyrun
|
|
|
8
8
|
File.read(File.expand_path(path.to_s, Dir.pwd)).split("\n").map(&:strip).reject(&:empty?)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
# Prefer +spec/+ RSpec files, then +test/+ Minitest, then Polyrun Quick files (same globs as +polyrun quick+).
|
|
12
|
+
# Order avoids running the broader Quick glob when RSpec or Minitest files already exist.
|
|
13
|
+
def detect_auto_suite(cwd = Dir.pwd)
|
|
14
|
+
base = File.expand_path(cwd)
|
|
15
|
+
return :rspec if Dir.glob(File.join(base, "spec/**/*_spec.rb")).any?
|
|
16
|
+
|
|
17
|
+
return :minitest if Dir.glob(File.join(base, "test/**/*_test.rb")).any?
|
|
18
|
+
|
|
19
|
+
quick = quick_parallel_default_paths(base)
|
|
20
|
+
return :quick if quick.any?
|
|
21
|
+
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Infer parallel suite from explicit paths (+_spec.rb+ vs +_test.rb+ vs Polyrun quick-style +.rb+).
|
|
26
|
+
# Returns +:rspec+, +:minitest+, +:quick+, +:invalid+ (mixed spec and test), or +nil+ (empty).
|
|
27
|
+
def infer_suite_from_paths(paths)
|
|
28
|
+
paths = paths.map { |p| File.expand_path(p) }
|
|
29
|
+
return nil if paths.empty?
|
|
30
|
+
|
|
31
|
+
specs = paths.count { |p| File.basename(p).end_with?("_spec.rb") }
|
|
32
|
+
tests = paths.count { |p| File.basename(p).end_with?("_test.rb") }
|
|
33
|
+
return :invalid if specs.positive? && tests.positive?
|
|
34
|
+
|
|
35
|
+
return :rspec if specs.positive?
|
|
36
|
+
return :minitest if tests.positive?
|
|
37
|
+
|
|
38
|
+
others = paths.size - specs - tests
|
|
39
|
+
return :quick if others.positive?
|
|
40
|
+
|
|
41
|
+
nil
|
|
42
|
+
end
|
|
43
|
+
|
|
11
44
|
# When +paths_file+ is set but missing, returns +{ error: "..." }+.
|
|
12
45
|
# Otherwise returns +{ items:, source: }+ (human-readable source label).
|
|
13
|
-
|
|
46
|
+
#
|
|
47
|
+
# +partition.suite+ (optional): +auto+ (default), +rspec+, +minitest+, +quick+ — used only when resolving
|
|
48
|
+
# from globs (no explicit +paths_file+ and no +spec/spec_paths.txt+).
|
|
49
|
+
def resolve_run_shard_items(paths_file: nil, cwd: Dir.pwd, partition: {})
|
|
14
50
|
if paths_file
|
|
15
51
|
abs = File.expand_path(paths_file.to_s, cwd)
|
|
16
52
|
unless File.file?(abs)
|
|
@@ -20,9 +56,54 @@ module Polyrun
|
|
|
20
56
|
elsif File.file?(File.join(cwd, "spec", "spec_paths.txt"))
|
|
21
57
|
{items: read_lines(File.join(cwd, "spec", "spec_paths.txt")), source: "spec/spec_paths.txt"}
|
|
22
58
|
else
|
|
23
|
-
|
|
59
|
+
resolve_run_shard_items_glob(cwd: cwd, partition: partition)
|
|
24
60
|
end
|
|
25
61
|
end
|
|
62
|
+
|
|
63
|
+
def resolve_run_shard_items_glob(cwd:, partition: {})
|
|
64
|
+
suite = (partition["suite"] || partition[:suite] || "auto").to_s.downcase
|
|
65
|
+
suite = "auto" if suite.empty?
|
|
66
|
+
|
|
67
|
+
base = File.expand_path(cwd)
|
|
68
|
+
spec = Dir.glob(File.join(base, "spec/**/*_spec.rb")).sort
|
|
69
|
+
test = Dir.glob(File.join(base, "test/**/*_test.rb")).sort
|
|
70
|
+
quick = quick_parallel_default_paths(base)
|
|
71
|
+
|
|
72
|
+
case suite
|
|
73
|
+
when "rspec"
|
|
74
|
+
return {error: "partition.suite is rspec but no spec/**/*_spec.rb files"} if spec.empty?
|
|
75
|
+
|
|
76
|
+
{items: spec, source: "spec/**/*_spec.rb glob"}
|
|
77
|
+
when "minitest"
|
|
78
|
+
return {error: "partition.suite is minitest but no test/**/*_test.rb files"} if test.empty?
|
|
79
|
+
|
|
80
|
+
{items: test, source: "test/**/*_test.rb glob"}
|
|
81
|
+
when "quick"
|
|
82
|
+
return {error: "partition.suite is quick but no Polyrun quick files under spec/ or test/"} if quick.empty?
|
|
83
|
+
|
|
84
|
+
{items: quick, source: "Polyrun quick glob"}
|
|
85
|
+
when "auto"
|
|
86
|
+
if spec.any?
|
|
87
|
+
{items: spec, source: "spec/**/*_spec.rb glob"}
|
|
88
|
+
elsif test.any?
|
|
89
|
+
{items: test, source: "test/**/*_test.rb glob"}
|
|
90
|
+
elsif quick.any?
|
|
91
|
+
{items: quick, source: "Polyrun quick glob"}
|
|
92
|
+
else
|
|
93
|
+
{
|
|
94
|
+
error: "no spec paths (spec/spec_paths.txt, partition.paths_file, or spec/**/*_spec.rb); " \
|
|
95
|
+
"no test/**/*_test.rb; no Polyrun quick files"
|
|
96
|
+
}
|
|
97
|
+
end
|
|
98
|
+
else
|
|
99
|
+
{error: "unknown partition.suite: #{suite.inspect} (expected auto, rspec, minitest, quick)"}
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def quick_parallel_default_paths(base)
|
|
104
|
+
require_relative "../quick/runner"
|
|
105
|
+
Polyrun::Quick::Runner.parallel_default_paths(base)
|
|
106
|
+
end
|
|
26
107
|
end
|
|
27
108
|
end
|
|
28
109
|
end
|
data/lib/polyrun/quick/runner.rb
CHANGED
|
@@ -62,6 +62,30 @@ module Polyrun
|
|
|
62
62
|
new(out: out, err: err, verbose: verbose).run(paths)
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
+
# Files Polyrun::Quick would run with no explicit paths (excludes normal RSpec/Minitest files).
|
|
66
|
+
def self.parallel_default_paths(cwd = Dir.pwd)
|
|
67
|
+
base = File.expand_path(cwd)
|
|
68
|
+
globs = [
|
|
69
|
+
File.join(base, "spec", "polyrun_quick", "**", "*.rb"),
|
|
70
|
+
File.join(base, "test", "polyrun_quick", "**", "*.rb"),
|
|
71
|
+
File.join(base, "spec", "**", "*.rb"),
|
|
72
|
+
File.join(base, "test", "**", "*.rb")
|
|
73
|
+
]
|
|
74
|
+
globs.flat_map { |g| Dir.glob(g) }.uniq.reject { |p| quick_path_excluded?(p, base) }.sort
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def self.quick_path_excluded?(path, base)
|
|
78
|
+
rel = Pathname.new(path).relative_path_from(Pathname.new(base)).to_s
|
|
79
|
+
parts = rel.split(File::SEPARATOR)
|
|
80
|
+
bn = File.basename(path)
|
|
81
|
+
return true if bn.end_with?("_spec.rb", "_test.rb")
|
|
82
|
+
return true if %w[spec_helper.rb rails_helper.rb test_helper.rb].include?(bn)
|
|
83
|
+
return true if parts[0] == "spec" && %w[support fixtures factories].include?(parts[1])
|
|
84
|
+
return true if parts[0] == "test" && %w[support fixtures].include?(parts[1])
|
|
85
|
+
|
|
86
|
+
false
|
|
87
|
+
end
|
|
88
|
+
|
|
65
89
|
def initialize(out: $stdout, err: $stderr, verbose: false)
|
|
66
90
|
@out = out
|
|
67
91
|
@err = err
|
|
@@ -153,27 +177,12 @@ module Polyrun
|
|
|
153
177
|
end
|
|
154
178
|
|
|
155
179
|
def default_globs
|
|
156
|
-
|
|
157
|
-
globs = [
|
|
158
|
-
File.join(base, "spec", "polyrun_quick", "**", "*.rb"),
|
|
159
|
-
File.join(base, "test", "polyrun_quick", "**", "*.rb"),
|
|
160
|
-
File.join(base, "spec", "**", "*.rb"),
|
|
161
|
-
File.join(base, "test", "**", "*.rb")
|
|
162
|
-
]
|
|
163
|
-
globs.flat_map { |g| Dir.glob(g) }.uniq.reject { |p| default_quick_exclude?(p, base) }.sort
|
|
180
|
+
Runner.parallel_default_paths(Dir.pwd)
|
|
164
181
|
end
|
|
165
182
|
|
|
166
183
|
# Omit RSpec/Minitest files and common helpers so +polyrun quick+ with no args does not load normal suites.
|
|
167
184
|
def default_quick_exclude?(path, base)
|
|
168
|
-
|
|
169
|
-
parts = rel.split(File::SEPARATOR)
|
|
170
|
-
bn = File.basename(path)
|
|
171
|
-
return true if bn.end_with?("_spec.rb", "_test.rb")
|
|
172
|
-
return true if %w[spec_helper.rb rails_helper.rb test_helper.rb].include?(bn)
|
|
173
|
-
return true if parts[0] == "spec" && %w[support fixtures factories].include?(parts[1])
|
|
174
|
-
return true if parts[0] == "test" && %w[support fixtures].include?(parts[1])
|
|
175
|
-
|
|
176
|
-
false
|
|
185
|
+
Runner.quick_path_excluded?(path, base)
|
|
177
186
|
end
|
|
178
187
|
end
|
|
179
188
|
end
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
# bundle exec polyrun -c polyrun.yml ci-shard-run -- bundle exec rspec
|
|
4
4
|
# (or ci-shard-rspec; or e.g. ci-shard-run -- bundle exec polyrun quick).
|
|
5
5
|
# Equivalent to build-paths, plan --shard/--total, then run that command with this slice's paths.
|
|
6
|
-
# A separate CI job downloads coverage/polyrun-fragment-*.json and runs merge-coverage.
|
|
7
|
-
#
|
|
6
|
+
# A separate CI job downloads coverage/polyrun-fragment-*.json (e.g. shard<S>-worker<W>.json per N×M process) and runs merge-coverage.
|
|
7
|
+
# For N×M (N matrix jobs × M processes per job): set shard_processes: M or POLYRUN_SHARD_PROCESSES,
|
|
8
|
+
# or pass --shard-processes M to ci-shard-run / ci-shard-rspec (local split is round-robin).
|
|
8
9
|
# See: docs/SETUP_PROFILE.md
|
|
9
10
|
|
|
10
11
|
partition:
|
data/lib/polyrun/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: polyrun
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrei Makarov
|
|
@@ -167,10 +167,14 @@ files:
|
|
|
167
167
|
- lib/polyrun.rb
|
|
168
168
|
- lib/polyrun/cli.rb
|
|
169
169
|
- lib/polyrun/cli/ci_shard_run_command.rb
|
|
170
|
+
- lib/polyrun/cli/ci_shard_run_parse.rb
|
|
171
|
+
- lib/polyrun/cli/config_command.rb
|
|
170
172
|
- lib/polyrun/cli/coverage_commands.rb
|
|
171
173
|
- lib/polyrun/cli/coverage_merge_io.rb
|
|
172
174
|
- lib/polyrun/cli/database_commands.rb
|
|
175
|
+
- lib/polyrun/cli/default_run.rb
|
|
173
176
|
- lib/polyrun/cli/env_commands.rb
|
|
177
|
+
- lib/polyrun/cli/help.rb
|
|
174
178
|
- lib/polyrun/cli/helpers.rb
|
|
175
179
|
- lib/polyrun/cli/init_command.rb
|
|
176
180
|
- lib/polyrun/cli/plan_command.rb
|
|
@@ -187,9 +191,13 @@ files:
|
|
|
187
191
|
- lib/polyrun/cli/start_bootstrap.rb
|
|
188
192
|
- lib/polyrun/cli/timing_command.rb
|
|
189
193
|
- lib/polyrun/config.rb
|
|
194
|
+
- lib/polyrun/config/dotted_path.rb
|
|
195
|
+
- lib/polyrun/config/effective.rb
|
|
196
|
+
- lib/polyrun/config/resolver.rb
|
|
190
197
|
- lib/polyrun/coverage/cobertura_zero_lines.rb
|
|
191
198
|
- lib/polyrun/coverage/collector.rb
|
|
192
199
|
- lib/polyrun/coverage/collector_finish.rb
|
|
200
|
+
- lib/polyrun/coverage/collector_fragment_meta.rb
|
|
193
201
|
- lib/polyrun/coverage/filter.rb
|
|
194
202
|
- lib/polyrun/coverage/formatter.rb
|
|
195
203
|
- lib/polyrun/coverage/merge.rb
|