shopify-cli 2.2.2 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (267) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/ISSUE_TEMPLATE.md +0 -4
  4. data/.github/workflows/shopify.yml +104 -0
  5. data/.gitignore +3 -0
  6. data/.rubocop.yml +14 -14
  7. data/.rubocop_todo.yml +3 -3
  8. data/CHANGELOG.md +30 -0
  9. data/CONTRIBUTING.md +23 -0
  10. data/Dockerfile +17 -0
  11. data/Gemfile +1 -0
  12. data/Gemfile.lock +67 -24
  13. data/RELEASING.md +1 -1
  14. data/Rakefile +75 -18
  15. data/bin/console +11 -0
  16. data/bin/shopify +16 -4
  17. data/dev.yml +14 -1
  18. data/ext/shopify-cli/extconf.rb +2 -0
  19. data/ext/shopify-extensions/extconf.rb +21 -0
  20. data/ext/shopify-extensions/shopify_extensions.rb +152 -0
  21. data/ext/shopify-extensions/version +1 -0
  22. data/lib/project_types/extension/cli.rb +19 -3
  23. data/lib/project_types/extension/commands/build.rb +32 -3
  24. data/lib/project_types/extension/commands/check.rb +2 -2
  25. data/lib/project_types/extension/commands/connect.rb +1 -1
  26. data/lib/project_types/extension/commands/create.rb +59 -16
  27. data/lib/project_types/extension/commands/extension_command.rb +1 -1
  28. data/lib/project_types/extension/commands/info.rb +1 -1
  29. data/lib/project_types/extension/commands/push.rb +1 -1
  30. data/lib/project_types/extension/commands/register.rb +2 -2
  31. data/lib/project_types/extension/commands/serve.rb +5 -5
  32. data/lib/project_types/extension/commands/tunnel.rb +6 -6
  33. data/lib/project_types/extension/extension_project.rb +4 -4
  34. data/lib/project_types/extension/features/argo.rb +3 -3
  35. data/lib/project_types/extension/features/argo_config.rb +5 -5
  36. data/lib/project_types/extension/features/argo_serve.rb +21 -6
  37. data/lib/project_types/extension/features/argo_setup.rb +1 -1
  38. data/lib/project_types/extension/features/argo_setup_step.rb +1 -1
  39. data/lib/project_types/extension/features/argo_setup_steps.rb +2 -2
  40. data/lib/project_types/extension/forms/connect.rb +2 -2
  41. data/lib/project_types/extension/forms/create.rb +6 -3
  42. data/lib/project_types/extension/forms/questions/ask_app.rb +2 -2
  43. data/lib/project_types/extension/forms/questions/ask_name.rb +1 -1
  44. data/lib/project_types/extension/forms/questions/ask_registration.rb +2 -2
  45. data/lib/project_types/extension/forms/questions/ask_template.rb +44 -0
  46. data/lib/project_types/extension/forms/questions/ask_type.rb +2 -2
  47. data/lib/project_types/extension/messages/message_loading.rb +2 -2
  48. data/lib/project_types/extension/messages/messages.rb +3 -0
  49. data/lib/project_types/extension/models/development_server.rb +78 -0
  50. data/lib/project_types/extension/models/development_server_requirements.rb +35 -0
  51. data/lib/project_types/extension/models/lazy_specification_handler.rb +1 -1
  52. data/lib/project_types/extension/models/server_config/base.rb +31 -0
  53. data/lib/project_types/extension/models/server_config/development.rb +23 -0
  54. data/lib/project_types/extension/models/server_config/development_entries.rb +38 -0
  55. data/lib/project_types/extension/models/server_config/development_renderer.rb +30 -0
  56. data/lib/project_types/extension/models/server_config/extension.rb +35 -0
  57. data/lib/project_types/extension/models/server_config/root.rb +18 -0
  58. data/lib/project_types/extension/models/server_config/user.rb +10 -0
  59. data/lib/project_types/extension/models/specification.rb +1 -1
  60. data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +1 -1
  61. data/lib/project_types/extension/models/specification_handlers/default.rb +14 -2
  62. data/lib/project_types/extension/models/specification_handlers/theme_app_extension.rb +1 -1
  63. data/lib/project_types/extension/models/specifications.rb +4 -4
  64. data/lib/project_types/extension/tasks/choose_next_available_port.rb +2 -2
  65. data/lib/project_types/extension/tasks/configure_features.rb +1 -1
  66. data/lib/project_types/extension/tasks/configure_options.rb +1 -1
  67. data/lib/project_types/extension/tasks/converters/product_converter.rb +1 -1
  68. data/lib/project_types/extension/tasks/converters/server_config_converter.rb +31 -0
  69. data/lib/project_types/extension/tasks/create_extension.rb +2 -2
  70. data/lib/project_types/extension/tasks/fetch_specifications.rb +2 -2
  71. data/lib/project_types/extension/tasks/find_npm_packages.rb +5 -5
  72. data/lib/project_types/extension/tasks/get_app.rb +2 -2
  73. data/lib/project_types/extension/tasks/get_apps.rb +2 -2
  74. data/lib/project_types/extension/tasks/get_extensions.rb +2 -2
  75. data/lib/project_types/extension/tasks/get_product.rb +2 -2
  76. data/lib/project_types/extension/tasks/load_server_config.rb +23 -0
  77. data/lib/project_types/extension/tasks/run_extension_command.rb +81 -0
  78. data/lib/project_types/extension/tasks/update_draft.rb +2 -2
  79. data/lib/project_types/node/cli.rb +3 -3
  80. data/lib/project_types/node/commands/connect.rb +4 -4
  81. data/lib/project_types/node/commands/create.rb +10 -14
  82. data/lib/project_types/node/commands/deploy/heroku.rb +4 -4
  83. data/lib/project_types/node/commands/deploy.rb +3 -3
  84. data/lib/project_types/node/commands/generate.rb +2 -2
  85. data/lib/project_types/node/commands/open.rb +3 -3
  86. data/lib/project_types/node/commands/serve.rb +15 -7
  87. data/lib/project_types/node/commands/tunnel.rb +6 -6
  88. data/lib/project_types/node/forms/create.rb +3 -3
  89. data/lib/project_types/node/messages/messages.rb +3 -0
  90. data/lib/project_types/php/cli.rb +27 -0
  91. data/lib/project_types/php/commands/connect.rb +19 -0
  92. data/lib/project_types/php/commands/create.rb +143 -0
  93. data/lib/project_types/php/commands/deploy/heroku.rb +129 -0
  94. data/lib/project_types/php/commands/deploy.rb +32 -0
  95. data/lib/project_types/php/commands/open.rb +16 -0
  96. data/lib/project_types/php/commands/serve.rb +51 -0
  97. data/lib/project_types/php/commands/tunnel.rb +37 -0
  98. data/lib/project_types/php/forms/create.rb +45 -0
  99. data/lib/project_types/php/messages/messages.rb +191 -0
  100. data/lib/project_types/rails/cli.rb +3 -3
  101. data/lib/project_types/rails/commands/connect.rb +4 -4
  102. data/lib/project_types/rails/commands/create.rb +12 -16
  103. data/lib/project_types/rails/commands/deploy/heroku.rb +4 -4
  104. data/lib/project_types/rails/commands/deploy.rb +3 -3
  105. data/lib/project_types/rails/commands/generate/webhook.rb +3 -3
  106. data/lib/project_types/rails/commands/generate.rb +3 -3
  107. data/lib/project_types/rails/commands/open.rb +3 -3
  108. data/lib/project_types/rails/commands/serve.rb +8 -8
  109. data/lib/project_types/rails/commands/tunnel.rb +6 -6
  110. data/lib/project_types/rails/forms/create.rb +3 -3
  111. data/lib/project_types/rails/gem.rb +1 -1
  112. data/lib/project_types/rails/ruby.rb +1 -1
  113. data/lib/project_types/script/cli.rb +16 -6
  114. data/lib/project_types/script/commands/create.rb +4 -2
  115. data/lib/project_types/script/commands/push.rb +2 -2
  116. data/lib/project_types/script/config/extension_points.yml +30 -29
  117. data/lib/project_types/script/forms/create.rb +1 -1
  118. data/lib/project_types/script/layers/application/create_script.rb +32 -12
  119. data/lib/project_types/script/layers/application/extension_points.rb +4 -4
  120. data/lib/project_types/script/layers/application/push_script.rb +13 -1
  121. data/lib/project_types/script/layers/domain/extension_point.rb +13 -45
  122. data/lib/project_types/script/layers/domain/push_package.rb +0 -12
  123. data/lib/project_types/script/layers/domain/script_project.rb +2 -2
  124. data/lib/project_types/script/layers/infrastructure/api_clients/partners_proxy_api_client.rb +57 -0
  125. data/lib/project_types/script/layers/infrastructure/api_clients/script_service_api_client.rb +35 -0
  126. data/lib/project_types/script/layers/infrastructure/command_runner.rb +1 -1
  127. data/lib/project_types/script/layers/infrastructure/errors.rb +5 -0
  128. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +10 -90
  129. data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +76 -11
  130. data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +1 -1
  131. data/lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb +33 -0
  132. data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +105 -0
  133. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +1 -1
  134. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +6 -6
  135. data/lib/project_types/script/layers/infrastructure/script_service.rb +25 -144
  136. data/lib/project_types/script/layers/infrastructure/script_uploader.rb +27 -0
  137. data/lib/project_types/script/layers/infrastructure/service_locator.rb +20 -0
  138. data/lib/project_types/script/messages/messages.rb +4 -0
  139. data/lib/project_types/script/tasks/ensure_env.rb +7 -7
  140. data/lib/project_types/script/ui/error_handler.rb +84 -76
  141. data/lib/project_types/script/ui/printing_spinner.rb +1 -1
  142. data/lib/project_types/theme/cli.rb +3 -3
  143. data/lib/project_types/theme/commands/check.rb +3 -3
  144. data/lib/project_types/theme/commands/delete.rb +7 -7
  145. data/lib/project_types/theme/commands/init.rb +3 -3
  146. data/lib/project_types/theme/commands/language_server.rb +2 -2
  147. data/lib/project_types/theme/commands/package.rb +2 -2
  148. data/lib/project_types/theme/commands/publish.rb +5 -5
  149. data/lib/project_types/theme/commands/pull.rb +15 -9
  150. data/lib/project_types/theme/commands/push.rb +18 -12
  151. data/lib/project_types/theme/commands/serve.rb +4 -4
  152. data/lib/project_types/theme/forms/confirm_store.rb +1 -1
  153. data/lib/project_types/theme/forms/select.rb +2 -2
  154. data/lib/{shopify-cli → shopify_cli}/admin_api/populate_resource_command.rb +3 -3
  155. data/lib/{shopify-cli → shopify_cli}/admin_api/schema.rb +4 -4
  156. data/lib/{shopify-cli → shopify_cli}/admin_api.rb +27 -27
  157. data/lib/{shopify-cli → shopify_cli}/api.rb +8 -8
  158. data/lib/shopify_cli/command/app_sub_command.rb +16 -0
  159. data/lib/{shopify-cli → shopify_cli}/command.rb +3 -3
  160. data/lib/{shopify-cli → shopify_cli}/commands/config.rb +14 -14
  161. data/lib/{shopify-cli → shopify_cli}/commands/help.rb +4 -4
  162. data/lib/{shopify-cli → shopify_cli}/commands/login.rb +7 -7
  163. data/lib/shopify_cli/commands/logout.rb +39 -0
  164. data/lib/{shopify-cli → shopify_cli}/commands/populate/customer.rb +4 -4
  165. data/lib/{shopify-cli → shopify_cli}/commands/populate/draft_order.rb +4 -4
  166. data/lib/{shopify-cli → shopify_cli}/commands/populate/product.rb +4 -4
  167. data/lib/shopify_cli/commands/populate.rb +23 -0
  168. data/lib/shopify_cli/commands/store.rb +15 -0
  169. data/lib/{shopify-cli → shopify_cli}/commands/switch.rb +5 -5
  170. data/lib/{shopify-cli → shopify_cli}/commands/system.rb +10 -10
  171. data/lib/shopify_cli/commands/version.rb +15 -0
  172. data/lib/{shopify-cli → shopify_cli}/commands/whoami.rb +7 -7
  173. data/lib/shopify_cli/commands.rb +34 -0
  174. data/lib/{shopify-cli → shopify_cli}/connect.rb +3 -3
  175. data/lib/shopify_cli/constants.rb +54 -0
  176. data/lib/{shopify-cli → shopify_cli}/context.rb +6 -6
  177. data/lib/{shopify-cli → shopify_cli}/core/entry_point.rb +7 -7
  178. data/lib/{shopify-cli → shopify_cli}/core/executor.rb +8 -4
  179. data/lib/{shopify-cli → shopify_cli}/core/finalize.rb +1 -1
  180. data/lib/{shopify-cli → shopify_cli}/core/help_resolver.rb +2 -2
  181. data/lib/{shopify-cli → shopify_cli}/core/monorail.rb +8 -8
  182. data/lib/shopify_cli/core.rb +8 -0
  183. data/lib/{shopify-cli → shopify_cli}/db.rb +8 -8
  184. data/lib/shopify_cli/environment.rb +91 -0
  185. data/lib/shopify_cli/exception_reporter/permission_controller.rb +54 -0
  186. data/lib/shopify_cli/exception_reporter.rb +55 -0
  187. data/lib/{shopify-cli → shopify_cli}/feature.rb +8 -8
  188. data/lib/{shopify-cli → shopify_cli}/form.rb +2 -2
  189. data/lib/{shopify-cli → shopify_cli}/git.rb +38 -8
  190. data/lib/{shopify-cli → shopify_cli}/helpers/haikunator.rb +1 -1
  191. data/lib/shopify_cli/helpers.rb +5 -0
  192. data/lib/{shopify-cli → shopify_cli}/heroku.rb +38 -13
  193. data/lib/{shopify-cli → shopify_cli}/http_request.rb +1 -1
  194. data/lib/{shopify-cli → shopify_cli}/identity_auth/servlet.rb +1 -1
  195. data/lib/{shopify-cli → shopify_cli}/identity_auth.rb +24 -31
  196. data/lib/{shopify-cli → shopify_cli}/js_deps.rb +7 -7
  197. data/lib/{shopify-cli → shopify_cli}/js_system.rb +10 -10
  198. data/lib/{shopify-cli → shopify_cli}/lazy_delegator.rb +2 -2
  199. data/lib/{shopify-cli → shopify_cli}/messages/messages.rb +44 -2
  200. data/lib/{shopify-cli → shopify_cli}/method_object.rb +15 -8
  201. data/lib/shopify_cli/migrator/migration.rb +27 -0
  202. data/lib/shopify_cli/migrator/migrations/1631709766_noop.rb +13 -0
  203. data/lib/shopify_cli/migrator.rb +48 -0
  204. data/lib/{shopify-cli → shopify_cli}/options.rb +1 -1
  205. data/lib/{shopify-cli → shopify_cli}/packager.rb +8 -8
  206. data/lib/{shopify-cli → shopify_cli}/partners_api/organizations.rb +1 -1
  207. data/lib/{shopify-cli → shopify_cli}/partners_api.rb +16 -40
  208. data/lib/shopify_cli/php_deps.rb +102 -0
  209. data/lib/{shopify-cli → shopify_cli}/process_supervision.rb +23 -21
  210. data/lib/{shopify-cli → shopify_cli}/project.rb +15 -15
  211. data/lib/{shopify-cli → shopify_cli}/project_commands.rb +3 -3
  212. data/lib/{shopify-cli → shopify_cli}/project_type.rb +5 -5
  213. data/lib/{shopify-cli → shopify_cli}/resolve_constant.rb +5 -5
  214. data/lib/{shopify-cli → shopify_cli}/resources/env_file.rb +1 -1
  215. data/lib/shopify_cli/resources.rb +5 -0
  216. data/lib/{shopify-cli → shopify_cli}/result.rb +11 -11
  217. data/lib/{shopify-cli → shopify_cli}/shopifolk.rb +6 -6
  218. data/lib/{shopify-cli → shopify_cli}/sub_command.rb +1 -1
  219. data/lib/{shopify-cli → shopify_cli}/task.rb +1 -1
  220. data/lib/{shopify-cli → shopify_cli}/tasks/confirm_store.rb +3 -3
  221. data/lib/{shopify-cli → shopify_cli}/tasks/create_api_client.rb +4 -4
  222. data/lib/shopify_cli/tasks/ensure_authenticated.rb +13 -0
  223. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_dev_store.rb +5 -5
  224. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_env.rb +3 -3
  225. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_loopback_url.rb +4 -4
  226. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_project_type.rb +3 -3
  227. data/lib/{shopify-cli → shopify_cli}/tasks/select_org_and_shop.rb +8 -8
  228. data/lib/{shopify-cli → shopify_cli}/tasks/update_dashboard_urls.rb +6 -6
  229. data/lib/{shopify-cli → shopify_cli}/tasks.rb +10 -10
  230. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/certificate_manager.rb +5 -5
  231. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/header_hash.rb +5 -1
  232. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/hot-reload.js +0 -0
  233. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/hot_reload.rb +5 -6
  234. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/local_assets.rb +1 -1
  235. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/proxy.rb +15 -3
  236. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/sse.rb +1 -1
  237. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/watcher.rb +1 -1
  238. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/web_server.rb +1 -1
  239. data/lib/{shopify-cli → shopify_cli}/theme/dev_server.rb +3 -3
  240. data/lib/shopify_cli/theme/development_theme.rb +83 -0
  241. data/lib/{shopify-cli → shopify_cli}/theme/file.rb +12 -4
  242. data/lib/{shopify-cli → shopify_cli}/theme/ignore_filter.rb +8 -1
  243. data/lib/{shopify-cli → shopify_cli}/theme/mime_type.rb +1 -1
  244. data/lib/{shopify-cli → shopify_cli}/theme/syncer.rb +7 -7
  245. data/lib/{shopify-cli → shopify_cli}/theme/theme.rb +4 -4
  246. data/lib/{shopify-cli → shopify_cli}/transform_data_structure.rb +4 -4
  247. data/lib/{shopify-cli → shopify_cli}/tunnel.rb +14 -14
  248. data/lib/shopify_cli/version.rb +3 -0
  249. data/lib/shopify_cli.rb +61 -50
  250. data/shopify-cli.gemspec +13 -5
  251. data/utilities/docker.rb +47 -0
  252. data/utilities/utilities.rb +5 -0
  253. metadata +155 -97
  254. data/.github/workflows/build.yml +0 -28
  255. data/lib/project_types/script/layers/infrastructure/languages/rust_project_creator.rb +0 -73
  256. data/lib/project_types/script/layers/infrastructure/languages/rust_task_runner.rb +0 -60
  257. data/lib/shopify-cli/commands/logout.rb +0 -39
  258. data/lib/shopify-cli/commands/populate.rb +0 -23
  259. data/lib/shopify-cli/commands/store.rb +0 -15
  260. data/lib/shopify-cli/commands/version.rb +0 -15
  261. data/lib/shopify-cli/commands.rb +0 -34
  262. data/lib/shopify-cli/core.rb +0 -8
  263. data/lib/shopify-cli/helpers.rb +0 -5
  264. data/lib/shopify-cli/resources.rb +0 -5
  265. data/lib/shopify-cli/tasks/ensure_authenticated.rb +0 -13
  266. data/lib/shopify-cli/theme/development_theme.rb +0 -69
  267. data/lib/shopify-cli/version.rb +0 -3
