shopify-cli 1.10.0 → 1.11.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/PULL_REQUEST_TEMPLATE.md +1 -0
  3. data/CHANGELOG.md +9 -1
  4. data/Gemfile.lock +1 -1
  5. data/lib/project_types/extension/cli.rb +6 -2
  6. data/lib/project_types/extension/commands/serve.rb +69 -1
  7. data/lib/project_types/extension/commands/tunnel.rb +3 -1
  8. data/lib/project_types/extension/extension_project.rb +1 -0
  9. data/lib/project_types/extension/features/argo.rb +15 -24
  10. data/lib/project_types/extension/features/argo_runtime.rb +63 -0
  11. data/lib/project_types/extension/features/argo_serve.rb +35 -25
  12. data/lib/project_types/extension/features/argo_serve_options.rb +40 -0
  13. data/lib/project_types/extension/messages/messages.rb +3 -0
  14. data/lib/project_types/extension/models/npm_package.rb +14 -0
  15. data/lib/project_types/extension/models/specification.rb +1 -0
  16. data/lib/project_types/extension/models/specification_handlers/checkout_argo_extension.rb +18 -0
  17. data/lib/project_types/extension/models/specification_handlers/default.rb +28 -3
  18. data/lib/project_types/extension/tasks/choose_next_available_port.rb +36 -0
  19. data/lib/project_types/extension/tasks/configure_features.rb +2 -0
  20. data/lib/project_types/extension/tasks/find_npm_packages.rb +106 -0
  21. data/lib/project_types/script/cli.rb +1 -0
  22. data/lib/project_types/script/layers/domain/errors.rb +0 -2
  23. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +12 -17
  24. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +13 -7
  25. data/lib/project_types/script/layers/infrastructure/command_runner.rb +19 -0
  26. data/lib/project_types/script/layers/infrastructure/errors.rb +12 -3
  27. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +4 -4
  28. data/lib/project_types/script/layers/infrastructure/rust_project_creator.rb +9 -10
  29. data/lib/project_types/script/layers/infrastructure/rust_task_runner.rb +5 -6
  30. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +2 -28
  31. data/lib/project_types/script/layers/infrastructure/script_service.rb +1 -1
  32. data/lib/project_types/script/messages/messages.rb +6 -4
  33. data/lib/project_types/script/tasks/ensure_env.rb +10 -2
  34. data/lib/project_types/script/ui/error_handler.rb +7 -6
  35. data/lib/shopify-cli/messages/messages.rb +47 -43
  36. data/lib/shopify-cli/method_object.rb +4 -4
  37. data/lib/shopify-cli/oauth.rb +7 -1
  38. data/lib/shopify-cli/partners_api/organizations.rb +3 -3
  39. data/lib/shopify-cli/tasks/select_org_and_shop.rb +6 -4
  40. data/lib/shopify-cli/tunnel.rb +22 -1
  41. data/lib/shopify-cli/version.rb +1 -1
  42. metadata +10 -4
  43. data/lib/project_types/extension/features/argo_renderer_package.rb +0 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea41fa5cbfa0eb2bf575fe82111c6be56df6807ed7696e64acc741ef2fa2e6be
4
- data.tar.gz: 899299251ed4b0a50b0c3a5c5ae55324ebd64e92fbb981da7d4a093df94d5596
3
+ metadata.gz: e1ca8221a25313b8cd908a02e4c5c68dc9f74ed38e7472804346419e45d8d9d8
4
+ data.tar.gz: b0658aae7cb7ca368b78aa80f3fab364867bc1d6ae36515c07f3692bb87730cb
5
5
  SHA512:
