Module: Kamal::Lint::Loader
- Defined in:
- lib/kamal/lint/loader.rb
Class Method Summary collapse
-
.build_line_index(text) ⇒ Object
Build a mapping from dot-path ("env.secret") to source line numbers by walking the Psych AST.
- .deep_merge(base, override) ⇒ Object
- .derive_working_dir(config_file) ⇒ Object
- .load(config_file:, destination: nil, kamal_version: nil, include_kamal_errors: false) ⇒ Object
- .read_override(config_file, destination) ⇒ Object
- .read_yaml(path) ⇒ Object
- .safe_parse_yaml(text) ⇒ Object
-
.try_kamal_load(config_file, destination, working_dir) ⇒ Object
Invoke Kamal's own loader so we can capture (and selectively surface) the errors it would raise at deploy time.
- .walk_node(node, path, index) ⇒ Object
Class Method Details
.build_line_index(text) ⇒ Object
Build a mapping from dot-path ("env.secret") to source line numbers by walking the Psych AST.
138 139 140 141 142 143 144 145 146 |
# File 'lib/kamal/lint/loader.rb', line 138 def build_line_index(text) index = {} Psych.parse_stream(text).children.each do |doc| walk_node(doc.root, [], index) end index rescue Psych::SyntaxError index || {} end |
.deep_merge(base, override) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/kamal/lint/loader.rb', line 122 def deep_merge(base, override) return override unless base.is_a?(Hash) && override.is_a?(Hash) result = base.dup override.each do |k, v| result[k] = if result[k].is_a?(Hash) && v.is_a?(Hash) deep_merge(result[k], v) else v end end result end |
.derive_working_dir(config_file) ⇒ Object
79 80 81 |
# File 'lib/kamal/lint/loader.rb', line 79 def derive_working_dir(config_file) Pathname.new(config_file).realpath.dirname.dirname.to_s end |
.load(config_file:, destination: nil, kamal_version: nil, include_kamal_errors: false) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/kamal/lint/loader.rb', line 47 def load(config_file:, destination: nil, kamal_version: nil, include_kamal_errors: false) raise ConfigNotFoundError, "Config file not found: #{config_file}" unless File.exist?(config_file) working_dir = derive_working_dir(config_file) base_text, base_parsed = read_yaml(config_file) override_parsed = read_override(config_file, destination) kamal_loaded, kamal_load_error = try_kamal_load(config_file, destination, working_dir) base_secrets_path = File.join(working_dir, ".kamal", "secrets") destination_secrets_path = destination && File.join(working_dir, ".kamal", "secrets.#{destination}") secrets = SecretsFile.read_keys(base_secrets_path) secrets |= SecretsFile.read_keys(destination_secrets_path) if destination_secrets_path Context.new( config_file: config_file, destination: destination, working_dir: working_dir, parsed: override_parsed ? deep_merge(base_parsed, override_parsed) : base_parsed, base_parsed: base_parsed, override_parsed: override_parsed, line_index: build_line_index(base_text), secrets: secrets, secrets_path: base_secrets_path, destination_secrets_path: destination_secrets_path, gitignore_path: File.join(working_dir, ".gitignore"), kamal_version: kamal_version || KamalVersion.detect, kamal_loaded: kamal_loaded, kamal_load_error: kamal_load_error, include_kamal_errors: include_kamal_errors ) end |
.read_override(config_file, destination) ⇒ Object
88 89 90 91 92 93 94 95 |
# File 'lib/kamal/lint/loader.rb', line 88 def read_override(config_file, destination) return nil unless destination override_path = File.join(File.dirname(config_file), "deploy.#{destination}.yml") return nil unless File.exist?(override_path) safe_parse_yaml(File.read(override_path)) end |
.read_yaml(path) ⇒ Object
83 84 85 86 |
# File 'lib/kamal/lint/loader.rb', line 83 def read_yaml(path) text = File.read(path) [ text, safe_parse_yaml(text) ] end |
.safe_parse_yaml(text) ⇒ Object
115 116 117 118 119 120 |
# File 'lib/kamal/lint/loader.rb', line 115 def safe_parse_yaml(text) result = YAML.safe_load(text, aliases: true, permitted_classes: [ Symbol ]) result.is_a?(Hash) ? result : {} rescue Psych::SyntaxError {} end |
.try_kamal_load(config_file, destination, working_dir) ⇒ Object
Invoke Kamal's own loader so we can capture (and selectively surface) the errors it would raise at deploy time. The returned config object is discarded — checks operate on the parsed Hash so they retain source line numbers.
101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/kamal/lint/loader.rb', line 101 def try_kamal_load(config_file, destination, working_dir) require "kamal" Dir.chdir(working_dir) do Kamal::Configuration.create_from( config_file: Pathname.new(config_file), destination: destination, version: "kamal-lint" ) end [ true, nil ] rescue => e [ false, e ] end |
.walk_node(node, path, index) ⇒ Object
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/kamal/lint/loader.rb', line 148 def walk_node(node, path, index) case node when Psych::Nodes::Mapping node.children.each_slice(2) do |key_node, value_node| next unless key_node && value_node new_path = path + [ key_node.value ] index[new_path.join(".")] ||= key_node.start_line + 1 walk_node(value_node, new_path, index) end when Psych::Nodes::Sequence node.children.each_with_index do |child, idx| new_path = path + [ idx.to_s ] index[new_path.join(".")] ||= child.start_line + 1 walk_node(child, new_path, index) end end end |