@@ -0,0 +1,91 @@
1
+ module ShopifyCLI
2
+ # The environment module provides an interface to get information from
3
+ # the environment in which the CLI runs
4
+ module Environment
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
+
18
+ def self.use_local_partners_instance?(env_variables: ENV)
19
+ env_variable_truthy?(
20
+ Constants::EnvironmentVariables::LOCAL_PARTNERS,
21
+ env_variables: env_variables
22
+ )
23
+ end
24
+
25
+ def self.print_stacktrace?(env_variables: ENV)
26
+ env_variable_truthy?(
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,
42
+ env_variables: env_variables
43
+ )
44
+ end
45
+
46
+ def self.use_spin_partners_instance?(env_variables: ENV)
47
+ env_variable_truthy?(
48
+ Constants::EnvironmentVariables::SPIN_PARTNERS,
49
+ env_variables: env_variables
50
+ )
51
+ end
52
+
53
+ def self.partners_domain(env_variables: ENV)
54
+ if use_local_partners_instance?(env_variables: env_variables)
55
+ "partners.myshopify.io"
56
+ elsif use_spin_partners_instance?(env_variables: env_variables)
57
+ "partners.#{spin_url(env_variables: env_variables)}"
58
+ else
59
+ "partners.shopify.com"
60
+ end
61
+ end
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
+
68
+ def self.spin_url(env_variables: ENV)
69
+ spin_workspace = spin_workspace(env_variables: env_variables)
70
+ spin_namespace = spin_namespace(env_variables: env_variables)
71
+ spin_host = spin_host(env_variables: env_variables)
72
+ "#{spin_workspace}.#{spin_namespace}.#{spin_host}"
73
+ end
74
+
75
+ def self.env_variable_truthy?(variable_name, env_variables: ENV)
76
+ TRUTHY_ENV_VARIABLE_VALUES.include?(env_variables[variable_name.to_s])
77
+ end
78
+
79
+ def self.spin_workspace(env_variables: ENV)
80
+ env_variables[Constants::EnvironmentVariables::SPIN_WORKSPACE]
81
+ end
82
+
83
+ def self.spin_namespace(env_variables: ENV)
84
+ env_variables[Constants::EnvironmentVariables::SPIN_NAMESPACE]
85
+ end
86
+
87
+ def self.spin_host(env_variables: ENV)
88
+ env_variables[Constants::EnvironmentVariables::SPIN_HOST] || "us.spin.dev"
89
+ end
90
+ end
91
+ end
@@ -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
@@ -1,6 +1,6 @@
1
- module ShopifyCli
1
+ module ShopifyCLI
2
2
  ##
