Class: Necropsy::Configuration
- Inherits:
-
Object
- Object
- Necropsy::Configuration
- Defined in:
- lib/necropsy/configuration.rb
Constant Summary collapse
- DEFAULT_FAIL_ON =
:high- DEFAULT_BASELINE =
'.necropsy_baseline.yml'- RTA_PRUNING_MODES =
%w[rank_only legacy].freeze
- STATIC_ANALYZER_ORDER =
%w[name_resolution cha rta].freeze
- QUARANTINE_EXPIRY_POLICIES =
%w[warn fail ignore].freeze
- WORLD_MODES =
%w[application library].freeze
- LOAD_ROOT_POLICIES =
%w[known all].freeze
- FRAMEWORK_GEMS =
{ 'rails' => 'rails', 'rubocop' => 'rubocop', 'sidekiq' => 'sidekiq', 'graphql' => 'graphql', 'view_component' => 'view_component', 'active_model_serializers' => 'active_model_serializers', 'blueprinter' => 'blueprinter' }.freeze
- TOP_LEVEL_KEYS =
%w[ analysis analyzers frameworks entry_points ci quarantine bench cache rta resolution paths report logging implicit_callers ].freeze
- NESTED_KEYS =
{ 'analysis' => %w[world load_roots], 'analyzers' => %w[static dynamic custom], 'analyzers.dynamic' => %w[coverage coverband trace_point], 'entry_points' => %w[extra], 'ci' => %w[baseline fail_on], 'quarantine' => %w[days expiry], 'bench' => %w[precision_threshold recall_threshold], 'cache' => %w[enabled path], 'rta' => %w[factory_methods pruning], 'resolution' => %w[ambiguity_limit], 'paths' => %w[analyze reference test include exclude], 'report' => %w[include exclude], 'logging' => %w[verbose] }.freeze
- DYNAMIC_KEYS =
%w[source min_observation_days expected_source_revision keys key pattern connect_timeout read_timeout].freeze
- IMPLICIT_CALLER_KEYS =
%w[name_pattern owner_ancestors reason].freeze
- CUSTOM_ANALYZER_KEYS =
%w[class require trusted].freeze
- REMOTE_DYNAMIC_KEYS =
%w[ total_timeout max_response_bytes max_bulk_bytes max_array_elements max_resp_depth max_keys max_payload_depth ].freeze
- DYNAMIC_TIMEOUT_KEYS =
%w[connect_timeout read_timeout total_timeout].freeze
- DYNAMIC_LIMIT_KEYS =
(REMOTE_DYNAMIC_KEYS - %w[total_timeout]).freeze
Instance Attribute Summary collapse
-
#data ⇒ Object
readonly
Returns the value of attribute data.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
Class Method Summary collapse
Instance Method Summary collapse
- #ambiguity_limit ⇒ Object
- #analyze_paths ⇒ Object
- #baseline_path ⇒ Object
- #bench_precision_threshold ⇒ Object
- #bench_recall_threshold ⇒ Object
- #cache_enabled? ⇒ Boolean
- #cache_path ⇒ Object
- #custom_analyzers ⇒ Object
- #dynamic_config(name) ⇒ Object
- #entry_point_patterns ⇒ Object
- #exclude_paths ⇒ Object
- #factory_methods ⇒ Object
- #fail_on ⇒ Object
- #frameworks(reference_files: nil) ⇒ Object
- #implicit_callers ⇒ Object
- #include_paths ⇒ Object
-
#initialize(root:, path:, data:) ⇒ Configuration
constructor
A new instance of Configuration.
- #legacy_include_paths? ⇒ Boolean
- #library_world? ⇒ Boolean
- #load_roots ⇒ Object
- #min_observation_days ⇒ Object
- #quarantine_days ⇒ Object
- #quarantine_expiry ⇒ Object
- #rails_enabled?(reference_files: nil) ⇒ Boolean
- #reference_paths ⇒ Object
- #report_exclude_paths ⇒ Object
- #report_include_paths ⇒ Object
- #rta_pruning ⇒ Object
- #scan_cache_key ⇒ Object
- #static_analyzers ⇒ Object
- #test_paths ⇒ Object
- #verbose? ⇒ Boolean
- #world ⇒ Object
Constructor Details
#initialize(root:, path:, data:) ⇒ Configuration
Returns a new instance of Configuration.
58 59 60 61 62 63 |
# File 'lib/necropsy/configuration.rb', line 58 def initialize(root:, path:, data:) @root = File.(root) @path = path @data = stringify_keys(data) validate! end |
Instance Attribute Details
#data ⇒ Object (readonly)
Returns the value of attribute data.
48 49 50 |
# File 'lib/necropsy/configuration.rb', line 48 def data @data end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
48 49 50 |
# File 'lib/necropsy/configuration.rb', line 48 def path @path end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
48 49 50 |
# File 'lib/necropsy/configuration.rb', line 48 def root @root end |
Class Method Details
.load(root:, path: nil) ⇒ Object
50 51 52 53 54 55 56 |
# File 'lib/necropsy/configuration.rb', line 50 def self.load(root:, path: nil) config_path = path ? File.(path, root) : File.join(root, '.necropsy.yml') data = File.exist?(config_path) ? YAML.safe_load_file(config_path, permitted_classes: [Symbol], aliases: true) : {} new(root: root, path: config_path, data: data || {}) rescue Psych::Exception => e raise Error, "Could not parse configuration #{config_path}: #{e.}" end |
Instance Method Details
#ambiguity_limit ⇒ Object
183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/necropsy/configuration.rb', line 183 def ambiguity_limit value = fetch('resolution', 'ambiguity_limit') return 4 if value.nil? return Float::INFINITY if value.to_s == 'unlimited' limit = Integer(value) return limit if limit.positive? raise Error, 'resolution.ambiguity_limit must be a positive integer or unlimited' rescue ArgumentError, TypeError raise Error, 'resolution.ambiguity_limit must be a positive integer or unlimited' end |
#analyze_paths ⇒ Object
196 197 198 199 200 |
# File 'lib/necropsy/configuration.rb', line 196 def analyze_paths configured = fetch('paths', 'analyze') configured = fetch('paths', 'include') if configured.nil? Array(configured).map(&:to_s) end |
#baseline_path ⇒ Object
114 115 116 |
# File 'lib/necropsy/configuration.rb', line 114 def baseline_path fetch('ci', 'baseline') || DEFAULT_BASELINE end |
#bench_precision_threshold ⇒ Object
149 150 151 |
# File 'lib/necropsy/configuration.rb', line 149 def bench_precision_threshold Float(fetch('bench', 'precision_threshold') || 0.85) end |
#bench_recall_threshold ⇒ Object
153 154 155 156 |
# File 'lib/necropsy/configuration.rb', line 153 def bench_recall_threshold value = fetch('bench', 'recall_threshold') value && Float(value) end |
#cache_enabled? ⇒ Boolean
158 159 160 161 |
# File 'lib/necropsy/configuration.rb', line 158 def cache_enabled? value = fetch('cache', 'enabled') value.nil? || value != false end |
#cache_path ⇒ Object
163 164 165 |
# File 'lib/necropsy/configuration.rb', line 163 def cache_path fetch('cache', 'path') || '.necropsy_cache/scan.json' end |
#custom_analyzers ⇒ Object
93 94 95 |
# File 'lib/necropsy/configuration.rb', line 93 def custom_analyzers Array(fetch('analyzers', 'custom')).compact end |
#dynamic_config(name) ⇒ Object
89 90 91 |
# File 'lib/necropsy/configuration.rb', line 89 def dynamic_config(name) fetch('analyzers', 'dynamic', name.to_s) || {} end |
#entry_point_patterns ⇒ Object
97 98 99 |
# File 'lib/necropsy/configuration.rb', line 97 def entry_point_patterns Array(fetch('entry_points', 'extra')).compact.map(&:to_s) end |
#exclude_paths ⇒ Object
220 221 222 |
# File 'lib/necropsy/configuration.rb', line 220 def exclude_paths Array(fetch('paths', 'exclude')).map(&:to_s) end |
#factory_methods ⇒ Object
171 172 173 |
# File 'lib/necropsy/configuration.rb', line 171 def factory_methods Array(fetch('rta', 'factory_methods') || %w[build create build_stubbed]).map(&:to_s) end |
#fail_on ⇒ Object
118 119 120 121 122 123 |
# File 'lib/necropsy/configuration.rb', line 118 def fail_on level = (fetch('ci', 'fail_on') || DEFAULT_FAIL_ON).to_sym return level if CONFIDENCE_LEVELS.key?(level) raise Error, "Invalid ci.fail_on confidence level: #{level}" end |
#frameworks(reference_files: nil) ⇒ Object
101 102 103 104 105 106 107 |
# File 'lib/necropsy/configuration.rb', line 101 def frameworks(reference_files: nil) return @frameworks if defined?(@frameworks) reference_files ||= Project.new(root: root, config: self).reference_files configured = Array(data['frameworks']).map(&:to_s) @frameworks = (configured + detected_frameworks(reference_files)).uniq.sort.freeze end |
#implicit_callers ⇒ Object
232 233 234 235 236 237 238 239 240 |
# File 'lib/necropsy/configuration.rb', line 232 def implicit_callers @implicit_callers ||= Array(data['implicit_callers']).map do |entry| { name_pattern: Regexp.new(entry.fetch('name_pattern')), owner_ancestors: Array(entry['owner_ancestors']).map(&:to_s), reason: entry['reason']&.to_s } end end |
#include_paths ⇒ Object
212 213 214 |
# File 'lib/necropsy/configuration.rb', line 212 def include_paths analyze_paths end |
#legacy_include_paths? ⇒ Boolean
216 217 218 |
# File 'lib/necropsy/configuration.rb', line 216 def legacy_include_paths? !fetch('paths', 'include').nil? && fetch('paths', 'analyze').nil? end |
#library_world? ⇒ Boolean
77 78 79 |
# File 'lib/necropsy/configuration.rb', line 77 def library_world? world == :library end |
#load_roots ⇒ Object
81 82 83 84 85 86 87 |
# File 'lib/necropsy/configuration.rb', line 81 def load_roots configured = fetch('analysis', 'load_roots') policy = configured.nil? ? 'known' : configured.to_s return policy.to_sym if LOAD_ROOT_POLICIES.include?(policy) raise Error, "analysis.load_roots must be one of: #{LOAD_ROOT_POLICIES.join(', ')}" end |
#min_observation_days ⇒ Object
125 126 127 128 129 |
# File 'lib/necropsy/configuration.rb', line 125 def min_observation_days coverage_days = fetch('analyzers', 'dynamic', 'coverage', 'min_observation_days') coverband_days = fetch('analyzers', 'dynamic', 'coverband', 'min_observation_days') Integer(coverage_days || coverband_days || 30) end |
#quarantine_days ⇒ Object
137 138 139 |
# File 'lib/necropsy/configuration.rb', line 137 def quarantine_days Integer(fetch('quarantine', 'days') || 30) end |
#quarantine_expiry ⇒ Object
141 142 143 144 145 146 147 |
# File 'lib/necropsy/configuration.rb', line 141 def quarantine_expiry configured = fetch('quarantine', 'expiry') policy = configured.nil? ? 'warn' : configured.to_s return policy.to_sym if QUARANTINE_EXPIRY_POLICIES.include?(policy) raise Error, "quarantine.expiry must be one of: #{QUARANTINE_EXPIRY_POLICIES.join(', ')}" end |
#rails_enabled?(reference_files: nil) ⇒ Boolean
109 110 111 112 |
# File 'lib/necropsy/configuration.rb', line 109 def rails_enabled?(reference_files: nil) reference_files ||= Project.new(root: root, config: self).reference_files frameworks(reference_files: reference_files).include?('rails') end |
#reference_paths ⇒ Object
202 203 204 205 |
# File 'lib/necropsy/configuration.rb', line 202 def reference_paths configured = fetch('paths', 'reference') Array(configured.nil? ? ['**/*'] : configured).map(&:to_s) end |
#report_exclude_paths ⇒ Object
228 229 230 |
# File 'lib/necropsy/configuration.rb', line 228 def report_exclude_paths Array(fetch('report', 'exclude')).map(&:to_s) end |
#report_include_paths ⇒ Object
224 225 226 |
# File 'lib/necropsy/configuration.rb', line 224 def report_include_paths Array(fetch('report', 'include')).map(&:to_s) end |
#rta_pruning ⇒ Object
175 176 177 178 179 180 181 |
# File 'lib/necropsy/configuration.rb', line 175 def rta_pruning configured = fetch('rta', 'pruning') mode = configured.nil? ? 'rank_only' : configured.to_s return mode.to_sym if RTA_PRUNING_MODES.include?(mode) raise Error, "rta.pruning must be one of: #{RTA_PRUNING_MODES.join(', ')}" end |
#scan_cache_key ⇒ Object
167 168 169 |
# File 'lib/necropsy/configuration.rb', line 167 def scan_cache_key data.except('cache', 'report') end |
#static_analyzers ⇒ Object
65 66 67 |
# File 'lib/necropsy/configuration.rb', line 65 def static_analyzers Array(fetch('analyzers', 'static') || %w[name_resolution cha rta]).map(&:to_s) end |
#test_paths ⇒ Object
207 208 209 210 |
# File 'lib/necropsy/configuration.rb', line 207 def test_paths configured = fetch('paths', 'test') Array(configured.nil? ? %w[spec/** test/**] : configured).map(&:to_s) end |
#verbose? ⇒ Boolean
242 243 244 |
# File 'lib/necropsy/configuration.rb', line 242 def verbose? fetch('logging', 'verbose') == true end |
#world ⇒ Object
69 70 71 72 73 74 75 |
# File 'lib/necropsy/configuration.rb', line 69 def world configured = fetch('analysis', 'world') mode = configured.nil? ? 'application' : configured.to_s return mode.to_sym if WORLD_MODES.include?(mode) raise Error, "analysis.world must be one of: #{WORLD_MODES.join(', ')}" end |