shopify-cli 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +11 -0
- data/Dockerfile +0 -2
- data/Gemfile.lock +22 -16
- data/Rakefile +7 -16
- data/bin/console +11 -0
- data/bin/shopify +15 -3
- data/dev.yml +3 -0
- data/ext/shopify-cli/extconf.rb +2 -0
- data/lib/project_types/extension/cli.rb +2 -0
- data/lib/project_types/extension/commands/build.rb +2 -1
- data/lib/project_types/extension/features/argo.rb +1 -1
- data/lib/project_types/extension/features/argo_serve.rb +1 -0
- data/lib/project_types/extension/models/development_server.rb +4 -0
- data/lib/project_types/extension/models/development_server_requirements.rb +1 -2
- data/lib/project_types/extension/models/specification_handlers/default.rb +4 -0
- data/lib/project_types/extension/tasks/converters/server_config_converter.rb +31 -0
- data/lib/project_types/extension/tasks/find_npm_packages.rb +2 -2
- data/lib/project_types/extension/tasks/load_server_config.rb +23 -0
- data/lib/project_types/extension/tasks/run_extension_command.rb +26 -10
- data/lib/project_types/node/commands/serve.rb +9 -1
- data/lib/project_types/node/messages/messages.rb +3 -0
- data/lib/project_types/script/cli.rb +4 -3
- data/lib/project_types/script/commands/create.rb +2 -0
- data/lib/project_types/script/config/extension_points.yml +30 -29
- data/lib/project_types/script/layers/application/create_script.rb +32 -12
- data/lib/project_types/script/layers/application/extension_points.rb +3 -3
- data/lib/project_types/script/layers/domain/extension_point.rb +13 -45
- data/lib/project_types/script/layers/infrastructure/api_clients/partners_proxy_api_client.rb +4 -2
- data/lib/project_types/script/layers/infrastructure/api_clients/script_service_api_client.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/errors.rb +5 -0
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +10 -90
- data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +76 -11
- data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb +33 -0
- data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +105 -0
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +1 -1
- data/lib/project_types/script/messages/messages.rb +4 -0
- data/lib/project_types/script/ui/error_handler.rb +8 -0
- data/lib/shopify_cli/command/app_sub_command.rb +16 -0
- data/lib/shopify_cli/constants.rb +33 -5
- data/lib/shopify_cli/core/executor.rb +5 -1
- data/lib/shopify_cli/environment.rb +35 -4
- data/lib/shopify_cli/exception_reporter/permission_controller.rb +54 -0
- data/lib/shopify_cli/exception_reporter.rb +55 -0
- data/lib/shopify_cli/git.rb +30 -0
- data/lib/shopify_cli/messages/messages.rb +27 -1
- data/lib/shopify_cli/method_object.rb +11 -4
- data/lib/shopify_cli/migrator/migration.rb +27 -0
- data/lib/shopify_cli/migrator/migrations/1631709766_noop.rb +13 -0
- data/lib/shopify_cli/migrator.rb +48 -0
- data/lib/shopify_cli/version.rb +1 -1
- data/lib/shopify_cli.rb +11 -3
- data/shopify-cli.gemspec +9 -1
- data/utilities/docker.rb +47 -0
- data/utilities/utilities.rb +5 -0
- metadata +31 -6
- data/lib/project_types/script/layers/infrastructure/languages/rust_project_creator.rb +0 -73
- data/lib/project_types/script/layers/infrastructure/languages/rust_task_runner.rb +0 -60
| @@ -1,26 +1,54 @@ | |
| 1 1 | 
             
            module ShopifyCLI
         | 
| 2 2 | 
             
              module Constants
         | 
| 3 | 
            +
                module Paths
         | 
| 4 | 
            +
                  ROOT = File.expand_path("../..", __dir__)
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                module StoreKeys
         | 
| 8 | 
            +
                  LAST_MIGRATION_DATE = :last_migration_date
         | 
| 9 | 
            +
                  ANALYTICS_ENABLED = :analytics_enabled
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                module Bugsnag
         | 
| 13 | 
            +
                  API_KEY = "773b0c801eb40c20d8928be5b7c739bd"
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                module Config
         | 
| 17 | 
            +
                  module Sections
         | 
| 18 | 
            +
                    module ErrorTracking
         | 
| 19 | 
            +
                      NAME = "error-tracking"
         | 
| 20 | 
            +
                      module Fields
         | 