6
- metadata.gz: 8b757bbf4ef686593f3fe8fdf82da6c83468f40d04bc312476e2bea614d5f75e3d63afe097c149f3de34b35631032c096799f0728b12732dfbbb5bd3e5141384
7
- data.tar.gz: 2059062ef9aff95cad44d2b4bcad442e2cf82636d6733c065bb83544ac4d0b8cef2a5de3c438d5f252a251fa0cf813b03fc064db407940e3469b476a26c35e0d
6
+ metadata.gz: 54fde8fed1098f483c817cfb0dd8d9ab291556da026dabcc7d0e0dc934fb9c2e97dd2865d72257ca75a2c5d1560759e4ece27c8acc76a8a56f299e8f004594f0
7
+ data.tar.gz: b193f5f389c2a03875e98d4636aa3cd16c7bfe212d798defed234233b0aad410382e3f56d83b58f63189b6f8256be762518c4439bfe732961c682db8fd81cb25
@@ -29,3 +29,4 @@ Fixes #0000 <!-- link to issue if one exists -->
29
29
  -->
30
30
  - [ ] I've added a CHANGELOG entry for this PR (if the change is public-facing)
31
31
  - [ ] I've considered possible cross-platform impacts (Mac, Linux, Windows).
32
+ - [ ] I've left the version number as is (we'll handle incrmenting this when releasing).
data/CHANGELOG.md CHANGED
@@ -1,8 +1,16 @@
1
1
  Unreleased
2
2
  ------
3
3
 
