# frozen_string_literal: true require "json" require "terminal-table" require_relative "base" module Neetob class CLI module Heroku module ConfigVars class Audit < Base attr_accessor :apps, :expected_config_vars_json_file_path, :sandbox def initialize(apps, expected_config_vars_json_file_path = "", sandbox = false) super() @apps = apps @expected_config_vars_json_file_path = expected_config_vars_json_file_path @sandbox = sandbox end def run matching_apps = find_all_matching_apps_or_repos(apps, :heroku, sandbox) table_rows = [] expected_config = read_json_file(expected_config_vars_json_file_path || default_config_vars_json_file_path) return unless expected_config matching_apps.each do |app| actual_config = `heroku config -a #{app} --json` unless $?.success? ui.error("There is a problem in accessing the app with name \"#{app}\" in your account.") ui.error("Please check the specified app name and ensure you're authorized to view that app.") next end actual_config_json = JSON.parse(actual_config) table_rows.concat(compare_config_and_build_rows(app, expected_config, actual_config_json)) end table = Terminal::Table.new headings: ["App", "Config var", "Expected", "Result"], rows: table_rows ui.success(table) end private def compare_config_and_build_rows(app, expected_config, actual_config) expected_config.map do |key, val| row = [app, key.to_s] row << (value_set_dynamically_by_heroku?(val) ? "Heroku has dynamically set the value" : val.to_s) row << (actual_config[key] == val ? "✅" : (actual_config[key] || "No such key")) end end def value_set_dynamically_by_heroku?(value) value == { "isDynamic" => true } end def default_config_vars_json_file_path File.expand_path("../../../../../data/config-vars-audit.json", __dir__) end end end end end end