| 21 | 
            +
                        AUTOMATIC_REPORTING = "automatic-reporting"
         | 
| 22 | 
            +
                      end
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 3 27 | 
             
                module EnvironmentVariables
         | 
| 28 | 
            +
                  STACKTRACE = "SHOPIFY_CLI_STACKTRACE"
         | 
| 29 | 
            +
             | 
| 4 30 | 
             
                  # When true the CLI points to a local instance of
         | 
| 5 31 | 
             
                  # the partners dashboard and identity.
         | 
| 6 32 | 
             
                  LOCAL_PARTNERS = "SHOPIFY_APP_CLI_LOCAL_PARTNERS"
         | 
| 7 33 |  | 
| 8 34 | 
             
                  # When true the CLI points to a spin instance of spin
         | 
| 9 35 | 
             
                  SPIN_PARTNERS = "SHOPIFY_APP_CLI_SPIN_PARTNERS"
         | 
| 10 | 
            -
             | 
| 11 36 | 
             
                  SPIN_WORKSPACE = "SPIN_WORKSPACE"
         | 
| 12 | 
            -
             | 
| 13 37 | 
             
                  SPIN_NAMESPACE = "SPIN_NAMESPACE"
         | 
| 14 | 
            -
             | 
| 15 38 | 
             
                  SPIN_HOST = "SPIN_HOST"
         | 
| 16 39 |  | 
| 17 | 
            -
                  #  | 
| 18 | 
            -
                   | 
| 40 | 
            +
                  # Environments
         | 
| 41 | 
            +
                  TEST = "SHOPIFY_CLI_TEST"
         | 
| 42 | 
            +
                  DEVELOPMENT = "SHOPIFY_CLI_DEVELOPMENT"
         | 
| 19 43 | 
             
                end
         | 
| 20 44 |  | 
| 21 45 | 
             
                module Identity
         | 
| 22 46 | 
             
                  CLIENT_ID_DEV = "e5380e02-312a-7408-5718-e07017e9cf52"
         | 
| 23 47 | 
             
                  CLIENT_ID = "fbdb2649-e327-4907-8f67-908d24cfd7e3"
         | 
| 24 48 | 
             
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                module Links
         | 
| 51 | 
            +
                  NEW_ISSUE = "https://github.com/Shopify/shopify-cli/issues/new"
         | 
| 52 | 
            +
                end
         | 
| 25 53 | 
             
              end
         | 
| 26 54 | 
             
            end
         | 
| @@ -3,6 +3,18 @@ module ShopifyCLI | |
| 3 3 | 
             
              # the environment in which the CLI runs
         | 
| 4 4 | 
             
              module Environment
         | 
| 5 5 | 
             
                TRUTHY_ENV_VARIABLE_VALUES = ["1", "true", "TRUE", "yes", "YES"]
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def self.development?(env_variables: ENV)
         | 
| 8 | 
            +
                  env_variable_truthy?(
         | 
| 9 | 
            +
                    Constants::EnvironmentVariables::DEVELOPMENT,
         | 
| 10 | 
            +
                    env_variables: env_variables
         | 
| 11 | 
            +
                  )
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def self.interactive?
         | 
| 15 | 
            +
                  ShopifyCLI::Context.new.tty?
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 6 18 | 
             
                def self.use_local_partners_instance?(env_variables: ENV)
         | 
| 7 19 | 
             
                  env_variable_truthy?(
         | 
| 8 20 | 
             
                    Constants::EnvironmentVariables::LOCAL_PARTNERS,
         | 
| @@ -10,16 +22,30 @@ module ShopifyCLI | |
| 10 22 | 
             
                  )
         | 
| 11 23 | 
             
                end
         | 
| 12 24 |  | 
| 13 | 
            -
                def self. | 
| 25 | 
            +
                def self.print_stacktrace?(env_variables: ENV)
         | 
| 14 26 | 
             
                  env_variable_truthy?(
         | 
| 15 | 
            -
                    Constants::EnvironmentVariables:: | 
| 27 | 
            +
                    Constants::EnvironmentVariables::STACKTRACE,
         | 
| 28 | 
            +
                    env_variables: env_variables
         | 
| 29 | 
            +
                  )
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def self.test?(env_variables: ENV)
         | 
| 33 | 
            +
                  env_variable_truthy?(
         | 
| 34 | 
            +
                    Constants::EnvironmentVariables::TEST,
         | 
| 35 | 
            +
                    env_variables: env_variables
         | 
| 36 | 
            +
                  )
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def self.print_backtrace?(env_variables: ENV)
         | 
