Class: Space::Architect::GateLint

Inherits:
Object
  • Object
show all
Defined in:
lib/space_architect/gate_lint.rb

Overview

Validates the structured gates block parsed from an iteration's

Acceptance Criteria section. Returns a Dry::Monads::Result:

Success(gates) — well-formed (or empty list)
Failure([messages]) — aggregated lint errors

Defined Under Namespace

Classes: GateContract

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.call(gates) ⇒ Object



79
# File 'lib/space_architect/gate_lint.rb', line 79

def self.call(gates) = new.call(gates)

Instance Method Details

#call(gates) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/space_architect/gate_lint.rb', line 81

def call(gates)
  return Success([]) if gates.nil? || (gates.is_a?(Array) && gates.empty?)
  return Failure(["gates block must be a YAML list, got #{gates.class}"]) unless gates.is_a?(Array)

  errors   = []
  seen_ids = {}
  contract = GateContract.new

  gates.each.with_index(1) do |gate, i|
    pfx = "gate[#{i}]"
    unless gate.is_a?(Hash)
      errors << "#{pfx}: must be a hash, got #{gate.class}"
      next
    end

    result = contract.call(gate)
    flatten_errors(result.errors.to_h, pfx, errors) unless result.success?

    id = gate["id"] || gate[:id]
    id = (id.is_a?(String) && !id.strip.empty?) ? id : nil
    next unless id

    if seen_ids.key?(id)
      errors << "#{pfx}: duplicate id '#{id}' (also at gate[#{seen_ids[id]}])"
    else
      seen_ids[id] = i
    end
  end

  errors.empty? ? Success(gates) : Failure(errors)
end