3
- # ShopifyCli::Feature contains the logic to hide and show features across the CLI
3
+ # ShopifyCLI::Feature contains the logic to hide and show features across the CLI
4
4
  # These features can be either commands or project types currently.
5
5
  #
6
6
  # Feature flags will persist between runs so if the flag is enabled or disabled,
@@ -9,7 +9,7 @@ module ShopifyCli
9
9
  SECTION = "features"
10
10
 
11
11
  ##
12
- # ShopifyCli::Feature::Set is included on commands and projects to allow you to hide
12
+ # ShopifyCLI::Feature::Set is included on commands and projects to allow you to hide
13
13
  # and enable projects and commands based on feature flags.
14
14
  module Set
15
15
  ##
@@ -21,9 +21,9 @@ module ShopifyCli
21
21
  #
22
22
  # #### Example
23
23
  #
24
- # module ShopifyCli
24
+ # module ShopifyCLI
25
25
  # module Commands
26
- # class Config < ShopifyCli::Command
26
+ # class Config < ShopifyCLI::Command
27
27
  # hidden_feature(feature_set: :basic)
28
28
  # ....
29
29
  #
@@ -41,7 +41,7 @@ module ShopifyCli
41
41
  #
42
42
  # #### Example
43
43
  #
44
- # ShopifyCli::Commands::Config.hidden?
44
+ # ShopifyCLI::Commands::Config.hidden?
45
45
  #