| 40 | 
            +
                  env_variable_truthy?(
         | 
| 41 | 
            +
                    Constants::EnvironmentVariables::BACKTRACE,
         | 
| 16 42 | 
             
                    env_variables: env_variables
         | 
| 17 43 | 
             
                  )
         | 
| 18 44 | 
             
                end
         | 
| 19 45 |  | 
| 20 | 
            -
                def self. | 
| 46 | 
            +
                def self.use_spin_partners_instance?(env_variables: ENV)
         | 
| 21 47 | 
             
                  env_variable_truthy?(
         | 
| 22 | 
            -
                    Constants::EnvironmentVariables:: | 
| 48 | 
            +
                    Constants::EnvironmentVariables::SPIN_PARTNERS,
         | 
| 23 49 | 
             
                    env_variables: env_variables
         | 
| 24 50 | 
             
                  )
         | 
| 25 51 | 
             
                end
         | 
| @@ -34,6 +60,11 @@ module ShopifyCLI | |
| 34 60 | 
             
                  end
         | 
| 35 61 | 
             
                end
         | 
| 36 62 |  | 
| 63 | 
            +
                def self.use_spin?(env_variables: ENV)
         | 
| 64 | 
            +
                  !env_variables[Constants::EnvironmentVariables::SPIN_WORKSPACE].nil? &&
         | 
| 65 | 
            +
                    !env_variables[Constants::EnvironmentVariables::SPIN_NAMESPACE].nil?
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 37 68 | 
             
                def self.spin_url(env_variables: ENV)
         | 
| 38 69 | 
             
                  spin_workspace = spin_workspace(env_variables: env_variables)
         | 
| 39 70 | 
             
                  spin_namespace = spin_namespace(env_variables: env_variables)
         | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            module ShopifyCLI
         | 
| 2 | 
            +
              module ExceptionReporter
         | 
| 3 | 
            +
                module PermissionController
         | 
| 4 | 
            +
                  def self.report_error?(context: ShopifyCLI::Context.new)
         | 
| 5 | 
            +
                    CLI::UI::Prompt.ask(context.message("core.error_reporting.report_error.question")) do |handler|
         | 
| 6 | 
            +
                      handler.option(context.message("core.error_reporting.report_error.yes")) { |_| true }
         | 
| 7 | 
            +
                      handler.option(context.message("core.error_reporting.report_error.no")) { |_| false }
         | 
| 8 | 
            +
                    end
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def self.automatic_reporting_prompted?
         | 
| 12 | 
            +
                    ShopifyCLI::Config.get_section(Constants::Config::Sections::ErrorTracking::NAME).key?(
         | 
| 13 | 
            +
                      Constants::Config::Sections::ErrorTracking::Fields::AUTOMATIC_REPORTING
         | 
| 14 | 
            +
                    )
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def self.can_report_automatically?(context: ShopifyCLI::Context.new)
         | 
| 18 | 
            +
                    # If the terminal is not interactive we can't prompt the user.
         | 
| 19 | 
            +
                    return false unless ShopifyCLI::Environment.interactive?
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    if automatic_reporting_prompted?
         | 
| 22 | 
            +
                      automatic_reporting_enabled?
         | 
| 23 | 
            +
                    else
         | 
| 24 | 
            +
                      prompt_user(context: context)
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def self.prompt_user(context:)
         | 
| 29 | 
            +
                    enable_automatic_tracking = CLI::UI::Prompt.ask(
         | 
| 30 | 
            +
                      context.message("core.error_reporting.enable_automatic_reporting_prompt.question")
         | 
| 31 | 
            +
                    ) do |handler|
         | 
| 32 | 
            +
                      handler.option(context.message("core.error_reporting.enable_automatic_reporting_prompt.yes")) { |_| true }
         | 
| 33 | 
            +
                      handler.option(context.message("core.error_reporting.enable_automatic_reporting_prompt.no")) { |_| false }
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    ShopifyCLI::Config.set(
         | 
| 37 | 
            +
                      Constants::Config::Sections::ErrorTracking::NAME,
         | 
| 38 | 
            +
                      Constants::Config::Sections::ErrorTracking::Fields::AUTOMATIC_REPORTING,
         | 
| 39 | 
            +
                      enable_automatic_tracking
         | 
| 40 | 
            +
                    )
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    enable_automatic_tracking
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  def self.automatic_reporting_enabled?
         | 
