branchproof 0.11.1 → 0.12.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 +82 -0
- data/README.md +440 -29
- data/doc/Branchproof/CLI.md +1 -1
- data/doc/Branchproof/ChangedCoverage.md +19 -0
- data/doc/Branchproof/ChangedCoveragePolicy.md +24 -0
- data/doc/Branchproof/ChangedDecisionMap.md +20 -0
- data/doc/Branchproof/ChangedScope.md +18 -0
- data/doc/Branchproof/Collation.md +23 -0
- data/doc/Branchproof/CollationManifest.md +29 -0
- data/doc/Branchproof/CoverageSummary.md +20 -0
- data/doc/Branchproof/Doctor/TerminalRenderer.md +15 -0
- data/doc/Branchproof/Doctor.md +34 -0
- data/doc/Branchproof/FallbackInstrumentation.md +8 -0
- data/doc/Branchproof/FallbackRuntime.md +12 -0
- data/doc/Branchproof/FallbackSyntax.md +13 -0
- data/doc/Branchproof/GitChanges.md +19 -0
- data/doc/Branchproof/GithubReport.md +25 -0
- data/doc/Branchproof/HtmlReport.md +22 -0
- data/doc/Branchproof/Instrumenter.md +1 -1
- data/doc/Branchproof/MinitestAdapter.md +4 -0
- data/doc/Branchproof/RakeTask.md +121 -0
- data/doc/Branchproof/Report.md +41 -3
- data/doc/Branchproof/ReportSelection.md +10 -1
- data/doc/Branchproof/Runtime.md +4 -1
- data/doc/Branchproof/Source.md +1 -1
- data/doc/Branchproof/SummaryRanking/Decision.md +86 -0
- data/doc/Branchproof/SummaryRanking/SourceFile.md +43 -0
- data/doc/Branchproof/SummaryRanking.md +36 -0
- data/doc/Branchproof/SummaryReport.md +42 -0
- data/doc/Branchproof/Worker.md +1 -1
- data/doc/Branchproof.md +21 -1
- data/doc/CHANGELOG.md +82 -0
- data/doc/README.md +440 -29
- data/lib/branchproof/analyzer.rb +2 -52
- data/lib/branchproof/changed_coverage.rb +177 -0
- data/lib/branchproof/changed_decision_map.rb +359 -0
- data/lib/branchproof/changed_scope.rb +93 -0
- data/lib/branchproof/cli.rb +242 -21
- data/lib/branchproof/collation.rb +525 -0
- data/lib/branchproof/collation_manifest.rb +129 -0
- data/lib/branchproof/comparison.rb +11 -3
- data/lib/branchproof/comparison_report.rb +2 -0
- data/lib/branchproof/configuration.rb +12 -2
- data/lib/branchproof/coverage_policy.rb +122 -0
- data/lib/branchproof/coverage_summary.rb +94 -0
- data/lib/branchproof/doctor.rb +241 -0
- data/lib/branchproof/evidence.rb +5 -1
- data/lib/branchproof/exception_instrumentation.rb +4 -3
- data/lib/branchproof/exception_syntax.rb +15 -1
- data/lib/branchproof/fallback_instrumentation.rb +25 -0
- data/lib/branchproof/fallback_runtime.rb +14 -0
- data/lib/branchproof/fallback_syntax.rb +90 -0
- data/lib/branchproof/focused_report.rb +81 -22
- data/lib/branchproof/git_changes.rb +188 -0
- data/lib/branchproof/github_report.rb +292 -0
- data/lib/branchproof/html_report.rb +412 -0
- data/lib/branchproof/instrumenter.rb +2 -0
- data/lib/branchproof/minimizer.rb +4 -2
- data/lib/branchproof/minitest_adapter.rb +45 -5
- data/lib/branchproof/rails_support.rb +2 -2
- data/lib/branchproof/rake_task.rb +186 -0
- data/lib/branchproof/report.rb +383 -71
- data/lib/branchproof/report_selection.rb +26 -5
- data/lib/branchproof/runtime.rb +2 -0
- data/lib/branchproof/saved_report.rb +323 -5
- data/lib/branchproof/source.rb +15 -3
- data/lib/branchproof/summary_ranking.rb +165 -0
- data/lib/branchproof/summary_report.rb +241 -0
- data/lib/branchproof/version.rb +1 -1
- data/lib/branchproof/worker.rb +14 -9
- data/lib/branchproof.rb +12 -0
- data/llms.txt +21 -1
- data/sig/branchproof.rbs +206 -5
- metadata +39 -23
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "English"
|
|
4
|
+
require "rake"
|
|
5
|
+
require "rake/tasklib"
|
|
6
|
+
require "rbconfig"
|
|
7
|
+
require_relative "../branchproof"
|
|
8
|
+
|
|
9
|
+
module Branchproof
|
|
10
|
+
# Defines a Rake task that runs `branchproof analyze` in a subprocess.
|
|
11
|
+
#
|
|
12
|
+
# The task shells out to the `branchproof` executable, so the isolated
|
|
13
|
+
# worker model is unchanged. Only options the Rakefile sets are passed as
|
|
14
|
+
# CLI flags. Everything else keeps the CLI default, and `.branchproof.json`
|
|
15
|
+
# precedence stays intact.
|
|
16
|
+
#
|
|
17
|
+
# @example Minitest project
|
|
18
|
+
# require "branchproof/rake_task"
|
|
19
|
+
#
|
|
20
|
+
# Branchproof::RakeTask.new(:branchproof) do |t|
|
|
21
|
+
# t.sources = ["lib/**/*.rb"]
|
|
22
|
+
# t.tests = ["test/**/*_test.rb"]
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# @example RSpec project with a coverage gate
|
|
26
|
+
# Branchproof::RakeTask.new(:branchproof) do |t|
|
|
27
|
+
# t.sources = ["app/**/*.rb"]
|
|
28
|
+
# t.framework = "rspec"
|
|
29
|
+
# t.minimum = ["mcdc=100"]
|
|
30
|
+
# end
|
|
31
|
+
class RakeTask < ::Rake::TaskLib
|
|
32
|
+
# Option names in the order they appear in the built argv.
|
|
33
|
+
OPTIONS = %i[tests project framework view level missing_only minimum format output].freeze
|
|
34
|
+
|
|
35
|
+
# Options that repeat one flag per array item.
|
|
36
|
+
REPEATED_FLAGS = { tests: "--test", minimum: "--minimum" }.freeze
|
|
37
|
+
|
|
38
|
+
# CLI defaults. The task only passes a flag when the Rakefile sets it.
|
|
39
|
+
DEFAULTS = { sources: [], tests: [], project: "auto", framework: "auto", view: "decisions", level: 3,
|
|
40
|
+
missing_only: false, minimum: [], format: "terminal", output: nil, runner_args: [] }.freeze
|
|
41
|
+
|
|
42
|
+
# @return [Symbol] the Rake task name
|
|
43
|
+
attr_reader :name
|
|
44
|
+
|
|
45
|
+
# @return [String] the task description shown by `rake -T`
|
|
46
|
+
attr_accessor :description
|
|
47
|
+
|
|
48
|
+
# Source globs passed as positional arguments.
|
|
49
|
+
# @return [Array<String>]
|
|
50
|
+
attr_reader :sources
|
|
51
|
+
|
|
52
|
+
# Test globs, one `--test` flag each.
|
|
53
|
+
# @return [Array<String>]
|
|
54
|
+
attr_reader :tests
|
|
55
|
+
|
|
56
|
+
# Project mode: `"auto"`, `"ruby"`, or `"rails"`.
|
|
57
|
+
# @return [String]
|
|
58
|
+
attr_reader :project
|
|
59
|
+
|
|
60
|
+
# Test framework: `"auto"`, `"minitest"`, or `"rspec"`.
|
|
61
|
+
# @return [String]
|
|
62
|
+
attr_reader :framework
|
|
63
|
+
|
|
64
|
+
# Terminal view: `"decisions"`, `"conditions"`, `"tests"`, or `"decision-tables"`.
|
|
65
|
+
# @return [String]
|
|
66
|
+
attr_reader :view
|
|
67
|
+
|
|
68
|
+
# Report level: 1, 2, or 3.
|
|
69
|
+
# @return [Integer]
|
|
70
|
+
attr_reader :level
|
|
71
|
+
|
|
72
|
+
# When true, terminal output lists only missing evidence.
|
|
73
|
+
# @return [Boolean]
|
|
74
|
+
attr_reader :missing_only
|
|
75
|
+
|
|
76
|
+
# Coverage gates as `"criterion=threshold"` strings, one `--minimum` flag each.
|
|
77
|
+
# @return [Array<String>]
|
|
78
|
+
attr_reader :minimum
|
|
79
|
+
|
|
80
|
+
# Output format: `"terminal"` or `"json"`.
|
|
81
|
+
# @return [String]
|
|
82
|
+
attr_reader :format
|
|
83
|
+
|
|
84
|
+
# Output path, or nil to write to stdout.
|
|
85
|
+
# @return [String, nil]
|
|
86
|
+
attr_reader :output
|
|
87
|
+
|
|
88
|
+
# Extra arguments appended after `--` and passed to the test runner.
|
|
89
|
+
# @return [Array<String>]
|
|
90
|
+
attr_reader :runner_args
|
|
91
|
+
|
|
92
|
+
# Defines the task. The block receives the task so a Rakefile can set options.
|
|
93
|
+
#
|
|
94
|
+
# @param name [Symbol, String] the Rake task name
|
|
95
|
+
# @yieldparam task [RakeTask] this task, before it is defined
|
|
96
|
+
def initialize(name = :branchproof)
|
|
97
|
+
super()
|
|
98
|
+
@name = name.to_sym
|
|
99
|
+
@description = "Run branchproof analyze"
|
|
100
|
+
@explicit = {}
|
|
101
|
+
DEFAULTS.each { |key, value| instance_variable_set(:"@#{key}", value.dup) }
|
|
102
|
+
yield self if block_given?
|
|
103
|
+
define
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
OPTIONS.each do |option|
|
|
107
|
+
# Each writer records that the Rakefile set the option, so #argv passes its flag.
|
|
108
|
+
define_method(:"#{option}=") do |value|
|
|
109
|
+
@explicit[option] = true
|
|
110
|
+
instance_variable_set(:"@#{option}", value)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# @param value [Array<String>] source globs
|
|
115
|
+
def sources=(value)
|
|
116
|
+
@sources = Array(value)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# @param value [Array<String>] runner arguments appended after `--`
|
|
120
|
+
def runner_args=(value)
|
|
121
|
+
@runner_args = Array(value)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Builds the CLI arguments without running anything.
|
|
125
|
+
#
|
|
126
|
+
# @return [Array<String>] arguments for `branchproof analyze`
|
|
127
|
+
def argv
|
|
128
|
+
args = ["analyze", *sources]
|
|
129
|
+
OPTIONS.each do |option|
|
|
130
|
+
value = instance_variable_get(:"@#{option}")
|
|
131
|
+
next unless @explicit[option] || (REPEATED_FLAGS.key?(option) && !Array(value).empty?)
|
|
132
|
+
|
|
133
|
+
args.concat(flags_for(option))
|
|
134
|
+
end
|
|
135
|
+
args.push("--", *runner_args) unless runner_args.empty?
|
|
136
|
+
args.map(&:to_s)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Full command line, starting with the current Ruby and the gem executable.
|
|
140
|
+
#
|
|
141
|
+
# @return [Array<String>]
|
|
142
|
+
def command
|
|
143
|
+
[RbConfig.ruby, executable, *argv]
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Path to the `branchproof` executable. Works inside this repository and as an installed gem.
|
|
147
|
+
#
|
|
148
|
+
# @return [String]
|
|
149
|
+
def executable
|
|
150
|
+
local = File.expand_path("../../exe/branchproof", __dir__)
|
|
151
|
+
return local if File.file?(local)
|
|
152
|
+
|
|
153
|
+
Gem.bin_path("branchproof", "branchproof")
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Runs the analysis in a subprocess. A non-zero exit status ends the Rake
|
|
157
|
+
# process with the same status so CI fails on coverage gate failures.
|
|
158
|
+
#
|
|
159
|
+
# @return [void]
|
|
160
|
+
def run
|
|
161
|
+
ran = system(*command)
|
|
162
|
+
status = $CHILD_STATUS
|
|
163
|
+
raise Error, "branchproof could not start: #{command.first(2).join(" ")}" if ran.nil? || status.nil?
|
|
164
|
+
return if status.success?
|
|
165
|
+
|
|
166
|
+
warn "branchproof exited with status #{status.exitstatus}"
|
|
167
|
+
exit status.exitstatus
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
private
|
|
171
|
+
|
|
172
|
+
def define
|
|
173
|
+
desc description
|
|
174
|
+
task(name) { run }
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def flags_for(option)
|
|
178
|
+
value = instance_variable_get(:"@#{option}")
|
|
179
|
+
return Array(value).flat_map { |item| [REPEATED_FLAGS.fetch(option), item] } if REPEATED_FLAGS.key?(option)
|
|
180
|
+
return (value ? ["--missing-only"] : []) if option == :missing_only
|
|
181
|
+
return [] if value.nil?
|
|
182
|
+
|
|
183
|
+
["--#{option}", value]
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|