shopify-cli 0.9.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 (273) hide show
  1. checksums.yaml +7 -0
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/CODE_OF_CONDUCT.md +73 -0
  4. data/.github/CONTRIBUTING.md +51 -0
  5. data/.github/DESIGN.md +153 -0
  6. data/.github/ISSUE_TEMPLATE.md +38 -0
  7. data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
  8. data/.github/probots.yml +3 -0
  9. data/.gitignore +19 -0
  10. data/.rubocop.yml +47 -0
  11. data/.ruby-version +1 -0
  12. data/.travis.yml +12 -0
  13. data/Gemfile +22 -0
  14. data/Gemfile.lock +77 -0
  15. data/LICENSE.md +7 -0
  16. data/README.md +13 -0
  17. data/Rakefile +101 -0
  18. data/SECURITY.md +59 -0
  19. data/Vagrantfile +17 -0
  20. data/bin/load_shopify.rb +20 -0
  21. data/bin/shopify +32 -0
  22. data/dev.yml +17 -0
  23. data/docs/Gemfile +5 -0
  24. data/docs/Gemfile.lock +248 -0
  25. data/docs/_config.yml +16 -0
  26. data/docs/_data/nav.yml +26 -0
  27. data/docs/_includes/footer.html +15 -0
  28. data/docs/_includes/head.html +19 -0
  29. data/docs/_includes/sidebar_nav.html +22 -0
  30. data/docs/_includes/toc.html +112 -0
  31. data/docs/_layouts/default.html +79 -0
  32. data/docs/app/node/commands/index.md +82 -0
  33. data/docs/app/node/index.md +35 -0
  34. data/docs/app/rails/commands/index.md +80 -0
  35. data/docs/app/rails/index.md +36 -0
  36. data/docs/core/index.md +70 -0
  37. data/docs/css/docs.css +157 -0
  38. data/docs/getting-started/index.md +61 -0
  39. data/docs/help/start-app/index.md +6 -0
  40. data/docs/images/header.png +0 -0
  41. data/docs/index.md +27 -0
  42. data/docs/installing-ruby.md +28 -0
  43. data/ext/shopify-cli/extconf.rb +27 -0
  44. data/install.sh +7 -0
  45. data/lib/docgen/class_template.md.erb +81 -0
  46. data/lib/docgen/index_template.md.erb +5 -0
  47. data/lib/docgen/markdown.rb +101 -0
  48. data/lib/graphql/admin_introspection.graphql +87 -0
  49. data/lib/graphql/all_organizations.graphql +19 -0
  50. data/lib/graphql/all_orgs_with_apps.graphql +30 -0
  51. data/lib/graphql/api_versions.graphql +6 -0
  52. data/lib/graphql/convert_dev_to_test_store.graphql +10 -0
  53. data/lib/graphql/create_app.graphql +20 -0
  54. data/lib/graphql/create_customer.graphql +9 -0
  55. data/lib/graphql/create_draft_order.graphql +8 -0
  56. data/lib/graphql/create_product.graphql +9 -0
  57. data/lib/graphql/extension_create.graphql +21 -0
  58. data/lib/graphql/extension_update_draft.graphql +18 -0
  59. data/lib/graphql/find_organization.graphql +17 -0
  60. data/lib/graphql/get_app_urls.graphql +6 -0
  61. data/lib/graphql/update_dashboard_urls.graphql +8 -0
  62. data/lib/project_types/extension/cli.rb +71 -0
  63. data/lib/project_types/extension/commands/build.rb +29 -0
  64. data/lib/project_types/extension/commands/create.rb +49 -0
  65. data/lib/project_types/extension/commands/extension_command.rb +22 -0
  66. data/lib/project_types/extension/commands/push.rb +69 -0
  67. data/lib/project_types/extension/commands/register.rb +78 -0
  68. data/lib/project_types/extension/commands/serve.rb +24 -0
  69. data/lib/project_types/extension/commands/tunnel.rb +69 -0
  70. data/lib/project_types/extension/extension_project.rb +85 -0
  71. data/lib/project_types/extension/extension_project_keys.rb +10 -0
  72. data/lib/project_types/extension/features/argo.rb +48 -0
  73. data/lib/project_types/extension/features/argo_dependencies.rb +28 -0
  74. data/lib/project_types/extension/features/argo_setup.rb +54 -0
  75. data/lib/project_types/extension/features/argo_setup_step.rb +31 -0
  76. data/lib/project_types/extension/features/argo_setup_steps.rb +53 -0
  77. data/lib/project_types/extension/features/tunnel_url.rb +20 -0
  78. data/lib/project_types/extension/forms/create.rb +52 -0
  79. data/lib/project_types/extension/forms/register.rb +48 -0
  80. data/lib/project_types/extension/messages/message_loading.rb +37 -0
  81. data/lib/project_types/extension/messages/messages.rb +126 -0
  82. data/lib/project_types/extension/models/app.rb +14 -0
  83. data/lib/project_types/extension/models/registration.rb +19 -0
  84. data/lib/project_types/extension/models/type.rb +76 -0
  85. data/lib/project_types/extension/models/types/checkout_post_purchase.rb +20 -0
  86. data/lib/project_types/extension/models/types/subscription_management.rb +20 -0
  87. data/lib/project_types/extension/models/validation_error.rb +17 -0
  88. data/lib/project_types/extension/models/version.rb +15 -0
  89. data/lib/project_types/extension/tasks/converters/registration_converter.rb +26 -0
  90. data/lib/project_types/extension/tasks/converters/validation_error_converter.rb +25 -0
  91. data/lib/project_types/extension/tasks/converters/version_converter.rb +28 -0
  92. data/lib/project_types/extension/tasks/create_extension.rb +31 -0
  93. data/lib/project_types/extension/tasks/get_apps.rb +34 -0
  94. data/lib/project_types/extension/tasks/update_draft.rb +29 -0
  95. data/lib/project_types/extension/tasks/user_errors.rb +45 -0
  96. data/lib/project_types/node/cli.rb +37 -0
  97. data/lib/project_types/node/commands/create.rb +117 -0
  98. data/lib/project_types/node/commands/deploy.rb +22 -0
  99. data/lib/project_types/node/commands/deploy/heroku.rb +91 -0
  100. data/lib/project_types/node/commands/generate.rb +51 -0
  101. data/lib/project_types/node/commands/generate/billing.rb +37 -0
  102. data/lib/project_types/node/commands/generate/page.rb +55 -0
  103. data/lib/project_types/node/commands/generate/webhook.rb +33 -0
  104. data/lib/project_types/node/commands/open.rb +16 -0
  105. data/lib/project_types/node/commands/populate.rb +23 -0
  106. data/lib/project_types/node/commands/populate/customer.rb +31 -0
  107. data/lib/project_types/node/commands/populate/draft_order.rb +28 -0
  108. data/lib/project_types/node/commands/populate/product.rb +30 -0
  109. data/lib/project_types/node/commands/serve.rb +45 -0
  110. data/lib/project_types/node/commands/tunnel.rb +39 -0
  111. data/lib/project_types/node/forms/create.rb +87 -0
  112. data/lib/project_types/node/messages/messages.rb +260 -0
  113. data/lib/project_types/rails/cli.rb +41 -0
  114. data/lib/project_types/rails/commands/create.rb +126 -0
  115. data/lib/project_types/rails/commands/deploy.rb +22 -0
  116. data/lib/project_types/rails/commands/deploy/heroku.rb +113 -0
  117. data/lib/project_types/rails/commands/generate.rb +49 -0
  118. data/lib/project_types/rails/commands/generate/webhook.rb +39 -0
  119. data/lib/project_types/rails/commands/open.rb +16 -0
  120. data/lib/project_types/rails/commands/populate.rb +23 -0
  121. data/lib/project_types/rails/commands/populate/customer.rb +31 -0
  122. data/lib/project_types/rails/commands/populate/draft_order.rb +28 -0
  123. data/lib/project_types/rails/commands/populate/product.rb +30 -0
  124. data/lib/project_types/rails/commands/serve.rb +47 -0
  125. data/lib/project_types/rails/commands/tunnel.rb +39 -0
  126. data/lib/project_types/rails/forms/create.rb +116 -0
  127. data/lib/project_types/rails/gem.rb +56 -0
  128. data/lib/project_types/rails/messages/messages.rb +283 -0
  129. data/lib/project_types/rails/ruby.rb +17 -0
  130. data/lib/project_types/script/cli.rb +76 -0
  131. data/lib/project_types/script/commands/create.rb +45 -0
  132. data/lib/project_types/script/commands/disable.rb +36 -0
  133. data/lib/project_types/script/commands/enable.rb +46 -0
  134. data/lib/project_types/script/commands/push.rb +39 -0
  135. data/lib/project_types/script/config/extension_points.yml +18 -0
  136. data/lib/project_types/script/errors.rb +16 -0
  137. data/lib/project_types/script/forms/create.rb +29 -0
  138. data/lib/project_types/script/forms/enable.rb +24 -0
  139. data/lib/project_types/script/forms/push.rb +19 -0
  140. data/lib/project_types/script/forms/script_form.rb +66 -0
  141. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +27 -0
  142. data/lib/project_types/script/graphql/script_service_proxy.graphql +8 -0
  143. data/lib/project_types/script/graphql/shop_script_delete.graphql +14 -0
  144. data/lib/project_types/script/graphql/shop_script_update_or_create.graphql +28 -0
  145. data/lib/project_types/script/layers/application/build_script.rb +43 -0
  146. data/lib/project_types/script/layers/application/create_script.rb +47 -0
  147. data/lib/project_types/script/layers/application/disable_script.rb +19 -0
  148. data/lib/project_types/script/layers/application/enable_script.rb +21 -0
  149. data/lib/project_types/script/layers/application/extension_points.rb +17 -0
  150. data/lib/project_types/script/layers/application/project_dependencies.rb +34 -0
  151. data/lib/project_types/script/layers/application/push_script.rb +30 -0
  152. data/lib/project_types/script/layers/domain/errors.rb +25 -0
  153. data/lib/project_types/script/layers/domain/extension_point.rb +29 -0
  154. data/lib/project_types/script/layers/domain/push_package.rb +29 -0
  155. data/lib/project_types/script/layers/domain/script.rb +18 -0
  156. data/lib/project_types/script/layers/infrastructure/assemblyscript_dependency_manager.rb +73 -0
  157. data/lib/project_types/script/layers/infrastructure/assemblyscript_tsconfig.rb +38 -0
  158. data/lib/project_types/script/layers/infrastructure/assemblyscript_wasm_builder.rb +39 -0
  159. data/lib/project_types/script/layers/infrastructure/dependency_manager.rb +36 -0
  160. data/lib/project_types/script/layers/infrastructure/errors.rb +38 -0
  161. data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +31 -0
  162. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +47 -0
  163. data/lib/project_types/script/layers/infrastructure/script_builder.rb +34 -0
  164. data/lib/project_types/script/layers/infrastructure/script_repository.rb +89 -0
  165. data/lib/project_types/script/layers/infrastructure/script_service.rb +165 -0
  166. data/lib/project_types/script/layers/infrastructure/test_suite_repository.rb +59 -0
  167. data/lib/project_types/script/messages/messages.rb +204 -0
  168. data/lib/project_types/script/script_project.rb +37 -0
  169. data/lib/project_types/script/templates/ts/as-pect.config.js +21 -0
  170. data/lib/project_types/script/ui/error_handler.rb +136 -0
  171. data/lib/project_types/script/ui/strict_spinner.rb +22 -0
  172. data/lib/rubygems_plugin.rb +18 -0
  173. data/lib/shopify-cli/admin_api.rb +99 -0
  174. data/lib/shopify-cli/admin_api/populate_resource_command.rb +165 -0
  175. data/lib/shopify-cli/admin_api/schema.rb +32 -0
  176. data/lib/shopify-cli/api.rb +104 -0
  177. data/lib/shopify-cli/command.rb +67 -0
  178. data/lib/shopify-cli/commands.rb +28 -0
  179. data/lib/shopify-cli/commands/connect.rb +108 -0
  180. data/lib/shopify-cli/commands/create.rb +50 -0
  181. data/lib/shopify-cli/commands/help.rb +79 -0
  182. data/lib/shopify-cli/commands/logout.rb +23 -0
  183. data/lib/shopify-cli/commands/system.rb +135 -0
  184. data/lib/shopify-cli/commands/version.rb +15 -0
  185. data/lib/shopify-cli/context.rb +372 -0
  186. data/lib/shopify-cli/core.rb +9 -0
  187. data/lib/shopify-cli/core/entry_point.rb +40 -0
  188. data/lib/shopify-cli/core/executor.rb +21 -0
  189. data/lib/shopify-cli/core/help_resolver.rb +20 -0
  190. data/lib/shopify-cli/core/monorail.rb +118 -0
  191. data/lib/shopify-cli/db.rb +114 -0
  192. data/lib/shopify-cli/form.rb +40 -0
  193. data/lib/shopify-cli/git.rb +141 -0
  194. data/lib/shopify-cli/helpers.rb +5 -0
  195. data/lib/shopify-cli/helpers/haikunator.rb +92 -0
  196. data/lib/shopify-cli/heroku.rb +97 -0
  197. data/lib/shopify-cli/js_deps.rb +110 -0
  198. data/lib/shopify-cli/js_system.rb +98 -0
  199. data/lib/shopify-cli/messages/messages.rb +287 -0
  200. data/lib/shopify-cli/oauth.rb +192 -0
  201. data/lib/shopify-cli/oauth/servlet.rb +61 -0
  202. data/lib/shopify-cli/options.rb +40 -0
  203. data/lib/shopify-cli/packager.rb +116 -0
  204. data/lib/shopify-cli/partners_api.rb +114 -0
  205. data/lib/shopify-cli/partners_api/organizations.rb +32 -0
  206. data/lib/shopify-cli/process_supervision.rb +187 -0
  207. data/lib/shopify-cli/project.rb +191 -0
  208. data/lib/shopify-cli/project_type.rb +83 -0
  209. data/lib/shopify-cli/resources.rb +5 -0
  210. data/lib/shopify-cli/resources/env_file.rb +96 -0
  211. data/lib/shopify-cli/sub_command.rb +15 -0
  212. data/lib/shopify-cli/task.rb +10 -0
  213. data/lib/shopify-cli/tasks.rb +32 -0
  214. data/lib/shopify-cli/tasks/create_api_client.rb +29 -0
  215. data/lib/shopify-cli/tasks/ensure_dev_store.rb +41 -0
  216. data/lib/shopify-cli/tasks/ensure_env.rb +31 -0
  217. data/lib/shopify-cli/tasks/ensure_loopback_url.rb +20 -0
  218. data/lib/shopify-cli/tasks/update_dashboard_urls.rb +44 -0
  219. data/lib/shopify-cli/tunnel.rb +154 -0
  220. data/lib/shopify-cli/version.rb +3 -0
  221. data/lib/shopify_cli.rb +132 -0
  222. data/shopify-cli.gemspec +40 -0
  223. data/shopify.fish +12 -0
  224. data/shopify.sh +11 -0
  225. data/vendor/deps/cli-kit/REVISION +1 -0
  226. data/vendor/deps/cli-kit/lib/cli/kit.rb +60 -0
  227. data/vendor/deps/cli-kit/lib/cli/kit/autocall.rb +21 -0
  228. data/vendor/deps/cli-kit/lib/cli/kit/base_command.rb +49 -0
  229. data/vendor/deps/cli-kit/lib/cli/kit/command_registry.rb +94 -0
  230. data/vendor/deps/cli-kit/lib/cli/kit/config.rb +133 -0
  231. data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +115 -0
  232. data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +81 -0
  233. data/vendor/deps/cli-kit/lib/cli/kit/ini.rb +102 -0
  234. data/vendor/deps/cli-kit/lib/cli/kit/levenshtein.rb +82 -0
  235. data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +76 -0
  236. data/vendor/deps/cli-kit/lib/cli/kit/resolver.rb +60 -0
  237. data/vendor/deps/cli-kit/lib/cli/kit/ruby_backports/enumerable.rb +6 -0
  238. data/vendor/deps/cli-kit/lib/cli/kit/support.rb +9 -0
  239. data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +244 -0
  240. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +207 -0
  241. data/vendor/deps/cli-kit/lib/cli/kit/util.rb +189 -0
  242. data/vendor/deps/cli-kit/lib/cli/kit/version.rb +5 -0
  243. data/vendor/deps/cli-ui/REVISION +1 -0
  244. data/vendor/deps/cli-ui/lib/cli/ui.rb +187 -0
  245. data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +153 -0
  246. data/vendor/deps/cli-ui/lib/cli/ui/box.rb +15 -0
  247. data/vendor/deps/cli-ui/lib/cli/ui/color.rb +79 -0
  248. data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +179 -0
  249. data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +310 -0
  250. data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +78 -0
  251. data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +88 -0
  252. data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +248 -0
  253. data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +472 -0
  254. data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +24 -0
  255. data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +48 -0
  256. data/vendor/deps/cli-ui/lib/cli/ui/spinner/async.rb +40 -0
  257. data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +241 -0
  258. data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +227 -0
  259. data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +36 -0
  260. data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +102 -0
  261. data/vendor/deps/cli-ui/lib/cli/ui/version.rb +5 -0
  262. data/vendor/deps/smart_properties/REVISION +1 -0
  263. data/vendor/deps/smart_properties/lib/smart_properties.rb +174 -0
  264. data/vendor/deps/smart_properties/lib/smart_properties/errors.rb +114 -0
  265. data/vendor/deps/smart_properties/lib/smart_properties/property.rb +162 -0
  266. data/vendor/deps/smart_properties/lib/smart_properties/property_collection.rb +83 -0
  267. data/vendor/deps/smart_properties/lib/smart_properties/validations.rb +8 -0
  268. data/vendor/deps/smart_properties/lib/smart_properties/validations/ancestor.rb +27 -0
  269. data/vendor/deps/smart_properties/lib/smart_properties/version.rb +3 -0
  270. data/vendor/lib/semantic/LICENSE +20 -0
  271. data/vendor/lib/semantic/semantic.rb +4 -0
  272. data/vendor/lib/semantic/version.rb +180 -0
  273. metadata +374 -0