| 46 | 
            +
                    ShopifyCLI::Config.get_bool(
         | 
| 47 | 
            +
                      Constants::Config::Sections::ErrorTracking::NAME,
         | 
| 48 | 
            +
                      Constants::Config::Sections::ErrorTracking::Fields::AUTOMATIC_REPORTING,
         | 
| 49 | 
            +
                      default: false
         | 
| 50 | 
            +
                    )
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
            end
         | 
| @@ -0,0 +1,55 @@ | |
| 1 | 
            +
            module ShopifyCLI
         | 
| 2 | 
            +
              module ExceptionReporter
         | 
| 3 | 
            +
                autoload :PermissionController, "shopify_cli/exception_reporter/permission_controller"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def self.report(error, _logs = nil, _api_key = nil, custom_metadata = {})
         | 
| 6 | 
            +
                  context = ShopifyCLI::Context.new
         | 
| 7 | 
            +
                  context.puts("\n")
         | 
| 8 | 
            +
                  context.puts(context.message("core.error_reporting.unhandled_error.message"))
         | 
| 9 | 
            +
                  context.puts(context.message("core.error_reporting.unhandled_error.issue_message"))
         | 
| 10 | 
            +
                  unless ShopifyCLI::Environment.print_stacktrace?
         | 
| 11 | 
            +
                    context.puts(context.message("core.error_reporting.unhandled_error.stacktrace_message",
         | 
| 12 | 
            +
                      "#{ShopifyCLI::Constants::EnvironmentVariables::STACKTRACE}=1"))
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                  context.puts("\n")
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  return unless reportable_error?(error)
         | 
| 17 | 
            +
                  return unless report?
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  ENV["BUGSNAG_DISABLE_AUTOCONFIGURE"] = "1"
         | 
| 20 | 
            +
                  require "bugsnag"
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  Bugsnag.configure do |config|
         | 
| 23 | 
            +
                    config.logger.level = ::Logger::ERROR
         | 
| 24 | 
            +
                    config.api_key = ShopifyCLI::Constants::Bugsnag::API_KEY
         | 
| 25 | 
            +
                    config.app_type = "shopify"
         | 
| 26 | 
            +
                    config.project_root = File.expand_path("../../..", __FILE__)
         | 
| 27 | 
            +
                    config.app_version = ShopifyCLI::VERSION
         | 
| 28 | 
            +
                    config.auto_capture_sessions = false
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  metadata = {}
         | 
| 32 | 
            +
                  metadata.merge!(custom_metadata)
         | 
| 33 | 
            +
                  # Bugsnag.notify(error, metadata)
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def self.report?
         | 
| 37 | 
            +
                  # return false if ShopifyCLI::Environment.development?
         | 
| 38 | 
            +
                  return true if ExceptionReporter::PermissionController.automatic_reporting_prompted? &&
         | 
| 39 | 
            +
                    ExceptionReporter::PermissionController.can_report_automatically?
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  report_error = ExceptionReporter::PermissionController.report_error?
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  unless ExceptionReporter::PermissionController.automatic_reporting_prompted?
         | 
| 44 | 
            +
                    ExceptionReporter::PermissionController.can_report_automatically?
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  report_error
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def self.reportable_error?(error)
         | 
| 51 | 
            +
                  is_abort = error.is_a?(ShopifyCLI::Abort) || error.is_a?(ShopifyCLI::AbortSilent)
         | 
| 52 | 
            +
                  !is_abort
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
            end
         | 
    
        data/lib/shopify_cli/git.rb
    CHANGED
    
    | @@ -105,6 +105,36 @@ module ShopifyCLI | |
| 105 105 | 
             
                    end
         | 
| 106 106 | 
             
                  end
         | 
| 107 107 |  | 
| 108 | 
            +
                  def sparse_checkout(repo, set, branch, ctx)
         | 
| 109 | 
            +
                    _, status = ctx.capture2e("git init")
         | 
| 110 | 
            +
                    unless status.success?
         | 
| 111 | 
            +
                      ctx.abort(ctx.message("core.git.error.repo_not_initiated"))
         | 
| 112 | 
            +
                    end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                    _, status = ctx.capture2e("git remote add -f origin #{repo}")
         | 
| 115 | 
            +
                    unless status.success?
         | 