46
46
  def hidden?
47
47
  enabled = (@hidden_feature_set || []).any? do |feature|
@@ -84,11 +84,11 @@ module ShopifyCli
84
84
  # * `is_enabled` - will be true if the feature has been enabled.
85
85
  def enabled?(feature)
86
86
  return false if feature.nil?
87
- ShopifyCli::Config.get_bool(SECTION, feature.to_s)
87
+ ShopifyCLI::Config.get_bool(SECTION, feature.to_s)
88
88
  end
89
89
 
90
90
  def set(feature, value)
91
- ShopifyCli::Config.set(SECTION, feature.to_s, value)
91
+ ShopifyCLI::Config.set(SECTION, feature.to_s, value)
92
92
  end
93
93
  end
94
94
  end
@@ -1,6 +1,6 @@
1
1
  require "shopify_cli"
2
2
 
3
- module ShopifyCli
3
+ module ShopifyCLI
4
4
  class Form
5
5
  class << self
6
6
  def ask(ctx, args, flags)
@@ -12,7 +12,7 @@ module ShopifyCli
12
12
  begin
13
13
  form.ask
14
14
  form
15
- rescue ShopifyCli::Abort => err
15
+ rescue ShopifyCLI::Abort => err
16
16
  ctx.puts(err.message)