4
+ Version 1.11.0
5
+ --------------
6
+ * [#1221](https://github.com/Shopify/shopify-app-cli/pull/1221): Prioritizes returning an HTTPS URL over HTTP from `shopify tunnel status`.
7
+ * [#1223](https://github.com/Shopify/shopify-app-cli/pull/1233): Running `shopify serve` in an extension project now automatically runs `shopify tunnel`.
8
+ * [#1225](https://github.com/Shopify/shopify-app-cli/pull/1225): Improved handling of "account not found" scenario, plus improvements to related tests and UX messaging
9
+ * [#1229](https://github.com/Shopify/shopify-app-cli/pull/1229): Allows Checkout Extensions to specify configuration attributes in their extension.config.yml file.
10
+ * [#1238](https://github.com/Shopify/shopify-app-cli/pull/1238): Auto Tunnel Support for Checkout Extension
11
+
4
12
  Version 1.10.0
5
- -------------
13
+ --------------
6
14
  * Updating internal features in development
7
15
 
8
16
  Version 1.9.1
data/Gemfile.lock CHANGED
@@ -76,4 +76,4 @@ DEPENDENCIES
76
76
  webmock
77
77
 
78
78
  BUNDLED WITH
79
- 1.17.3
79
+ 2.1.4
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Extension
4
- class PackageNotFound < RuntimeError; end
4
+ class PackageResolutionFailed < RuntimeError; end
5
5
 
6
6
  class Project < ShopifyCli::ProjectType
7
7
  hidden_feature
@@ -38,6 +38,8 @@ module Extension
38
38
  autoload :UpdateDraft, Project.project_filepath("tasks/update_draft")
39
39
  autoload :FetchSpecifications, Project.project_filepath("tasks/fetch_specifications")
40
40
  autoload :ConfigureFeatures, Project.project_filepath("tasks/configure_features")
41
+ autoload :ChooseNextAvailablePort, Project.project_filepath("tasks/choose_next_available_port")
42
+ autoload :FindNpmPackages, Project.project_filepath("tasks/find_npm_packages")
41
43
 
42
44
  module Converters
43
45
  autoload :RegistrationConverter, Project.project_filepath("tasks/converters/registration_converter")
@@ -59,13 +61,14 @@ module Extension
59
61
  end
60
62
 
61
63
  module Features
62
- autoload :ArgoRendererPackage, Project.project_filepath("features/argo_renderer_package")
63
64
  autoload :ArgoServe, Project.project_filepath("features/argo_serve")
65
+ autoload :ArgoServeOptions, Project.project_filepath("features/argo_serve_options")
64
66
  autoload :ArgoSetup, Project.project_filepath("features/argo_setup")
65
67
  autoload :ArgoSetupStep, Project.project_filepath("features/argo_setup_step")
66
68
  autoload :ArgoSetupSteps, Project.project_filepath("features/argo_setup_steps")
67
69
  autoload :ArgoDependencies, Project.project_filepath("features/argo_dependencies")
68
70
  autoload :ArgoConfig, Project.project_filepath("features/argo_config")
71
+ autoload :ArgoRuntime, Project.project_filepath("features/argo_runtime")
69
72
  autoload :Argo, Project.project_filepath("features/argo")
70
73
  end
71
74
 
@@ -81,6 +84,7 @@ module Extension
81
84
  autoload :Specification, Project.project_filepath("models/specification")
82
85
  autoload :Specifications, Project.project_filepath("models/specifications")
83
86
  autoload :LazySpecificationHandler, Project.project_filepath("models/lazy_specification_handler")
87
+ autoload :NpmPackage, Project.project_filepath("models/npm_package")
84
88
  end
85
89
 
86
90
  autoload :ExtensionProjectKeys, Project.project_filepath("extension_project_keys")
@@ -3,16 +3,84 @@
3
3
  module Extension
4
4
  module Commands
5
5
  class Serve < ExtensionCommand
6
+ DEFAULT_PORT = 39351
7
+
8
+ options do |parser, flags|
9
+ parser.on("-t", "--[no-]tunnel", "Establish an ngrok tunnel") { |tunnel| flags[:tunnel] = tunnel }
10
+ end
11
+
12
+ class RuntimeConfiguration
13
+ include SmartProperties
14
+
15
+ property! :tunnel_url, accepts: String, default: ""
16
+ property! :tunnel_requested, accepts: [true, false], reader: :tunnel_requested?, default: true
17
+ property! :port, accepts: (1...(2**16)), default: DEFAULT_PORT
18
+ end
19
+
6
20
  def call(_args, _command_name)
7
- specification_handler.serve(@ctx)
21
+ config = RuntimeConfiguration.new(
22
+ tunnel_requested: tunnel_requested?
23
+ )
24
+
25
+ ShopifyCli::Result
26
+ .success(config)
27
+ .then(&method(:find_available_port))
28
+ .then(&method(:start_tunnel_if_required))
29
+ .then(&method(:serve))
30
+ .unwrap { |error| raise error }
8
31
  end
9
32
 
10
33
  def self.help
11
34
  <<~HELP
12
35
  Serve your extension in a local simulator for development.
13
36
  Usage: {{command:#{ShopifyCli::TOOL_NAME} serve}}
37
+ Options:
38
+ {{command:--tunnel=TUNNEL}} Establish an ngrok tunnel (default: false)
14
39
  HELP
15
40
  end
41
+
42
+ private
43
+
44
+ def tunnel_requested?
45
+ tunnel = options.flags[:tunnel]
46
+ tunnel.nil? || !!tunnel
47
+ end
48
+
49
+ def find_available_port(runtime_configuration)
50
+ return runtime_configuration unless specification_handler.choose_port?(@ctx)
51
+
52
+ chosen_port = Tasks::ChooseNextAvailablePort
53
+ .call(from: runtime_configuration.port)
54
+ .unwrap { |_error| @ctx.abort(@ctx.message("serve.no_available_ports_found")) }
55
+ runtime_configuration.tap { |c| c.port = chosen_port }
56
+ end
57
+
58
+ def start_tunnel_if_required(runtime_configuration)
59
+ return runtime_configuration unless specification_handler.establish_tunnel?(@ctx)
60
+ return runtime_configuration unless runtime_configuration.tunnel_requested?
61
+
62
+ return start_tunnel(runtime_configuration) if can_start_tunnel?(runtime_configuration)
63
+ @ctx.abort(@ctx.message("serve.tunnel_already_running"))
64
+ end
65
+
66
+ def can_start_tunnel?(runtime_configuration)
67
+ return true if ShopifyCli::Tunnel.urls.empty?
68
+ ShopifyCli::Tunnel.running_on?(runtime_configuration.port)
69
+ end
70
+
71
+ def start_tunnel(runtime_configuration)
72
+ tunnel_url = ShopifyCli::Tunnel.start(@ctx, port: runtime_configuration.port)
73
+ runtime_configuration.tap { |c| c.tunnel_url = tunnel_url }
74
+ end
75
+
76
+ def serve(runtime_configuration)
77
+ specification_handler.serve(
78
+ context: @ctx,
79
+ tunnel_url: runtime_configuration.tunnel_url,
80
+ port: runtime_configuration.port
81
+ )
82
+ runtime_configuration
83
+ end
16
84
  end
17
85
  end
18
86
  end
@@ -37,7 +37,9 @@ module Extension
37
37
  private
38
38
 
39
39
  def status
40
- tunnel_url = ShopifyCli::Tunnel.urls.first
40
+ tunnel_urls = ShopifyCli::Tunnel.urls
41
+ tunnel_url = tunnel_urls.find { |url| url.start_with?("https://") }
42
+ tunnel_url = tunnel_urls.first if tunnel_url.nil?
41
43
 
42
44
  if tunnel_url.nil?
43
45
  @ctx.puts(@ctx.message("tunnel.no_tunnel_running"))
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require "shopify_cli"
3
+ require "securerandom"
3
4
 
4
5
  module Extension
5
6
  class ExtensionProject < ShopifyCli::Project
@@ -13,18 +13,22 @@ module Extension
13
13
 
14
14
  SCRIPT_PATH = %w(build main.js).freeze
15
15
 
16
- NPM_LIST_COMMAND = %w(list).freeze
17
- YARN_LIST_COMMAND = %w(list).freeze
18
- NPM_LIST_PARAMETERS = %w(--prod --depth=1).freeze
19
- YARN_LIST_PARAMETERS = %w(--production).freeze
20
- private_constant :NPM_LIST_COMMAND, :YARN_LIST_COMMAND, :NPM_LIST_PARAMETERS, :YARN_LIST_PARAMETERS
21
-
22
16
  YARN_INSTALL_COMMAND = %w(install).freeze
23
17
  YARN_INSTALL_PARAMETERS = %w(--silent).freeze
24
18
  YARN_RUN_COMMAND = %w(run).freeze
25
19
  YARN_RUN_SCRIPT_NAME = %w(build).freeze
26
20
  private_constant :YARN_INSTALL_COMMAND, :YARN_INSTALL_PARAMETERS, :YARN_RUN_COMMAND, :YARN_RUN_SCRIPT_NAME
27
21
 
22
+ ARGO_CHECKOUT = "@shopify/argo-checkout"
23
+ ARGO_ADMIN = "@shopify/argo-admin"
24
+ ARGO_POST_PURCHASE = "@shopify/argo-post-purchase"
25
+
26
+ PACKAGE_NAMES = [
27
+ ARGO_CHECKOUT,
28
+ ARGO_ADMIN,
29
+ ARGO_POST_PURCHASE,
30
+ ].freeze
31
+
28
32
  def create(directory_name, identifier, context)
29
33
  Features::ArgoSetup.new(git_template: git_template).call(directory_name, identifier, context)
30
34
  end
@@ -48,8 +52,11 @@ module Extension
48
52
  end
49
53
 
50
54
  def renderer_package(context)
51
- Features::ArgoRendererPackage.from_package_manager(run_list_command(context))
52
- rescue Extension::PackageNotFound
55
+ js_system = ShopifyCli::JsSystem.new(ctx: context)
56
+ Tasks::FindNpmPackages
57
+ .exactly_one_of(*PACKAGE_NAMES, js_system: js_system)
58
+ .unwrap { |err| raise err }
59
+ rescue Extension::PackageResolutionFailed
53
60
  context.abort(
54
61
  context.message("features.argo.dependencies.argo_missing_renderer_package_error")
55
62
  )
@@ -57,22 +64,6 @@ module Extension
57
64
 
58
65
  private
59
66
 
60
- def run_list_command(context)
61
- yarn_list = YARN_LIST_COMMAND + YARN_LIST_PARAMETERS
62
- npm_list = NPM_LIST_COMMAND + NPM_LIST_PARAMETERS
63
-
64
- result, _error, _status = ShopifyCli::JsSystem.call(
65
- context,
66
- yarn: yarn_list,
67
- npm: npm_list,
68
- capture_response: true
69
- )
70
- # context.abort(
71
- # context.message("features.argo.dependencies.argo_missing_renderer_package_error", error)
72
- # ) unless status.success?
73
- result
74
- end
75
-
76
67
  def run_yarn_install(context, js_system)
77
68
  _result, error, status = js_system.call(
78
69
  yarn: YARN_INSTALL_COMMAND + YARN_INSTALL_PARAMETERS,
@@ -0,0 +1,63 @@
1
+ module Extension
2
+ module Features
3
+ class ArgoRuntime
4
+ include SmartProperties
5
+
6
+ ARGO_RUN_PACKAGE_NAME = "@shopify/argo-run"
7
+ ARGO_ADMIN_CLI_PACKAGE_NAME = "@shopify/argo-admin-cli"
8
+
9
+ ARGO_RUN_0_4_0 = Models::NpmPackage.new(name: "@shopify/argo-run", version: "0.4.0")
10
+ ARGO_ADMIN_CLI_0_9_3 = Models::NpmPackage.new(name: "@shopify/argo-admin-cli", version: "0.9.3")
11
+ ARGO_ADMIN_CLI_0_11_0 = Models::NpmPackage.new(name: "@shopify/argo-admin-cli", version: "0.11.0")
12
+
13
+ property! :renderer, accepts: Models::NpmPackage
14
+ property! :cli, accepts: Models::NpmPackage
15
+
16
+ def accepts_port?
17
+ case cli
18
+ when admin?
19
+ cli >= ARGO_ADMIN_CLI_0_11_0
20
+ when checkout?
21
+ cli >= ARGO_RUN_0_4_0
22
+ end
23
+ end
24
+
25
+ def accepts_tunnel_url?
26
+ case cli
27
+ when admin?
28
+ cli >= ARGO_ADMIN_CLI_0_11_0
29
+ when checkout?
30
+ cli >= ARGO_RUN_0_4_0
31
+ end
32
+ end
33
+
34
+ def accepts_uuid?
35
+ case cli
36
+ when admin?
37
+ cli >= ARGO_ADMIN_CLI_0_11_0
38
+ else
39
+ false
40
+ end
41
+ end
42
+
43
+ def accepts_argo_version?
44
+ case cli
45
+ when admin?
46
+ cli >= ARGO_ADMIN_CLI_0_9_3
47
+ else
48
+ false
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def admin?
55
+ ->(cli) { cli.name == ARGO_ADMIN_CLI_PACKAGE_NAME }
56
+ end
57
+
58
+ def checkout?
59
+ ->(cli) { cli.name == ARGO_RUN_PACKAGE_NAME }
60
+ end
61
+ end
62
+ end
63
+ end
@@ -4,33 +4,62 @@ module Extension
4
4
  include SmartProperties
5
5
 
6
6
  property! :specification_handler, accepts: Extension::Models::SpecificationHandlers::Default
7
+ property! :argo_runtime, accepts: Features::ArgoRuntime
7
8
  property! :context, accepts: ShopifyCli::Context
8
-
9
- YARN_SERVE_COMMAND = %w(server)
10
- NPM_SERVE_COMMAND = %w(run-script server)
9
+ property! :port, accepts: Integer, default: 39351
10
+ property :tunnel_url, accepts: String, default: ""
11
11
 
12
12
  def call
13
13
  validate_env!
14
14
 
15
15
  CLI::UI::Frame.open(context.message("serve.frame_title")) do
16
- success = ShopifyCli::JsSystem.call(context, yarn: yarn_serve_command, npm: npm_serve_command)
16
+ success = call_js_system(yarn_command: yarn_serve_command, npm_command: npm_serve_command)
17
17
  context.abort(context.message("serve.serve_failure_message")) unless success
18
18
  end
19
19
  end
20
20
 
21
21
  private
22
22
 
23
+ def call_js_system(yarn_command:, npm_command:)
24
+ ShopifyCli::JsSystem.call(context, yarn: yarn_command, npm: npm_command)
25
+ end
26
+
23
27
  def specification
24
28
  specification_handler.specification
25
29
  end
26
30
 
31
+ def renderer_package
32
+ specification_handler.renderer_package(context)
33
+ end
34
+
35
+ def required_fields
36
+ specification.features.argo.required_fields
37
+ end
38
+
39
+ def serve_options
40
+ @options ||= Features::ArgoServeOptions.new(
41
+ argo_runtime: argo_runtime,
42
+ port: port,
43
+ context: context,
44
+ required_fields: required_fields,
45
+ renderer_package: renderer_package,
46
+ public_url: tunnel_url
47
+ )
48
+ end
49
+
50
+ def yarn_serve_command
51
+ serve_options.yarn_serve_command
52
+ end
53
+
54
+ def npm_serve_command
55
+ serve_options.npm_serve_command
56
+ end
57
+
27
58
  def validate_env!
28
59
  ExtensionProject.reload
29
60
 
30
61
  ShopifyCli::Shopifolk.check && ShopifyCli::Feature.enabled?(:argo_admin_beta)
31
62
 
32
- required_fields = specification.features.argo.required_fields
33
-
34
63
  return if required_fields.none?
35
64
 
36
65
  ShopifyCli::Tasks::EnsureEnv.call(context, required: required_fields)
@@ -45,25 +74,6 @@ module Extension
45
74
 
46
75
  context.abort(context.message("serve.serve_missing_information"))
47
76
  end
48
-
49
- def yarn_serve_command
50
- YARN_SERVE_COMMAND + serve_options(specification.features.argo.required_fields)
51
- end
52
-
53
- def npm_serve_command
54
- NPM_SERVE_COMMAND + ["--"] + serve_options(specification.features.argo.required_fields)
55
- end
56
-
57
- def serve_options(required_fields)
58
- renderer_package = specification_handler.renderer_package(context)
59
- project = ExtensionProject.current
60
- @serve_options ||= [].tap do |options|
61
- options << "--shop=#{project.env.shop}" if required_fields.include?(:shop)
62
- options << "--apiKey=#{project.env.api_key}" if required_fields.include?(:api_key)
63
- options << "--argoVersion=#{renderer_package.version}" if renderer_package.admin?
64
- options << "--uuid=#{project.registration_uuid}" if renderer_package.supports_uuid_flag?
65
- end
66
- end
67
77
  end
68
78
  end
69
79
  end
@@ -0,0 +1,40 @@
1
+ module Extension
2
+ module Features
3
+ class ArgoServeOptions
4
+ include SmartProperties
5
+
6
+ property! :argo_runtime, accepts: Features::ArgoRuntime
7
+ property! :context, accepts: ShopifyCli::Context
8
+ property :port, accepts: Integer, default: 39351
9
+ property :public_url, accepts: String, default: ""
10
+ property! :required_fields, accepts: Array, default: -> { [] }
11
+ property! :renderer_package, accepts: Models::NpmPackage
12
+
13
+ YARN_SERVE_COMMAND = %w(server)
14
+ NPM_SERVE_COMMAND = %w(run-script server)
15
+
16
+ def yarn_serve_command
17
+ YARN_SERVE_COMMAND + options
18
+ end
19
+
20
+ def npm_serve_command
21
+ NPM_SERVE_COMMAND + ["--"] + options
22
+ end
23
+
24
+ private
25
+
26
+ def options
27
+ project = ExtensionProject.current
28
+
29
+ @serve_options ||= [].tap do |options|
30
+ options << "--port=#{port}" if argo_runtime.accepts_port?
31
+ options << "--shop=#{project.env.shop}" if required_fields.include?(:shop)
32
+ options << "--apiKey=#{project.env.api_key}" if required_fields.include?(:api_key)
33
+ options << "--argoVersion=#{renderer_package.version}" if argo_runtime.accepts_argo_version?
34
+ options << "--uuid=#{project.registration_uuid}" if argo_runtime.accepts_uuid?
35
+ options << "--publicUrl=#{public_url}" if argo_runtime.accepts_tunnel_url?
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end