# frozen_string_literal: true
require "pathname"
require "json"
# Cartage, a package builder.
class Cartage
# Generate and mount the full metadata reporter, Cartage::Rack.
def self.Rack(root_path = nil, &filter)
Cartage::Rack.send(:new, root_path, &filter)
end
# Cartage::Rack is a simple application that reads an application's static
# release metadata and returns it as an (optionally filtered)
# +application/json+ value, or as a +text/plain+ string if called with
# +.text+ or +.txt+.
class Rack
VERSION = "2.3" # :nodoc:
class << self
# When +true+, Cartage::Rack and Cartage::Rack::Simple will raise an
# exception if there is no metadata file (release-metadata.json or
# +release_hashref+). May be explicitly turned off.
#
# Defaults to +true+ except in development or test environments (based on
# $RAILS_ENV, $APP_ENV and $RACK_ENV).
def require_metadata(value = (arg = false; nil)) # rubocop:disable Style/Semicolon
@require_metadata = value unless arg == false
@require_metadata || default_require_metadata
end
private
def default_require_metadata
environment = ENV["RAILS_ENV"] || ENV["APP_ENV"] || ENV["RACK_ENV"] || "development"
environment !~ /\A(?:development|test)\z/i
end
end
def initialize(root_path = nil, &filter) # :nodoc:
@metadata = Cartage::Rack::Metadata.new(root_path, filter: filter)
end
def call(env) # :nodoc:
type, body = resolve_content(env)
["200", {"Content-Type" => type}, [body]]
end
def inspect # :nodoc:
"#{self.class} for #{@metadata.inspect}"
end
private
def resolve_content(env)
content = @metadata.resolve
case env["PATH_INFO"]
when /\.te?xt\z/
type = "text/plain"
body = [
"name: #{dig(content, "package", "name")}",
"environment: #{dig(content, "env", "name")}",
"hashref: #{dig(content, "package", "hashref")}"
]
value = dig(content, "package", "timestamp")
body << "timestamp: #{value}" if value
repo = dig(content, "package", "repo")
body << "#{repo["type"]}: #{repo["url"]}" if repo
body = body.join("\n")
else
type = "application/json"
body = content.to_json
end
[type, body]
end
attr_reader :metadata
# :nocov:
def dig(hash, key, *rest)
if hash.respond_to?(:dig)
hash.dig(key, *rest)
else
DIGGER.call(hash, key, *rest)
end
end
DIGGER = ->(h, k, *r) { # :nodoc:
v = h[k]
if v.nil? || r.empty?
v
else
DIGGER.call(v, *r)
end
}
private_constant :DIGGER
# :nocov:
end
end
require_relative "rack/simple"
require_relative "rack/metadata"