17
17
  nil
18
18
  end
@@ -1,6 +1,6 @@
1
- module ShopifyCli
1
+ module ShopifyCLI
2
2
  ##
3
- # ShopifyCli::Git wraps git functionality to make it easier to integrate will
3
+ # ShopifyCLI::Git wraps git functionality to make it easier to integrate will
4
4
  # git.
5
5
  class Git
6
6
  class << self
@@ -18,7 +18,7 @@ module ShopifyCli
18
18
  #
19
19
  # #### Example
20
20
  #
21
- # ShopifyCli::Git.sha
21
+ # ShopifyCLI::Git.sha
22
22
  #
23
23
  def sha(dir: Dir.pwd, ctx: Context.new)
24
24
  rev_parse("HEAD", dir: dir, ctx: ctx)
@@ -40,7 +40,7 @@ module ShopifyCli
40
40
  #
41
41
  # #### Example
42
42
  #
43
- # ShopifyCli::Git.clone('git@github.com:shopify/test.git', 'test-app')
43
+ # ShopifyCLI::Git.clone('git@github.com:shopify/test.git', 'test-app')
44
44
  #
45
45
  def clone(repository, dest, ctx: Context.new)
46
46
  if Dir.exist?(dest)
@@ -66,7 +66,7 @@ module ShopifyCli
66
66
  #
