Class: Textus::Doctor::Check::Sentinels

Inherits:
Textus::Doctor::Check show all
Defined in:
lib/textus/doctor/check/sentinels.rb

Instance Method Summary collapse

Methods inherited from Textus::Doctor::Check

#initialize, name_key

Constructor Details

This class inherits a constructor from Textus::Doctor::Check

Instance Method Details

#callObject



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/textus/doctor/check/sentinels.rb', line 8

def call
  out = []
  dir = File.join(store.root, "sentinels")
  return out unless File.directory?(dir)

  Dir.glob(File.join(dir, "**", "*.textus-managed.json")).each do |sp| # rubocop:disable Metrics/BlockLength
    begin
      data = JSON.parse(File.read(sp))
    rescue JSON::ParserError => e
      out << {
        "code" => "sentinel.parse_error",
        "level" => "warning",
        "subject" => sp,
        "message" => "sentinel is not valid JSON: #{e.message}",
        "fix" => "delete #{sp} and re-run 'textus build' to regenerate",
      }
      next
    end

    target = data["target"]
    recorded_sha = data["sha256"]

    if target.nil? || !File.exist?(target)
      out << {
        "code" => "sentinel.orphan",
        "level" => "warning",
        "subject" => sp,
        "message" => "sentinel target #{target.inspect} no longer exists",
        "fix" => "delete #{sp} (the published file is gone) or restore the target",
      }
      next
    end

    current_sha = Digest::SHA256.hexdigest(File.binread(target))
    next if recorded_sha.nil? || current_sha == recorded_sha

    out << {
      "code" => "sentinel.drift",
      "level" => "warning",
      "subject" => target,
      "message" => "published file at #{target} was modified out-of-band",
      "fix" => "re-run 'textus build' to overwrite, or copy the manual edit back into the store source",
    }
  end
  out
end