require "semantic/semantic" module ShopifyCLI # The environment module provides an interface to get information from # the environment in which the CLI runs module Environment TRUTHY_ENV_VARIABLE_VALUES = ["1", "true", "TRUE", "yes", "YES"] SPIN_OVERRIDE_ENV_NAMES = [ Constants::EnvironmentVariables::SPIN_WORKSPACE, Constants::EnvironmentVariables::SPIN_NAMESPACE, Constants::EnvironmentVariables::SPIN_HOST, ] def self.ruby_version(context: Context.new) output, status = context.capture2e("ruby", "--version") raise ShopifyCLI::Abort, context.message("core.errors.missing_ruby") unless status.success? version = output.match(/ruby (\d+\.\d+\.\d+)/)[1] ::Semantic::Version.new(version) end def self.node_version(context: Context.new) output, status = context.capture2e("node", "--version") raise ShopifyCLI::Abort, context.message("core.errors.missing_node") unless status.success? version = output.match(/v(\d+\.\d+\.\d+)/)[1] ::Semantic::Version.new(version) end def self.npm_version(context: Context.new) output, status = context.capture2e("npm", "--version") raise ShopifyCLI::Abort, context.message("core.errors.missing_npm") unless status.success? version = output.match(/(\d+\.\d+\.\d+)/)[1] ::Semantic::Version.new(version) end def self.rails_version(context: Context.new) output, status = context.capture2e("rails", "--version") context.abort(context.message("core.app.create.rails.error.install_failure", "rails")) unless status.success? version = output.match(/Rails (\d+\.\d+\.\d+)/)[1] ::Semantic::Version.new(version) end def self.interactive=(interactive) @interactive = interactive end def self.interactive?(env_variables: ENV) if env_variables.key?(Constants::EnvironmentVariables::TTY) env_variable_truthy?( Constants::EnvironmentVariables::TTY, env_variables: env_variables ) else @interactive ||= STDIN.tty? end end def self.development?(env_variables: ENV) env_variable_truthy?( Constants::EnvironmentVariables::DEVELOPMENT, env_variables: env_variables ) end def self.use_local_partners_instance?(env_variables: ENV) env_variable_truthy?( Constants::EnvironmentVariables::LOCAL_PARTNERS, env_variables: env_variables ) end def self.print_stacktrace?(env_variables: ENV) env_variable_truthy?( Constants::EnvironmentVariables::STACKTRACE, env_variables: env_variables ) || development?(env_variables: env_variables) end def self.test?(env_variables: ENV) env_variable_truthy?( Constants::EnvironmentVariables::TEST, env_variables: env_variables ) end def self.acceptance_test?(env_variables: ENV) env_variable_truthy?( Constants::EnvironmentVariables::ACCEPTANCE_TEST, env_variables: env_variables ) end def self.print_backtrace?(env_variables: ENV) env_variable_truthy?( Constants::EnvironmentVariables::BACKTRACE, env_variables: env_variables ) end def self.partners_domain(env_variables: ENV) if use_local_partners_instance?(env_variables: env_variables) "partners.myshopify.io" elsif use_spin?(env_variables: env_variables) "partners.#{spin_url(env_variables: env_variables)}" else "partners.shopify.com" end end def self.spin_url_override(env_variables: ENV) tokens = SPIN_OVERRIDE_ENV_NAMES.map do |name| env_variables[name] end return if tokens.all?(&:nil?) if tokens.any?(&:nil?) raise "To manually target a spin instance, you must set #{SPIN_OVERRIDE_ENV_NAMES}" else tokens.join(".") end end def self.use_spin?(env_variables: ENV) env_variable_truthy?( Constants::EnvironmentVariables::SPIN, env_variables: env_variables ) || env_variable_truthy?( Constants::EnvironmentVariables::SPIN_PARTNERS, env_variables: env_variables ) end def self.spin_url(env_variables: ENV) override = spin_url_override(env_variables: env_variables) return override unless override.nil? spin_response = if env_variables.key?( Constants::EnvironmentVariables::SPIN_INSTANCE ) spin_show else spin_show(latest: true) end begin instance = JSON.parse(spin_response) raise "Missing key 'fqdn' from spin show. Actual response: #{instance}" unless instance.include?("fqdn") instance["fqdn"] rescue => e raise "Failed to infer spin environment from spin show response #{spin_response}: #{e}" end end def self.spin_show(latest: false) latest ? %x(spin show --latest --json) : %x(spin show --json) end def self.send_monorail_events?(env_variables: ENV) env_variable_truthy?( Constants::EnvironmentVariables::MONORAIL_REAL_EVENTS, env_variables: env_variables ) end def self.auth_token(env_variables: ENV) env_variables[Constants::EnvironmentVariables::AUTH_TOKEN] end def self.admin_auth_token(env_variables: ENV) env_variables[Constants::EnvironmentVariables::ADMIN_AUTH_TOKEN] end def self.store(env_variables: ENV) env_variables[Constants::EnvironmentVariables::STORE] end def self.env_variable_truthy?(variable_name, env_variables: ENV) TRUTHY_ENV_VARIABLE_VALUES.include?(env_variables[variable_name.to_s]) end end end