67
67
  # #### Example
68
68
  #
69
- # branches = ShopifyCli::Git.branches(@ctx)
69
+ # branches = ShopifyCLI::Git.branches(@ctx)
70
70
  #
71
71
  def branches(ctx)
72
72
  output, status = ctx.capture2e("git", "branch", "--list", "--format=%(refname:short)")
@@ -91,7 +91,7 @@ module ShopifyCli
91
91
  #
92
92
  # #### Example
93
93
  #
94
- # ShopifyCli::Git.init(@ctx)
94
+ # ShopifyCLI::Git.init(@ctx)
95
95
  #
96
96
  def init(ctx)
97
97
  output, status = ctx.capture2e("git", "status")
@@ -105,11 +105,41 @@ 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)
111
- args = %w(git) + args
112
- out, _, stat = ctx.capture3(*args, chdir: dir)
141
+ args = %w(git) + ["--git-dir", File.join(dir, ".git")] + args
142
+ out, _, stat = ctx.capture3(*args)
113
143
  return default unless stat.success?
114
144
  out.chomp
115
145
  end
@@ -23,7 +23,7 @@
23
23
 
24
24
  require "securerandom"
25
25
 
26
- module ShopifyCli
26
+ module ShopifyCLI
27
27
  module Helpers
28
28
  module Haikunator
29
29
  class << self
@@ -0,0 +1,5 @@
1
+ module ShopifyCLI
2
+ module Helpers
3
+ autoload :Haikunator, "shopify_cli/helpers/haikunator"
4
+ end
5
+ end
@@ -1,4 +1,4 @@
1
- module ShopifyCli
1
+ module ShopifyCLI
2
2
  class Heroku