| 116 | 
            +
                      ctx.abort(ctx.message("core.git.error.remote_not_added"))
         | 
| 117 | 
            +
                    end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                    _, status = ctx.capture2e("git config core.sparsecheckout true")
         | 
| 120 | 
            +
                    unless status.success?
         | 
| 121 | 
            +
                      ctx.abort(ctx.message("core.git.error.sparse_checkout_not_enabled"))
         | 
| 122 | 
            +
                    end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                    _, status = ctx.capture2e("git sparse-checkout set #{set}")
         | 
| 125 | 
            +
                    unless status.success?
         | 
| 126 | 
            +
                      ctx.abort(ctx.message("core.git.error.sparse_checkout_not_set"))
         | 
| 127 | 
            +
                    end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                    resp, status = ctx.capture2e("git pull origin #{branch}")
         | 
| 130 | 
            +
                    unless status.success?
         | 
| 131 | 
            +
                      if resp.include?("fatal: couldn't find remote ref")
         | 
| 132 | 
            +
                        ctx.abort(ctx.message("core.git.error.pull_failed_bad_branch", branch))
         | 
| 133 | 
            +
                      end
         | 
| 134 | 
            +
                      ctx.abort(ctx.message("core.git.error.pull_failed"))
         | 
| 135 | 
            +
                    end
         | 
| 136 | 
            +
                  end
         | 
| 137 | 
            +
             | 
| 108 138 | 
             
                  private
         | 
| 109 139 |  | 
| 110 140 | 
             
                  def exec(*args, dir: Dir.pwd, default: nil, ctx: Context.new)
         | 
| @@ -14,6 +14,25 @@ module ShopifyCLI | |
| 14 14 | 
             
                    },
         | 
| 15 15 | 
             
                  },
         | 
| 16 16 | 
             
                  core: {
         | 
| 17 | 
            +
                    error_reporting: {
         | 
| 18 | 
            +
                      unhandled_error: {
         | 
| 19 | 
            +
                        message: "{{x}} {{red:An unexpected error occured.}}",
         | 
| 20 | 
            +
                        issue_message: "{{red:\tTo \e]8;;#{ShopifyCLI::Constants::Links::NEW_ISSUE}\e\\submit an issue\e]8;;\e\\"\
         | 
| 21 | 
            +
                          " include the stack trace.}}",
         | 
| 22 | 
            +
                        stacktrace_message: "{{red:\tTo print the stack trace, add the environment variable %s.}}",
         | 
| 23 | 
            +
                      },
         | 
| 24 | 
            +
                      enable_automatic_reporting_prompt: {
         | 
| 25 | 
            +
                        question: "Automatically send error reports moving forward?",
         | 
| 26 | 
            +
                        yes: "Automatically send error reports to the Shopify team",
         | 
| 27 | 
            +
                        no: "Don't send error reports",
         | 
| 28 | 
            +
                        enabled: "Anonymized error reports will be sent to Shopify.",
         | 
| 29 | 
            +
                      },
         | 
| 30 | 
            +
                      report_error: {
         | 
| 31 | 
            +
                        question: "Send an error report to Shopify?",
         | 
| 32 | 
            +
                        yes: "Send report",
         | 
| 33 | 
            +
                        no: "Don't send",
         | 
| 34 | 
            +
                      },
         | 
| 35 | 
            +
                    },
         | 
| 17 36 | 
             
                    connect: {
         | 
| 18 37 | 
             
                      already_connected_warning: "{{yellow:! This app appears to be already connected}}",
         | 
| 19 38 | 
             
                      project_type_select: "What type of project would you like to connect?",
         | 
| @@ -67,10 +86,18 @@ module ShopifyCLI | |
| 67 86 | 
             
                        repo_not_initiated:
         | 
| 68 87 | 
             
                          "Git repo is not initiated. Please run {{command:git init}} and make at least one commit.",
         | 
| 69 88 | 
             
                        no_commits_made: "No git commits have been made. Please make at least one commit.",
         | 
| 89 | 
            +
                        remote_not_added: "Remote could not be added.",
         | 
| 90 | 
            +
                        sparse_checkout_not_enabled: "Sparse checkout could not be enabled.",
         | 
| 91 | 
            +
                        sparse_checkout_not_set: "Sparse checkout set command failed.",
         | 
| 92 | 
            +
                        pull_failed: "Pull failed.",
         | 
| 93 | 
            +
                        pull_failed_bad_branch: "Pull failed. Branch %s cannot be found. Check the branch name and try again.",
         | 
| 70 94 | 
             
                      },
         | 
| 71 95 |  | 
| 72 96 | 
             
                      cloning: "Cloning %s into %s…",
         | 
| 73 97 | 
             
                      cloned: "{{v}} Cloned into %s",
         | 
| 98 | 
            +
                      pulling_from_to: "Pulling %s into %s…",
         | 
| 99 | 
            +
                      pulling: "Pulling…",
         | 
| 100 | 
            +
                      pulled: "Pulled into %s",
         | 
| 74 101 | 
             
                    },
         | 
