Module: Ibex::Impact::Severity
- Defined in:
- lib/ibex/impact/severity.rb
Overview
Severity ranking and CI gate evaluation for impact findings.
Constant Summary collapse
- LEVELS =
: Array
%w[info low medium high critical].freeze
- FAIL_ON =
%w[ new_conflict nullable_change first_change follow_change action_arity unreachable ].freeze
- RANK =
: Array
LEVELS.each_with_index.to_h.freeze
- GATE_TO_KIND =
: Hash[String, Integer]
{ "nullable_change" => "nullable", "first_change" => "first", "follow_change" => "follow" }.freeze
Class Method Summary collapse
- .action_gate?(report, gates) ⇒ Boolean
- .conflict_gate?(report, gates) ⇒ Boolean
- .fails?(report, gates) ⇒ Boolean
- .level_for_kind(kind) ⇒ Object
- .max(left, right) ⇒ Object
- .symbols(changes, actions) ⇒ Object
- .unreachable_gate?(report, gates) ⇒ Boolean
- .validate_gates(gates) ⇒ Object
Class Method Details
.action_gate?(report, gates) ⇒ Boolean
123 124 125 126 127 128 |
# File 'lib/ibex/impact/severity.rb', line 123 def action_gate?(report, gates) return false unless gates.include?("action_arity") action_records = report.fetch(:actions, []) #: Array[Hash[Symbol, Object?]] action_records.any? { |item| item[:severity] == "high" } end |
.conflict_gate?(report, gates) ⇒ Boolean
109 110 111 |
# File 'lib/ibex/impact/severity.rb', line 109 def conflict_gate?(report, gates) gates.include?("new_conflict") && report.dig(:automaton, :conflicts, :added)&.any? end |
.fails?(report, gates) ⇒ Boolean
94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/ibex/impact/severity.rb', line 94 def fails?(report, gates) return false if gates.empty? return true if conflict_gate?(report, gates) return true if unreachable_gate?(report, gates) return true if action_gate?(report, gates) symbol_records = report.fetch(:symbols, []) #: Array[Hash[Symbol, Object?]] gates.any? do |gate| kind = GATE_TO_KIND[gate] kind && symbol_records.any? { |item| item[:kinds].is_a?(Array) && item[:kinds].include?(kind) } end end |
.level_for_kind(kind) ⇒ Object
86 87 88 89 90 91 |
# File 'lib/ibex/impact/severity.rb', line 86 def level_for_kind(kind) return "high" if %w[first follow nullable].include?(kind) return "medium" if %w[reference precedence].include?(kind) "low" end |
.max(left, right) ⇒ Object
65 66 67 |
# File 'lib/ibex/impact/severity.rb', line 65 def max(left, right) RANK.fetch(left) >= RANK.fetch(right) ? left : right end |
.symbols(changes, actions) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/ibex/impact/severity.rb', line 70 def symbols(changes, actions) levels = Hash.new("info") #: Hash[String, String] changes.each do |name, kinds| kinds.each do |kind| level = level_for_kind(kind) levels[name] = max(levels[name], level) end end actions.each do |finding| name = finding.fetch(:production).split(" -> ").first levels[name] = max(levels[name], finding.fetch(:severity)) end levels end |
.unreachable_gate?(report, gates) ⇒ Boolean
114 115 116 117 118 119 120 |
# File 'lib/ibex/impact/severity.rb', line 114 def unreachable_gate?(report, gates) return false unless gates.include?("unreachable") states = report.dig(:automaton, :unreachable) || [] nonterminals = report.dig(:automaton, :unreachable_nonterminals) || [] states.any? || nonterminals.any? end |
.validate_gates(gates) ⇒ Object
131 132 133 134 135 136 |
# File 'lib/ibex/impact/severity.rb', line 131 def validate_gates(gates) unknown = gates - FAIL_ON raise OptionParser::InvalidArgument, "unknown --fail-on value #{unknown.first.inspect}" unless unknown.empty? gates.uniq end |