3
3
  DOWNLOAD_URLS = {
4
4
  linux: "https://cli-assets.heroku.com/heroku-linux-x64.tar.gz",
@@ -36,7 +36,7 @@ module ShopifyCli
36
36
  def download
37
37
  return if installed?
38
38
 
39
- result = @ctx.system("curl", "-o", download_path, DOWNLOAD_URLS[@ctx.os], chdir: ShopifyCli.cache_dir)
39
+ result = @ctx.system("curl", "-o", download_path, DOWNLOAD_URLS[@ctx.os], chdir: ShopifyCLI.cache_dir)
40
40
  @ctx.abort(@ctx.message("core.heroku.error.download")) unless result.success?
41
41
  @ctx.abort(@ctx.message("core.heroku.error.download")) unless File.exist?(download_path)
42
42
  end
@@ -47,7 +47,7 @@ module ShopifyCli
47
47
  result = if @ctx.windows?
48
48
  @ctx.system("\"#{download_path}\"")
49
49
  else
50
- @ctx.system("tar", "-xf", download_path, chdir: ShopifyCli.cache_dir)
50
+ @ctx.system("tar", "-xf", download_path, chdir: ShopifyCLI.cache_dir)
51
51
  end
52
52
  @ctx.abort(@ctx.message("core.heroku.error.install")) unless result.success?
53
53
 
@@ -67,23 +67,33 @@ module ShopifyCli
67
67
  nil
68
68
  end
69
69
 
70
- private
71
-
72
- def download_filename
73
- URI.parse(DOWNLOAD_URLS[@ctx.os]).path.split("/").last
70
+ def get_config(config)
71
+ output, status = @ctx.capture2e(heroku_command, "config:get", config.to_s)
72
+ return output.strip if status.success?
73
+ nil
74
74
  end
75
75
 
76
- def download_path
77
- File.join(ShopifyCli.cache_dir, download_filename)
76
+ def set_config(config, value)
77
+ result = @ctx.system(heroku_command, "config:set", "#{config}=#{value}")
78
+
79
+ msg = @ctx.message("core.heroku.error.set_config", config, value)
80
+ @ctx.abort(msg) unless result.success?
78
81
  end
79
82
 
80
- def git_remote
81
- output, status = @ctx.capture2e("git", "remote", "get-url", "heroku")
82
- status.success? ? output : nil
83
+ def add_buildpacks(buildpacks)
84
+ result = @ctx.system(heroku_command, "buildpacks:clear")
85
+ msg = @ctx.message("core.heroku.error.add_buildpacks")
86
+ @ctx.abort(msg) unless result.success?
87
+
88
+ buildpacks.each do |buildpack|
89
+ result = @ctx.system(heroku_command, "buildpacks:add", buildpack)
90
+ msg = @ctx.message("core.heroku.error.add_buildpacks")
91
+ @ctx.abort(msg) unless result.success?
92
+ end
83
93
  end
84
94
 
85
95
  def heroku_command
86
- local_path = File.join(ShopifyCli.cache_dir, "heroku", "bin", "heroku").to_s
96
+ local_path = File.join(ShopifyCLI.cache_dir, "heroku", "bin", "heroku").to_s
87
97
  if File.exist?(local_path)
88
98
  local_path
89
99
  elsif @ctx.windows?
@@ -103,6 +113,21 @@ module ShopifyCli
103
113
  end
104
114
  end
105
115
 
116
+ private
117
+
118
+ def download_filename
119
+ URI.parse(DOWNLOAD_URLS[@ctx.os]).path.split("/").last
120
+ end
121
+
122
+ def download_path
123
+ File.join(ShopifyCLI.cache_dir, download_filename)
124
+ end
125
+
126
+ def git_remote
127
+ output, status = @ctx.capture2e("git", "remote", "get-url", "heroku")
128
+ status.success? ? output : nil
129
+ end
130
+
106
131
  def installed?
107
132
  _output, status = @ctx.capture2e(heroku_command, "--version")
108
133
  status.success?
@@ -1,7 +1,7 @@
1
1
  require "net/http"
2
2
  require "openssl"
3
3
 
4
- module ShopifyCli
4
+ module ShopifyCLI
5
5
  class HttpRequest
6
6
  class << self
7
7
  def post(uri, body, headers)
@@ -1,4 +1,4 @@
1
- module ShopifyCli
1
+ module ShopifyCLI
2
2
  class IdentityAuth
3
3
  class Servlet < WEBrick::HTTPServlet::AbstractServlet
4
4
  TEMPLATE = %{<!DOCTYPE html>
@@ -8,16 +8,15 @@ require "shopify_cli"
8
8
  require "uri"
9
9
  require "webrick"
10
10
 
11
- module ShopifyCli
11
+ module ShopifyCLI
12
12
  class IdentityAuth
13
13
  include SmartProperties
14
14
 
15
- autoload :Servlet, "shopify-cli/identity_auth/servlet"
15
+ autoload :Servlet, "shopify_cli/identity_auth/servlet"
16
16
 
17
17
  class Error < StandardError; end
18
18
  class Timeout < StandardError; end
19
19
  LocalRequest = Struct.new(:method, :path, :query, :protocol)
20
- LOCAL_DEBUG = "SHOPIFY_APP_CLI_LOCAL_PARTNERS"
21
20
 
22
21
  DEFAULT_PORT = 3456
23
22
  REDIRECT_HOST = "http://127.0.0.1:#{DEFAULT_PORT}"
@@ -50,7 +49,7 @@ module ShopifyCli
50
49
  ]
51
50
 
52
51
  property! :ctx
53
- property :store, default: -> { ShopifyCli::DB.new }
52
+ property :store, default: -> { ShopifyCLI::DB.new }
54
53
  property :state_token, accepts: String, default: SecureRandom.hex(30)
55
54
  property :code_verifier, accepts: String, default: SecureRandom.hex(30)
56
55
 
@@ -71,7 +70,7 @@ module ShopifyCli
71
70
 
72
71
  def reauthenticate
73
72
  return if refresh_exchange_tokens || refresh_access_tokens
74
- ctx.abort(ctx.message("core.identity_auth.error.reauthenticate", ShopifyCli::TOOL_NAME))
73
+ ctx.abort(ctx.message("core.identity_auth.error.reauthenticate", ShopifyCLI::TOOL_NAME))
75
74
  end
76
75
 
77
76
  def code_challenge
@@ -94,8 +93,8 @@ module ShopifyCli
94
93
  end
95
94
 
96
95
  def self.delete_tokens_and_keys
97
- ShopifyCli::DB.del(*IDENTITY_ACCESS_TOKENS)
98
- ShopifyCli::DB.del(*EXCHANGE_TOKENS)
96
+ ShopifyCLI::DB.del(*IDENTITY_ACCESS_TOKENS)
97
+ ShopifyCLI::DB.del(*EXCHANGE_TOKENS)
99
98
  end
100
99
 
101
100
  private
@@ -213,7 +212,7 @@ module ShopifyCli
213
212
  https = Net::HTTP.new(uri.host, uri.port)
214
213
  https.use_ssl = true
215
214
  request = Net::HTTP::Post.new(uri.path)
216
- request["User-Agent"] = "Shopify CLI #{::ShopifyCli::VERSION}"
215
+ request["User-Agent"] = "Shopify CLI #{::ShopifyCLI::VERSION}"
217
216
  request.body = URI.encode_www_form(params)
218
217
  res = https.request(request)
219
218
  unless res.is_a?(Net::HTTPSuccess)
@@ -236,12 +235,17 @@ module ShopifyCli
236
235
  end
237
236
 
238
237
  def auth_url
239
- return "https://accounts.shopify.com/oauth" if ENV[LOCAL_DEBUG].nil?
240
- "https://identity.myshopify.io/oauth"
238
+ if Environment.use_local_partners_instance?
239
+ "https://identity.myshopify.io/oauth"
240
+ elsif Environment.use_spin_partners_instance?
241
+ "https://identity.#{Environment.spin_url}/oauth"
242
+ else
243
+ "https://accounts.shopify.com/oauth"
244
+ end
241
245
  end
242
246
 
243
247
  def client_id_for_application(application_name)
244
- client_ids = if ENV[LOCAL_DEBUG]
248
+ client_ids = if Environment.use_local_partners_instance? || Environment.use_spin_partners_instance?
245
249
  DEV_APPLICATION_CLIENT_IDS
246
250
  else
247
251
  APPLICATION_CLIENT_IDS
@@ -252,31 +256,20 @@ module ShopifyCli
252
256
 
253
257
  def scopes(additional_scopes = [])
254
258
  (["openid"] + additional_scopes).tap do |result|
255
- result << "employee" if ShopifyCli::Shopifolk.acting_as_shopify_organization?
259
+ result << "employee" if ShopifyCLI::Shopifolk.acting_as_shopify_organization?
256
260
  end.join(" ")
257
261
  end
258
262
 
259
263
  def client_id
260
- return "fbdb2649-e327-4907-8f67-908d24cfd7e3" if ENV[LOCAL_DEBUG].nil?
261
-
262
- ctx.abort(ctx.message("core.identity_auth.error.local_identity_not_running")) unless local_identity_running?
263
-
264
- # Fetch the client ID from the local Identity Dynamic Registration endpoint
265
- response = post_request("/client", {
266
- name: "shopify-cli-development",
267
- public_type: "native",
268
- })
269
-
270
- response["client_id"]
271
- end
272
-
273
- def local_identity_running?
274
- Net::HTTP.start("identity.myshopify.io", 443, use_ssl: true, open_timeout: 1, read_timeout: 10) do |http|
275
- req = Net::HTTP::Get.new(URI.join("https://identity.myshopify.io", "/services/ping"))
276
- http.request(req).is_a?(Net::HTTPSuccess)
264
+ if Environment.use_local_partners_instance? || Environment.use_spin_partners_instance?
265
+ Constants::Identity::CLIENT_ID_DEV
266
+ else
267
+ # In the future we might want to use Identity's dynamic
268
+ # registration. To migrate to a dynamic client ID we
269
+ # need to refactor some code that relies on a static
270
+ # value for the client
271
+ Constants::Identity::CLIENT_ID
277
272
  end
278
- rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::EHOSTDOWN, Errno::EADDRNOTAVAIL, Errno::ECONNREFUSED
279
- false
280
273
  end
281
274
  end
282
275
  end
@@ -1,17 +1,17 @@
1
1
  require "shopify_cli"
2
2
 
3
- module ShopifyCli
3
+ module ShopifyCLI
4
4
  ##
5
- # ShopifyCli::JsDeps ensures that all JavaScript dependencies are installed for projects.
5
+ # ShopifyCLI::JsDeps ensures that all JavaScript dependencies are installed for projects.
6
6
  #
7
7
  class JsDeps
8
8
  include SmartProperties
9
9
 
10
- property! :ctx, accepts: ShopifyCli::Context
10
+ property! :ctx, accepts: ShopifyCLI::Context
11
11
  property! :system, accepts: JsSystem, default: -> { JsSystem.new(ctx: ctx) }
12
12
 
13
13
  ##
14
- # Proxy to instance method ShopifyCli::JsDeps.new.install.
14
+ # Proxy to instance method ShopifyCLI::JsDeps.new.install.
15
15
  #
16
16
  # #### Parameters
17
17
  # - `ctx`: running context from your command
@@ -19,7 +19,7 @@ module ShopifyCli
19
19
  #
20
20
  # #### Example
21
21
  #
22
- # ShopifyCli::JsDeps.install(ctx)
22
+ # ShopifyCLI::JsDeps.install(ctx)
23
23
  #
24
24
  def self.install(ctx, verbose = false)
25
25
  new(ctx: ctx).install(verbose)
@@ -34,7 +34,7 @@ module ShopifyCli
34
34
  # #### Example
35
35
  #
36
36
  # # context is the running context for the command
37
- # ShopifyCli::JsDeps.new(context).install(true)
37
+ # ShopifyCLI::JsDeps.new(context).install(true)
38
38
  #
39
39
  def install(verbose = false)
40
40
  title = ctx.message("core.js_deps.installing", @system.package_manager)
@@ -104,7 +104,7 @@ module ShopifyCli
104
104
  ctx.message("core.js_deps.error.invalid_package", File.read(File.join(path, "package.json"))),
105
105
  error: true
106
106
  )
107
- raise ShopifyCli::AbortSilent
107
+ raise ShopifyCLI::AbortSilent
108
108
  end
109
109
  end
110
110
  end