# 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"