| 75 102 |  | 
| 76 103 | 
             
                    help: {
         | 
| @@ -429,7 +456,6 @@ module ShopifyCLI | |
| 429 456 | 
             
                        ngrok: "Something went wrong with ngrok installation,"\
         | 
| 430 457 | 
             
                          "please make sure %s exists within %s before trying again",
         | 
| 431 458 | 
             
                      },
         | 
| 432 | 
            -
             | 
| 433 459 | 
             
                      installing: "Installing ngrok…",
         | 
| 434 460 | 
             
                      not_running: "{{green:x}} ngrok tunnel not running",
         | 
| 435 461 | 
             
                      prereq_command_location: "%s @ %s",
         | 
| @@ -48,12 +48,14 @@ module ShopifyCLI | |
| 48 48 | 
             
              #
         | 
| 49 49 | 
             
              module MethodObject
         | 
| 50 50 | 
             
                module AutoCreateResultObject
         | 
| 51 | 
            +
                  def self.ruby2_keywords(*); end unless respond_to?(:ruby2_keywords, true)
         | 
| 52 | 
            +
             | 
| 51 53 | 
             
                  ##
         | 
| 52 54 | 
             
                  # invokes the original `call` implementation and wraps its return value
         | 
| 53 55 | 
             
                  # into a result object.
         | 
| 54 56 | 
             
                  #
         | 
