lib/envirobly/config.rb
require "yaml" require "json" require "digest" class Envirobly::Config DIR = ".envirobly" PATH = "#{DIR}/project.yml" attr_reader :errors, :result, :raw def initialize(commit) @commit = commit @errors = [] @result = nil @project_url = nil @raw = @commit.file_content PATH end def dig(*args) @project.dig(*args) rescue NoMethodError nil end def compile(environment = nil) @environment = environment return unless @project = parse set_project_url merge_environment_overrides! unless @environment.nil? transform_env_var_values! append_image_tags! @result = @project.slice(:services) end def to_deployment_params { environ: { logical_id: @environment, project_url: @project_url }, commit: { ref: @commit.ref, time: @commit.time, message: @commit.message }, config: @result, raw_config: @raw } end private def parse YAML.safe_load @raw, aliases: true, symbolize_names: true rescue Psych::Exception => exception @errors << exception.message nil end def set_project_url @project_url = dig :remote, :origin if @project_url.blank? @errors << "Missing a `remote.origin` link to project." end end def transform_env_var_values! @project.fetch(:services, {}).each do |logical_id, service| service.fetch(:env, {}).each do |key, value| if value.is_a?(Hash) && value.has_key?(:file) @project[:services][logical_id][:env][key] = @commit.file_content(value.fetch(:file)).strip end end end end NON_BUILDABLE_TYPES = %w[ postgres mysql valkey ] BUILD_DEFAULTS = { dockerfile: "Dockerfile", build_context: "." } def append_image_tags! @project.fetch(:services, {}).each do |logical_id, service| next if NON_BUILDABLE_TYPES.include?(service[:type]) || service[:image].present? checksums = [] BUILD_DEFAULTS.each do |attribute, default| value = service.fetch(attribute, default) checksum = @commit.objects_with_checksum_at value if checksum.empty? @errors << "Service `#{logical_id}` specifies `#{attribute}` as `#{value}` which doesn't exist in this commit." else checksums << checksum end end if checksums.size == 2 @project[:services][logical_id][:image_tag] = Digest::SHA1.hexdigest checksums.to_json end end end def merge_environment_overrides! return unless services = @project.dig(:environments, @environment.to_sym) services.each do |logical_id, service| service.each do |attribute, value| if value.is_a?(Hash) && @project[:services][logical_id][attribute].is_a?(Hash) @project[:services][logical_id][attribute].merge! value @project[:services][logical_id][attribute].compact! else @project[:services][logical_id][attribute] = value end end end end end