@@ -0,0 +1,9 @@
1
+ module ShopifyCli
2
+ module Core
3
+ autoload :EntryPoint, 'shopify-cli/core/entry_point'
4
+ autoload :Executor, 'shopify-cli/core/executor'
5
+ autoload :HelpResolver, 'shopify-cli/core/help_resolver'
6
+ autoload :Monorail, 'shopify-cli/core/monorail'
7
+ autoload :Update, 'shopify-cli/core/update'
8
+ end
9
+ end
@@ -0,0 +1,40 @@
1
+ require 'shopify_cli'
2
+
3
+ module ShopifyCli
4
+ module Core
5
+ module EntryPoint
6
+ class << self
7
+ def call(args, ctx = Context.new)
8
+ # Check if the shim is set up by checking whether the old Finalizer FD exists
9
+ begin
10
+ is_shell_shim = false
11
+ IO.open(9) { is_shell_shim = true }
12
+ rescue Errno::EBADF
13
+ # This is expected if the descriptor doesn't exist
14
+ end
15
+
16
+ if !ctx.testing? && is_shell_shim
17
+ ctx.puts(ctx.message('core.warning.shell_shim'))
18
+ return
19
+ end
20
+
21
+ if ctx.development?
22
+ ctx.puts(
23
+ ctx.message('core.warning.development_version', File.join(ShopifyCli::ROOT, 'bin', ShopifyCli::TOOL_NAME))
24
+ )
25
+ end
26
+
27
+ ProjectType.load_type(Project.current_project_type)
28
+
29
+ task_registry = ShopifyCli::Tasks::Registry
30
+
31
+ command, command_name, args = ShopifyCli::Resolver.call(args)
32
+ executor = ShopifyCli::Core::Executor.new(ctx, task_registry, log_file: ShopifyCli::LOG_FILE)
33
+ ShopifyCli::Core::Monorail.log(command_name, args) do
34
+ executor.call(command, command_name, args)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ require 'shopify_cli'
2
+
3
+ module ShopifyCli
4
+ module Core
5
+ class Executor < CLI::Kit::Executor
6
+ def initialize(ctx, task_registry, *args)
7
+ @ctx = ctx || ShopifyCli::Context.new
8
+ @task_registry = task_registry || ShopifyCli::Tasks::TaskRegistry.new
9
+ super(*args)
10
+ end
11
+
12
+ def call(command, command_name, args)
13
+ command.prerequisite_tasks.each do |task, _|
14
+ @task_registry[task]&.call(@ctx)
15
+ end
16
+ command.ctx = @ctx
17
+ super
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ require 'cli/kit'
2
+
3
+ module ShopifyCli
4
+ module Core
5
+ class HelpResolver < CLI::Kit::Resolver
6
+ def call(args)
7
+ args = args.dup
8
+ return super(args) unless args.first
9
+ if args.first.include?('-h') || args.first.include?('--help')
10
+ help = Commands::Help
11
+ help.ctx = Context.new
12
+ help.call([], nil)
13
+ raise ShopifyCli::AbortSilent
14
+ else
15
+ super(args)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,118 @@
1
+ require 'json'
2
+ require 'net/http'
3
+ require 'time'
4
+ require 'rbconfig'
5
+
6
+ module ShopifyCli
7
+ module Core
8
+ module Monorail
9
+ ENDPOINT_URI = URI.parse('https://monorail-edge.shopifycloud.com/v1/produce')
10
+ INVOCATIONS_SCHEMA = 'app_cli_command/4.0'
11
+
12
+ # Extra hash of data that will be sent in the payload
13
+ @metadata = {}
14
+
15
+ class << self
16
+ attr_accessor :metadata
17
+
18
+ def log(name, args, &block) # rubocop:disable Lint/UnusedMethodArgument
19
+ prompt_for_consent
20
+ return yield unless enabled? && consented?
21
+
22
+ command, command_name = Commands::Registry.lookup_command(name)
23
+ final_command = [command_name]
24
+ if command
25
+ subcommand, subcommand_name = command.subcommand_registry.lookup_command(args.first)
26
+ final_command << subcommand_name if subcommand
27
+ end
28
+
29
+ start_time = now_in_milliseconds
30
+ err = nil
31
+ begin
32
+ yield
33
+ rescue Exception => e # rubocop:disable Lint/RescueException
34
+ err = e
35
+ raise
36
+ ensure
37
+ send_event(start_time, final_command, args - final_command, err&.message)
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def now_in_milliseconds
44
+ (Time.now.utc.to_f * 1000).to_i
45
+ end
46
+
47
+ # we only want to send Monorail events in production or when explicitly developing
48
+ def enabled?
49
+ Context.new.system? || ENV['MONORAIL_REAL_EVENTS'] == '1'
50
+ end
51
+
52
+ def consented?
53
+ ShopifyCli::Config.get_bool('analytics', 'enabled')
54
+ end
55
+
56
+ def prompt_for_consent
57
+ return unless enabled?
58
+ return if ShopifyCli::Config.get_section('analytics').key?('enabled')
59
+ msg = Context.message('core.monorail.consent_prompt')
60
+ opt = CLI::UI::Prompt.confirm(msg)
61
+ ShopifyCli::Config.set('analytics', 'enabled', opt)
62
+ end
63
+
64
+ def send_event(start_time, commands, args, err = nil)
65
+ end_time = now_in_milliseconds
66
+ headers = {
67
+ 'Content-Type': 'application/json; charset=utf-8',
68
+ 'X-Monorail-Edge-Event-Created-At-Ms': start_time.to_s,
69
+ 'X-Monorail-Edge-Event-Sent-At-Ms': end_time.to_s,
70
+ }
71
+ begin
72
+ Net::HTTP.start(
73
+ ENDPOINT_URI.host,
74
+ ENDPOINT_URI.port,
75
+ # timeouts for opening a connection, reading, writing (in seconds)
76
+ open_timeout: 0.2, read_timeout: 0.2, write_timeout: 0.2,
77
+ use_ssl: ENDPOINT_URI.scheme == 'https'
78
+ ) do |http|
79
+ payload = build_payload(start_time, end_time, commands, args, err)
80
+ post = Net::HTTP::Post.new(ENDPOINT_URI.request_uri, headers)
81
+ post.body = JSON.dump(payload)
82
+ http.request(post)
83
+ end
84
+ rescue
85
+ # silently fail on errors, fire-and-forget approach
86
+ end
87
+ end
88
+
89
+ def build_payload(start_time, end_time, commands, args, err = nil)
90
+ {
91
+ schema_id: INVOCATIONS_SCHEMA,
92
+ payload: {
93
+ project_type: Project.current_project_type.to_s,
94
+ command: commands.join(' '),
95
+ args: args.join(' '),
96
+ time_start: start_time,
97
+ time_end: end_time,
98
+ total_time: end_time - start_time,
99
+ success: err.nil?,
100
+ error_message: err,
101
+ uname: RbConfig::CONFIG["host"],
102
+ cli_version: ShopifyCli::Git.sha(dir: ShopifyCli::ROOT),
103
+ ruby_version: RUBY_VERSION,
104
+ }.tap do |payload|
105
+ payload[:metadata] = JSON.dump(metadata) unless metadata.empty?
106
+
107
+ if Project.has_current?
108
+ project = Project.current
109
+ payload[:api_key] = project.env&.api_key
110
+ payload[:partner_id] = project.config['organization_id']
111
+ end
112
+ end,
113
+ }
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,114 @@
1
+ require 'pstore'
2
+ require 'forwardable'
3
+
4
+ module ShopifyCli
5
+ # Persists transient data like access tokens that may be cleared
6
+ # when user clears their session
7
+ #
8
+ # All of the instance methods documented here can be used as class methods. All class
9
+ # methods are forwarded to a new instance of the database, pointing at the default
10
+ # path.
11
+ class DB
12
+ extend SingleForwardable
13
+ def_delegators :new, :keys, :exists?, :set, :get, :del, :clear
14
+
15
+ attr_reader :db # :nodoc:
16
+
17
+ def initialize(path: File.join(ShopifyCli::CACHE_DIR, ".db.pstore")) # :nodoc:
18
+ @db = PStore.new(path)
19
+ end
20
+
21
+ # Get all keys that exist in the database.
22
+ #
23
+ # #### Returns
24
+ # - `keys`: an array of string or symbol keys that exist in the database
25
+ #
26
+ # #### Usage
27
+ #
28
+ # ShopifyCli::DB.keys
29
+ #
30
+ def keys
31
+ db.transaction(true) { db.roots }
32
+ end
33
+
34
+ # Check to see if a key exists in the database, the key will only exist if it
35
+ # has a value so if the key exists then there is also a value.
36
+ #
37
+ # #### Parameters
38
+ # - `key`: a string or a symbol representation of a key that is stored in the DB
39
+ #
40
+ # #### Returns
41
+ # - `exists`: a boolean value if the key exists in the database
42
+ #
43
+ # #### Usage
44
+ #
45
+ # exists = ShopifyCli::DB.exists?('admin_access_token')
46
+ #
47
+ def exists?(key)
48
+ db.transaction(true) { db.root?(key) }
49
+ end
50
+
51
+ # Persist a value by key in the local storage
52
+ #
53
+ # #### Parameters
54
+ # - `**args`: a hash of keys and values to persist in the database
55
+ #
56
+ # #### Usage
57
+ #
58
+ # ShopifyCli::DB.set(admin_access_token: 'token', metric_consent: true)
59
+ #
60
+ def set(**args)
61
+ db.transaction do
62
+ args.each do |key, val|
63
+ if val.nil?
64
+ db.delete(key)
65
+ else
66
+ db[key] = val
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ # Gets a value from the DB that is associated with the supplied key
73
+ #
74
+ # #### Parameters
75
+ # - `key`: a string or a symbol representation of a key that is stored in the DB
76
+ #
77
+ # #### Returns
78
+ # - `value`: will be the previously saved value or nil if the key does not exist
79
+ # in the database.
80
+ #
81
+ # #### Usage
82
+ #
83
+ # ShopifyCli::DB.get(:admin_access_token)
84
+ #
85
+ def get(key)
86
+ val = db.transaction(true) { db[key] }
87
+ val = yield if val.nil? && block_given?
88
+ val
89
+ end
90
+
91
+ # Deletes a value from the local storage
92
+ #
93
+ # #### Parameters
94
+ # - `*args`: an array of strings or symbols that are keys to be removed from the database
95
+ #
96
+ # #### Usage
97
+ #
98
+ # ShopifyCli::DB.del(:admin_access_token)
99
+ #
100
+ def del(*args)
101
+ db.transaction { args.each { |key| db.delete(key) } }
102
+ end
103
+
104
+ # Drops all keys from the database.
105
+ #
106
+ # #### Usage
107
+ #
108
+ # ShopifyCli::DB.clear
109
+ #
110
+ def clear
111
+ del(*keys)
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,40 @@
1
+ require 'shopify_cli'
2
+
3
+ module ShopifyCli
4
+ class Form
5
+ class << self
6
+ def ask(ctx, args, flags)
7
+ attrs = {}
8
+ (@positional_arguments || []).each { |name| attrs[name] = args.shift }
9
+ return nil if attrs.any? { |_k, v| v.nil? }
10
+ (@flag_arguments || []).each { |arg| attrs[arg] = flags[arg] }
11
+ form = new(ctx, args, attrs)
12
+ begin
13
+ form.ask
14
+ form
15
+ rescue ShopifyCli::Abort => err
16
+ ctx.puts(err.message)
17
+ nil
18
+ end
19
+ end
20
+
21
+ def positional_arguments(*args)
22
+ @positional_arguments = args
23
+ attr_accessor(*args)
24
+ end
25
+
26
+ def flag_arguments(*args)
27
+ @flag_arguments = args
28
+ attr_accessor(*args)
29
+ end
30
+ end
31
+
32
+ attr_accessor :ctx, :xargs
33
+
34
+ def initialize(ctx, xargs, attributes)
35
+ @ctx = ctx
36
+ @xargs = xargs
37
+ attributes.each { |k, v| send("#{k}=", v) unless v.nil? }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,141 @@
1
+ module ShopifyCli
2
+ ##
3
+ # ShopifyCli::Git wraps git functionality to make it easier to integrate will
4
+ # git.
5
+ class Git
6
+ class << self
7
+ ##
8
+ # will return the current sha of the cli repo
9
+ #
10
+ # #### Parameters
11
+ #
12
+ # * `dir` - the directory of the git repo. This defaults to the cli repo
13
+ # * `ctx` - the current running context of your command
14
+ #
15
+ # #### Returns
16
+ #
17
+ # * `sha_string` - string of the sha of the most recent commit to the repo
18
+ #
19
+ # #### Example
20
+ #
21
+ # ShopifyCli::Git.sha
22
+ #
23
+ def sha(dir: Dir.pwd, ctx: Context.new)
24
+ rev_parse('HEAD', dir: dir, ctx: ctx)
25
+ end
26
+
27
+ ##
28
+ # will make calls to git to clone a new repo into a supplied destination,
29
+ # it will also output progress of the cloning process.
30
+ #
31
+ # #### Parameters
32
+ #
33
+ # * `repository` - a git url for git to clone the repo from
34
+ # * `dest` - a filepath to where the repo should be cloned to
35
+ # * `ctx` - the current running context of your command, defaults to a new context.
36
+ #
37
+ # #### Returns
38
+ #
39
+ # * `sha_string` - string of the sha of the most recent commit to the repo
40
+ #
41
+ # #### Example
42
+ #
43
+ # ShopifyCli::Git.clone('git@github.com:shopify/test.git', 'test-app')
44
+ #
45
+ def clone(repository, dest, ctx: Context.new)
46
+ if Dir.exist?(dest)
47
+ ctx.abort(ctx.message('core.git.error.directory_exists'))
48
+ else
49
+ CLI::UI::Frame.open(ctx.message('core.git.cloning', dest)) do
50
+ clone_progress('clone', '--single-branch', repository, dest, ctx: ctx)
51
+ end
52
+ ctx.done(ctx.message('core.git.cloned', dest))
53
+ end
54
+ end
55
+
56
+ ##
57
+ # will fetch the repos list of branches.
58
+ #
59
+ # #### Parameters
60
+ #
61
+ # * `ctx` - the current running context of your command, defaults to a new context.
62
+ #
63
+ # #### Returns
64
+ #
65
+ # * `branches` - [String] an array of strings that are branch names
66
+ #
67
+ # #### Example
68
+ #
69
+ # branches = ShopifyCli::Git.branches(@ctx)
70
+ #
71
+ def branches(ctx)
72
+ output, status = ctx.capture2e('git', 'branch', '--list', '--format=%(refname:short)')
73
+ ctx.abort(ctx.message('core.git.error.no_branches_found')) unless status.success?
74
+
75
+ branches = if output == ''
76
+ ['master']
77
+ else
78
+ output.split("\n")
79
+ end
80
+
81
+ branches
82
+ end
83
+
84
+ ##
85
+ # will initialize a new repo in the current directory. This will output
86
+ # if it was successful or not.
87
+ #
88
+ # #### Parameters
89
+ #
90
+ # * `ctx` - the current running context of your command, defaults to a new context.
91
+ #
92
+ # #### Example
93
+ #
94
+ # ShopifyCli::Git.init(@ctx)
95
+ #
96
+ def init(ctx)
97
+ output, status = ctx.capture2e('git', 'status')
98
+
99
+ unless status.success?
100
+ ctx.abort(ctx.message('core.git.error.repo_not_initiated'))
101
+ end
102
+
103
+ if output.include?('No commits yet')
104
+ ctx.abort(ctx.message('core.git.error.no_commits_made'))
105
+ end
106
+ end
107
+
108
+ private
109
+
110
+ def exec(*args, dir: Dir.pwd, default: nil, ctx: Context.new)
111
+ args = %w(git) + args
112
+ out, _, stat = ctx.capture3(*args, chdir: dir)
113
+ return default unless stat.success?
114
+ out.chomp
115
+ end
116
+
117
+ def rev_parse(*args, dir: nil, ctx: Context.new)
118
+ exec('rev-parse', *args, dir: dir, ctx: ctx)
119
+ end
120
+
121
+ def clone_progress(*git_command, ctx:)
122
+ CLI::UI::Progress.progress do |bar|
123
+ msg = []
124
+ success = ctx.system('git', *git_command, '--progress') do |_out, err|
125
+ if err.strip.start_with?('Receiving objects:')
126
+ percent = (err.match(/Receiving objects:\s+(\d+)/)[1].to_f / 100).round(2)
127
+ bar.tick(set_percent: percent)
128
+ next
129
+ end
130
+ msg << err
131
+ end.success?
132
+ unless success
133
+ ctx.abort(msg.join("\n"))
134
+ end
135
+ bar.tick(set_percent: 1.0)
136
+ true
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end