| 55 | 
            -
                  def call(*args,  | 
| 56 | 
            -
                    Result.wrap {  | 
| 57 | 
            +
                  ruby2_keywords def call(*args, &block)
         | 
| 58 | 
            +
                    Result.wrap { super(*args, &block) }.call
         | 
| 57 59 | 
             
                  end
         | 
| 58 60 | 
             
                end
         | 
| 59 61 |  | 
| @@ -66,8 +68,13 @@ module ShopifyCLI | |
| 66 68 | 
             
                  #
         | 
| 67 69 | 
             
                  def call(*args, **kwargs, &block)
         | 
| 68 70 | 
             
                    properties.keys.yield_self do |properties|
         | 
| 69 | 
            -
                      new(**kwargs.slice(*properties))
         | 
| 70 | 
            -
             | 
| 71 | 
            +
                      instance = new(**kwargs.slice(*properties))
         | 
| 72 | 
            +
                      kwargs = kwargs.slice(*(kwargs.keys - properties))
         | 
| 73 | 
            +
                      if kwargs.any?
         | 
| 74 | 
            +
                        instance.call(*args, **kwargs, &block)
         | 
| 75 | 
            +
                      else
         | 
| 76 | 
            +
                        instance.call(*args, &block)
         | 
| 77 | 
            +
                      end
         | 
| 71 78 | 
             
                    end
         | 
| 72 79 | 
             
                  end
         | 
| 73 80 |  | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require "date"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module ShopifyCLI
         | 
| 5 | 
            +
              module Migrator
         | 
| 6 | 
            +
                class Migration
         | 
| 7 | 
            +
                  attr_reader :name, :path, :date
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def initialize(name:, path:, date:)
         | 
| 10 | 
            +
                    @name = name
         | 
| 11 | 
            +
                    @path = path
         | 
| 12 | 
            +
                    @date = date
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def run
         | 
| 16 | 
            +
                    require(path)
         | 
| 17 | 
            +
                    ShopifyCli::Migrator::Migrations.const_get(class_name).run
         | 
| 18 | 
            +
                  rescue StandardError
         | 
| 19 | 
            +
                    # Continue
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  def class_name
         | 
| 23 | 
            +
                    name.split("_").collect(&:capitalize).join
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require "date"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module ShopifyCLI
         | 
| 5 | 
            +
              module Migrator
         | 
| 6 | 
            +
                autoload :Migration, "shopify_cli/migrator/migration"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def self.migrate(
         | 
| 9 | 
            +
                  migrations_directory: File.expand_path("migrator/migrations", __dir__)
         | 
| 10 | 
            +
                )
         | 
| 11 | 
            +
                  baseline_date = last_migration_date
         | 
| 12 | 
            +
                  unless baseline_date.nil?        
         | 
| 13 | 
            +
                    migrations = migrations(migrations_directory: migrations_directory)
         | 
| 14 | 
            +
                      .select { |m| 
         | 
| 15 | 
            +
                        m.date > baseline_date.to_i 
         | 
| 16 | 
            +
                      }
         | 
| 17 | 
            +
                      .each { |m| m.run }
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  store_last_migration_date
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                private
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def self.store_last_migration_date
         | 
| 26 | 
            +
                  ShopifyCLI::DB.set(ShopifyCLI::Constants::StoreKeys::LAST_MIGRATION_DATE => Time.now.to_i)
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
                
         | 
| 29 | 
            +
                def self.last_migration_date
         | 
| 30 | 
            +
                  ShopifyCLI::DB.get(ShopifyCLI::Constants::StoreKeys::LAST_MIGRATION_DATE)
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def self.migrations(migrations_directory:)
         | 
| 34 | 
            +
                  Dir.glob(File.join(migrations_directory, "*.rb")).map do |file_path|
         | 
| 35 | 
            +
                    file_name = File.basename(file_path).gsub(".rb", "")
         | 
| 36 | 
            +
                    file_name_components = file_name.split("_")
         | 
| 37 | 
            +
                    date_timestamp = file_name_components[0].to_i
         | 
| 38 | 
            +
                    migration_name = file_name_components[1...].join("_")
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    Migrator::Migration.new(
         | 
| 41 | 
            +
                      name: migration_name,
         | 
| 42 | 
            +
                      date: Time.at(date_timestamp).to_i,
         | 
| 43 | 
            +
                      path: file_path
         | 
| 44 | 
            +
                    )
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
    
        data/lib/shopify_cli/version.rb
    CHANGED
    
    
    
        data/lib/shopify_cli.rb
    CHANGED
    
    | @@ -25,6 +25,8 @@ require "cli/ui" | |
| 25 25 | 
             
            require "cli/kit"
         | 
| 26 26 | 
             
            require "smart_properties"
         | 
| 27 27 | 
             
            require_relative "shopify_cli/version"
         | 
| 28 | 
            +
            require_relative "shopify_cli/migrator"
         | 
| 29 | 
            +
            require_relative "shopify_cli/exception_reporter"
         | 
| 28 30 |  | 
| 29 31 | 
             
            # Enable stdout routing. At this point all calls to STDOUT (and STDERR) will go through this class.
         | 
| 30 32 | 
             
            # See https://github.com/Shopify/cli-ui/blob/main/lib/cli/ui/stdout_router.rb for more info
         | 
| @@ -90,7 +92,7 @@ module ShopifyCLI | |
| 90 92 | 
             
              autocall(:ErrorHandler) do
         | 
| 91 93 | 
             
                CLI::Kit::ErrorHandler.new(
         | 
| 92 94 | 
             
                  log_file: ShopifyCLI.log_file,
         | 
| 93 | 
            -
                  exception_reporter:  | 
| 95 | 
            +
                  exception_reporter: ->() { ShopifyCLI::ExceptionReporter },
         | 
| 94 96 | 
             
                )
         | 
| 95 97 | 
             
              end
         | 
| 96 98 |  | 
| @@ -135,7 +137,7 @@ module ShopifyCLI | |
| 135 137 | 
             
              Context.load_messages(ShopifyCLI::Messages::MESSAGES)
         | 
| 136 138 |  | 
| 137 139 | 
             
              def self.cache_dir
         | 
| 138 | 
            -
                cache_dir = if Environment. | 
| 140 | 
            +
                cache_dir = if Environment.test?
         | 
| 139 141 | 
             
                  TEMP_DIR
         | 
| 140 142 | 
             
                elsif ENV["LOCALAPPDATA"].nil?
         | 
| 141 143 | 
             
                  File.join(File.expand_path(ENV.fetch("XDG_CACHE_HOME", "~/.cache")), TOOL_NAME)
         | 
| @@ -150,7 +152,7 @@ module ShopifyCLI | |
| 150 152 | 
             
              end
         | 
| 151 153 |  | 
| 152 154 | 
             
              def self.tool_config_path
         | 
| 153 | 
            -
                if Environment. | 
| 155 | 
            +
                if Environment.test?
         | 
| 154 156 | 
             
                  TEMP_DIR
         | 
| 155 157 | 
             
                elsif ENV["APPDATA"].nil?
         | 
| 156 158 | 
             
                  File.join(File.expand_path(ENV.fetch("XDG_CONFIG_HOME", "~/.config")), TOOL_NAME)
         | 
| @@ -171,4 +173,10 @@ module ShopifyCLI | |
| 171 173 | 
             
                return @sha if defined?(@sha)
         | 
| 172 174 | 
             
                @sha = Git.sha(dir: ShopifyCLI::ROOT)
         | 
| 173 175 | 
             
              end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
              # Migrate runs migrations that migrate the state of the environment
         | 
| 178 | 
            +
              # in which the CLI runs.
         | 
| 179 | 
            +
              unless ShopifyCLI::Environment.test? || ShopifyCLI::Environment.development?
         | 
| 180 | 
            +
                ShopifyCLI::Migrator.migrate
         | 
| 181 | 
            +
              end
         | 
| 174 182 | 
             
            end
         | 
    
        data/shopify-cli.gemspec
    CHANGED
    
    | @@ -43,6 +43,14 @@ Gem::Specification.new do |spec| | |
| 43 43 | 
             
              spec.add_development_dependency("rake", "~> 12.3", ">= 12.3.3")
         | 
| 44 44 | 
             
              spec.add_development_dependency("minitest", "~> 5.0")
         | 
| 45 45 |  | 
| 46 | 
            +
              spec.add_dependency("bugsnag", "~> 6.22")
         | 
| 46 47 | 
             
              spec.add_dependency("listen", "~> 3.7.0")
         | 
| 47 | 
            -
             | 
| 48 | 
            +
             | 
| 49 | 
            +
              # Note: theme-check is _intentionally_ not specifying the third
         | 
| 50 | 
            +
              # digit. We _want_ new features to make their way into new installs
         | 
| 51 | 
            +
              # of the Shopify CLI. Otherwise updates need to be released twice.
         | 
| 52 | 
            +
              #
         | 
| 53 | 
            +
              # That is, DO USE ~> 1.X, DO NOT USE ~> 1.X.Y, this would unnecessarily
         | 
| 54 | 
            +
              # fix the feature version.
         | 
| 55 | 
            +
              spec.add_dependency("theme-check", "~> 1.7")
         | 
| 48 56 | 
             
            end
         | 
    
        data/utilities/docker.rb
    ADDED
    
    | @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            require "open3"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Utilities
         | 
| 4 | 
            +
              module Docker
         | 
| 5 | 
            +
                Error = Class.new(StandardError)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                class << self
         | 
| 8 | 
            +
                  def run_and_rm_container(*args)
         | 
| 9 | 
            +
                    build_image_if_needed
         | 
| 10 | 
            +
                    system(
         | 
| 11 | 
            +
                      "docker", "run",
         | 
| 12 | 
            +
                      "-t", "--rm",
         | 
| 13 | 
            +
                      "--volume", "#{Shellwords.escape(root_dir)}:/usr/src/app",
         | 
| 14 | 
            +
                      image_tag,
         | 
| 15 | 
            +
                      *args
         | 
| 16 | 
            +
                    ) || abort
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  private
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def root_dir
         | 
| 22 | 
            +
                    File.expand_path("..", __dir__)
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def build_image_if_needed
         | 
| 26 | 
            +
                    unless image_exists?(image_tag)
         | 
| 27 | 
            +
                      system("docker", "build", root_dir, "-t", image_tag) || abort
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def image_tag
         | 
| 32 | 
            +
                    gemfile_lock_path = File.expand_path("./Gemfile.lock", root_dir)
         | 
| 33 | 
            +
                    image_sha = Digest::SHA256.hexdigest(File.read(gemfile_lock_path))
         | 
| 34 | 
            +
                    "shopify-cli-#{image_sha}"
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def image_exists?(tag)
         | 
| 38 | 
            +
                    _, stat = Open3.capture2(
         | 
| 39 | 
            +
                      "docker", "inspect",
         | 
| 40 | 
            +
                      "--type=image",
         | 
| 41 | 
            +
                      tag
         | 
| 42 | 
            +
                    )
         | 
| 43 | 
            +
                    stat.success?
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
            end
         |