shopify-cli 2.10.2 → 2.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.yaml +117 -0
  3. data/.github/ISSUE_TEMPLATE/enhancement.yaml +38 -0
  4. data/.github/ISSUE_TEMPLATE/feature.yaml +47 -0
  5. data/CHANGELOG.md +20 -3
  6. data/Gemfile.lock +1 -1
  7. data/dev.yml +3 -0
  8. data/lib/project_types/extension/commands/build.rb +3 -0
  9. data/lib/project_types/extension/commands/check.rb +3 -0
  10. data/lib/project_types/extension/commands/create.rb +3 -0
  11. data/lib/project_types/extension/commands/push.rb +3 -0
  12. data/lib/project_types/extension/commands/serve.rb +3 -0
  13. data/lib/project_types/extension/models/specification_handlers/default.rb +1 -1
  14. data/lib/project_types/extension/tasks/convert_server_config.rb +3 -1
  15. data/lib/project_types/script/commands/connect.rb +3 -1
  16. data/lib/project_types/script/commands/create.rb +2 -0
  17. data/lib/project_types/script/commands/push.rb +6 -0
  18. data/lib/project_types/script/layers/infrastructure/errors.rb +4 -3
  19. data/lib/project_types/script/layers/infrastructure/script_service.rb +2 -2
  20. data/lib/project_types/script/loaders/project.rb +2 -1
  21. data/lib/project_types/script/messages/messages.rb +87 -86
  22. data/lib/project_types/script/ui/error_handler.rb +34 -14
  23. data/lib/project_types/theme/commands/check.rb +3 -0
  24. data/lib/project_types/theme/commands/delete.rb +3 -0
  25. data/lib/project_types/theme/commands/init.rb +3 -0
  26. data/lib/project_types/theme/commands/language_server.rb +3 -0
  27. data/lib/project_types/theme/commands/package.rb +3 -0
  28. data/lib/project_types/theme/commands/publish.rb +3 -0
  29. data/lib/project_types/theme/commands/pull.rb +7 -1
  30. data/lib/project_types/theme/commands/push.rb +7 -1
  31. data/lib/project_types/theme/commands/serve.rb +3 -0
  32. data/lib/shopify_cli/command/sub_command.rb +2 -0
  33. data/lib/shopify_cli/command.rb +66 -0
  34. data/lib/shopify_cli/commands/app/create/node.rb +3 -0
  35. data/lib/shopify_cli/commands/app/create/rails.rb +3 -0
  36. data/lib/shopify_cli/commands/app/create.rb +3 -0
  37. data/lib/shopify_cli/commands/app/deploy.rb +3 -0
  38. data/lib/shopify_cli/commands/app/serve.rb +3 -0
  39. data/lib/shopify_cli/constants.rb +12 -0
  40. data/lib/shopify_cli/environment.rb +27 -1
  41. data/lib/shopify_cli/exception_reporter.rb +9 -0
  42. data/lib/shopify_cli/github/issue_url_generator.rb +19 -8
  43. data/lib/shopify_cli/identity_auth/env_auth_token.rb +34 -0
  44. data/lib/shopify_cli/identity_auth.rb +33 -15
  45. data/lib/shopify_cli/messages/messages.rb +1 -1
  46. data/lib/shopify_cli/partners_api.rb +7 -2
  47. data/lib/shopify_cli/services/app/create/rails_service.rb +37 -13
  48. data/lib/shopify_cli/theme/include_filter.rb +39 -17
  49. data/lib/shopify_cli/utilities.rb +7 -0
  50. data/lib/shopify_cli/version.rb +1 -1
  51. data/lib/shopify_cli.rb +1 -0
  52. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +1 -1
  53. data/vendor/deps/cli-kit/lib/cli/kit/util.rb +5 -1
  54. data/vendor/lib/semantic/version.rb +0 -1
  55. metadata +7 -3
  56. data/lib/project_types/rails/commands/create.rb +0 -210
@@ -5,6 +5,9 @@ module ShopifyCLI
5
5
  class Rails < ShopifyCLI::Command::AppSubCommand
6
6
  prerequisite_task :ensure_authenticated
7
7
 
8
+ recommend_default_node_range
9
+ recommend_default_ruby_range
10
+
8
11
  options do |parser, flags|
9
12
  parser.on("--name=NAME") { |t| flags[:name] = t }
10
13
  parser.on("--organization-id=ID") { |id| flags[:organization_id] = id }
@@ -6,6 +6,9 @@ module ShopifyCLI
6
6
  subcommand :PHP, "php", "shopify_cli/commands/app/create/php"
7
7
  subcommand :Node, "node", "shopify_cli/commands/app/create/node"
8
8
 
9
+ recommend_default_node_range
10
+ recommend_default_ruby_range
11
+
9
12
  def call(_args, _command_name)
10
13
  @ctx.puts(self.class.help)
11
14
  end
@@ -4,6 +4,9 @@ module ShopifyCLI
4
4
  class Deploy < ShopifyCLI::Command::AppSubCommand
5
5
  subcommand :Heroku, "heroku", "shopify_cli/commands/app/deploy/heroku"
6
6
 
7
+ recommend_default_node_range
8
+ recommend_default_ruby_range
9
+
7
10
  def call(args, _name)
8
11
  platform = args.shift
9
12
  case platform
@@ -6,6 +6,9 @@ module ShopifyCLI
6
6
 
7
7
  prerequisite_task :ensure_env, :ensure_dev_store
8
8
 
9
+ recommend_default_ruby_range
10
+ recommend_default_node_range
11
+
9
12
  options do |parser, flags|
10
13
  parser.on("--host=HOST") do |h|
11
14
  flags[:host] = h.gsub('"', "")
@@ -58,6 +58,18 @@ module ShopifyCLI
58
58
  MONORAIL_REAL_EVENTS = "MONORAIL_REAL_EVENTS"
59
59
  end
60
60
 
61
+ module SupportedVersions
62
+ module Ruby
63
+ FROM = "2.6.6"
64
+ TO = "3.1.0"
65
+ end
66
+
67
+ module Node
68
+ FROM = "12.0.0"
69
+ TO = "17.0.0"
70
+ end
71
+ end
72
+
61
73
  module Identity
62
74
  CLIENT_ID_DEV = "e5380e02-312a-7408-5718-e07017e9cf52"
63
75
  CLIENT_ID = "fbdb2649-e327-4907-8f67-908d24cfd7e3"
@@ -1,9 +1,25 @@
1
+ require "semantic/semantic"
2
+
1
3
  module ShopifyCLI
2
4
  # The environment module provides an interface to get information from
3
5
  # the environment in which the CLI runs
4
6
  module Environment
5
7
  TRUTHY_ENV_VARIABLE_VALUES = ["1", "true", "TRUE", "yes", "YES"]
6
8
 
9
+ def self.ruby_version(context: Context.new)
10
+ out, err, stat = context.capture3('ruby -e "puts RUBY_VERSION"')
11
+ raise ShopifyCLI::Abort, err unless stat.success?
12
+ out = out.gsub('"', "")
13
+ ::Semantic::Version.new(out.chomp)
14
+ end
15
+
16
+ def self.node_version(context: Context.new)
17
+ out, err, stat = context.capture3("node", "--version")
18
+ raise ShopifyCLI::Abort, err unless stat.success?
19
+ out = out.gsub("v", "")
20
+ ::Semantic::Version.new(out.chomp)
21
+ end
22
+
7
23
  def self.interactive=(interactive)
8
24
  @interactive = interactive
9
25
  end
@@ -90,7 +106,17 @@ module ShopifyCLI
90
106
 
91
107
  def self.spin_url(env_variables: ENV)
92
108
  if infer_spin?(env_variables: env_variables)
93
- %x(spin info fqdn 2> /dev/null).strip
109
+ # TODO: Remove version check and delete spin-legacy branch
110
+ # once spin2 becomes the installed "spin" binary by default
111
+ spin_version = %x(spin version 2> /dev/null).strip
112
+ if spin_version.start_with?("spin-")
113
+ # spin2
114
+ raise ShopifyCLI:: Abort, "SPIN_INSTANCE must be specified" unless ENV.key?("SPIN_INSTANCE")
115
+ %x(spin show -o fqdn 2> /dev/null).strip
116
+ else
117
+ # spin-legacy
118
+ %x(spin info fqdn 2> /dev/null).strip
119
+ end
94
120
  else
95
121
  spin_workspace = spin_workspace(env_variables: env_variables)
96
122
  spin_namespace = spin_namespace(env_variables: env_variables)
@@ -1,5 +1,10 @@
1
1
  module ShopifyCLI
2
2
  module ExceptionReporter
3
+ def self.report_error_silently(error)
4
+ return unless ReportingConfigurationController.reporting_enabled?
5
+ report_to_bugsnag(error: error)
6
+ end
7
+
3
8
  def self.report(error, _logs = nil, _api_key = nil, custom_metadata = {})
4
9
  context = ShopifyCLI::Context.new
5
10
  unless ShopifyCLI::Environment.development?
@@ -19,6 +24,10 @@ module ShopifyCLI
19
24
  return unless reportable_error?(error)
20
25
 
21
26
  return unless report?(context: context)
27
+ report_to_bugsnag(error: error, custom_metadata: custom_metadata)
28
+ end
29
+
30
+ def self.report_to_bugsnag(error:, custom_metadata: {})
22
31
  ENV["BUGSNAG_DISABLE_AUTOCONFIGURE"] = "1"
23
32
  require "bugsnag"
24
33
 
@@ -2,17 +2,28 @@ module ShopifyCLI
2
2
  module GitHub
3
3
  module IssueURLGenerator
4
4
  def self.error_url(error)
5
- title = "#{error.class}: #{error.message}"
5
+ title = "[Bug]: #{error.class}: #{error.message}"
6
6
  labels = "type:bug"
7
- content = File.read(File.join(ShopifyCLI::ROOT, ".github/ISSUE_TEMPLATE.md"))
8
7
 
9
8
  # take at most 5 lines from backtrace
10
- stacktrace = error.backtrace.length < 5 ? error.backtrace : error.backtrace[0..4]
11
- body = stacktrace.join("\n").to_s
12
- output = content.gsub(/<!--Stacktrace(.|\n)*-->/, body)
13
- query = URI.encode_www_form({ title: title, body: output, labels: labels })
14
- url = "#{ShopifyCLI::Constants::Links::NEW_ISSUE}?#{query}"
15
- url
9
+ stacktrace_text =
10
+ if error.backtrace # Sometimes errors seem to appear without backtrace, see https://github.com/Shopify/shopify-cli/issues/1972#issuecomment-1028013630
11
+ stacktrace = error.backtrace.length < 5 ? error.backtrace : error.backtrace[0..4]
12
+ stacktrace.join("\n").to_s
13
+ else
14
+ ""
15
+ end
16
+ query = URI.encode_www_form({
17
+ title: title,
18
+ labels: labels,
19
+ template: "bug_report.yaml",
20
+ stack_trace: stacktrace_text,
21
+ os: RUBY_PLATFORM,
22
+ cli_version: ShopifyCLI::VERSION,
23
+ ruby_version: "#{RUBY_VERSION}p#{RUBY_PATCHLEVEL}",
24
+ shell: ENV["SHELL"],
25
+ })
26
+ "#{ShopifyCLI::Constants::Links::NEW_ISSUE}?#{query}"
16
27
  end
17
28
  end
18
29
  end
@@ -0,0 +1,34 @@
1
+ module ShopifyCLI
2
+ class IdentityAuth
3
+ class EnvAuthToken
4
+ Token = Struct.new(:token, :expires_at, keyword_init: true)
5
+
6
+ class << self
7
+ attr_accessor :exchanged_partners_token
8
+
9
+ def partners_token_present?
10
+ Environment.auth_token
11
+ end
12
+
13
+ def fetch_exchanged_partners_token
14
+ current_time = Time.now.to_i
15
+
16
+ # If we have an in-memory token that hasn't expired yet, we reuse it.
17
+ if exchanged_partners_token && current_time < exchanged_partners_token.expires_at.to_i
18
+ return exchanged_partners_token.token
19
+ end
20
+
21
+ new_exchanged_token = yield(Environment.auth_token)
22
+ token = new_exchanged_token["access_token"]
23
+ expires_in = new_exchanged_token["expires_in"].to_i
24
+ expires_at = Time.at(current_time + expires_in)
25
+
26
+ token = Token.new(token: token, expires_at: expires_at)
27
+
28
+ self.exchanged_partners_token = token
29
+ token.token
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -13,6 +13,7 @@ module ShopifyCLI
13
13
  include SmartProperties
14
14
 
15
15
  autoload :Servlet, "shopify_cli/identity_auth/servlet"
16
+ autoload :EnvAuthToken, "shopify_cli/identity_auth/env_auth_token"
16
17
 
17
18
  class Error < StandardError; end
18
19
  class Timeout < StandardError; end
@@ -68,9 +69,12 @@ module ShopifyCLI
68
69
  request_exchange_tokens
69
70
  end
70
71
 
71
- def self.fetch_or_auth_partners_token(ctx:)
72
- env_var_auth_token = Environment.auth_token
73
- return env_var_auth_token if env_var_auth_token
72
+ def fetch_or_auth_partners_token
73
+ if EnvAuthToken.partners_token_present?
74
+ return EnvAuthToken.fetch_exchanged_partners_token do |env_token|
75
+ exchange_partners_auth_token(env_token)
76
+ end
77
+ end
74
78
 
75
79
  ShopifyCLI::DB.get(:partners_exchange_token) do
76
80
  IdentityAuth.new(ctx: ctx).authenticate
@@ -78,6 +82,15 @@ module ShopifyCLI
78
82
  end
79
83
  end
80
84
 
85
+ def exchange_partners_auth_token(subject_token)
86
+ application = "partners"
87
+ request_exchange_token(
88
+ audience: client_id_for_application(application),
89
+ scopes: APPLICATION_SCOPES[application],
90
+ subject_token: subject_token,
91
+ )
92
+ end
93
+
81
94
  def self.environment_auth_token?
82
95
  !!Environment.auth_token
83
96
  end
@@ -195,30 +208,35 @@ module ShopifyCLI
195
208
 
196
209
  def request_exchange_tokens
197
210
  APPLICATION_SCOPES.each do |key, scopes|
198
- request_exchange_token(key, client_id_for_application(key), scopes)
211
+ request_and_save_exchange_token(key, client_id_for_application(key), scopes)
199
212
  end
200
213
  end
201
214
 
202
- def request_exchange_token(name, audience, additional_scopes)
215
+ def request_and_save_exchange_token(name, audience, additional_scopes)
203
216
  return if name == "shopify" && !store.exists?(:shop)
217
+ access_token = request_exchange_token(
218
+ audience: audience,
219
+ scopes: scopes(additional_scopes),
220
+ subject_token: store.get(:identity_access_token),
221
+ destination: name == "shopify" ? "https://#{store.get(:shop)}/admin" : nil
222
+ )["access_token"]
223
+ store.set("#{name}_exchange_token".to_sym => access_token)
224
+ ctx.debug("#{name}_exchange_token: " + access_token)
225
+ end
204
226
 
227
+ def request_exchange_token(audience:, scopes:, subject_token:, destination: nil)
205
228
  params = {
206
229
  grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
207
230
  requested_token_type: "urn:ietf:params:oauth:token-type:access_token",
208
231
  subject_token_type: "urn:ietf:params:oauth:token-type:access_token",
209
232
  client_id: client_id,
210
233
  audience: audience,
211
- scope: scopes(additional_scopes),
212
- subject_token: store.get(:identity_access_token),
213
- }.tap do |result|
214
- if name == "shopify"
215
- result[:destination] = "https://#{store.get(:shop)}/admin"
216
- end
217
- end
234
+ scope: scopes,
235
+ subject_token: subject_token,
236
+ destination: destination,
237
+ }.compact
218
238
  # ctx.debug(params)
219
- resp = post_token_request(params)
220
- store.set("#{name}_exchange_token".to_sym => resp["access_token"])
221
- ctx.debug("#{name}_exchange_token: " + resp["access_token"])
239
+ post_token_request(params)
222
240
  end
223
241
 
224
242
  def post_token_request(params)
@@ -53,7 +53,7 @@ module ShopifyCLI
53
53
  {{command:--organization-id=ID}} Partner organization ID. Must be an existing organization.
54
54
  {{command:--store-domain=MYSHOPIFYDOMAIN }} Development store URL. Must be an existing development store.
55
55
  {{command:--db=DB}} Database type. Must be one of: mysql, postgresql, sqlite3, oracle, frontbase, ibm_db, sqlserver, jdbcmysql, jdbcsqlite3, jdbcpostgresql, jdbc.
56
- {{command:--rails-opts=RAILSOPTS}} Additional options. Must be string containing one or more valid Rails options, separated by spaces.
56
+ {{command:--rails-opts=RAILSOPTS}} Additional options. Must be a string containing one or more valid Rails options, separated by spaces.
57
57
  HELP
58
58
 
59
59
  error: {
@@ -38,7 +38,11 @@ module ShopifyCLI
38
38
  def query(ctx, query_name, **variables)
39
39
  CLI::Kit::Util.begin do
40
40
  api_client(ctx).query(query_name, variables: variables)
41
- end.retry_after(API::APIRequestUnauthorizedError, retries: 1) do
41
+ end.retry_after(
42
+ API::APIRequestUnauthorizedError,
43
+ retries: 1,
44
+ only: -> { !IdentityAuth::EnvAuthToken.partners_token_present? }
45
+ ) do
42
46
  ShopifyCLI::IdentityAuth.new(ctx: ctx).reauthenticate
43
47
  end
44
48
  rescue API::APIRequestUnauthorizedError => e
@@ -60,9 +64,10 @@ module ShopifyCLI
60
64
  private
61
65
 
62
66
  def api_client(ctx)
67
+ identity_auth = ShopifyCLI::IdentityAuth.new(ctx: ctx)
63
68
  new(
64
69
  ctx: ctx,
65
- token: IdentityAuth.fetch_or_auth_partners_token(ctx: ctx),
70
+ token: identity_auth.fetch_or_auth_partners_token,
66
71
  url: "https://#{Environment.partners_domain}/api/cli/graphql",
67
72
  )
68
73
  end
@@ -41,12 +41,7 @@ module ShopifyCLI
41
41
 
42
42
  raise ShopifyCLI::AbortSilent if form.nil?
43
43
 
44
- ruby_version = Rails::Ruby.version(context)
45
- context.abort(context.message("core.app.create.rails.error.invalid_ruby_version")) unless
46
- ruby_version.satisfies?("~>2.5") || ruby_version.satisfies?("~>3.0.0")
47
-
48
- check_node
49
- check_yarn
44
+ check_dependencies
50
45
 
51
46
  build(form.name, form.db)
52
47
  set_custom_ua
@@ -106,6 +101,18 @@ module ShopifyCLI
106
101
  end
107
102
  end
108
103
 
104
+ def check_dependencies
105
+ check_ruby
106
+ check_node
107
+ check_yarn
108
+ end
109
+
110
+ def check_ruby
111
+ ruby_version = Rails::Ruby.version(context)
112
+ return if ruby_version.satisfies?("~>2.5") || ruby_version.satisfies?("~>3.0.0")
113
+ context.abort(context.message("core.app.create.rails.error.invalid_ruby_version"))
114
+ end
115
+
109
116
  def check_node
110
117
  cmd_path = context.which("node")
111
118
  if cmd_path.nil?
@@ -148,11 +155,13 @@ module ShopifyCLI
148
155
  end
149
156
 
150
157
  def build(name, db)
151
- context.abort(context.message("core.app.create.rails.error.install_failure",
152
- "rails")) unless install_gem("rails",
153
- "<6.1")
154
- context.abort(context.message("core.app.create.rails.error.install_failure", "bundler ~>2.0")) unless
155
- install_gem("bundler", "~>2.0")
158
+ unless install_gem("rails")
159
+ context.abort(context.message("core.app.create.rails.error.install_failure", "rails"))
160
+ end
161
+
162
+ unless install_gem("bundler", "~>2.0")
163
+ context.abort(context.message("core.app.create.rails.error.install_failure", "bundler ~>2.0"))
164
+ end
156
165
 
157
166
  full_path = File.join(context.root, name)
158
167
  context.abort(context.message("core.app.create.rails.error.dir_exists", name)) if Dir.exist?(full_path)
@@ -173,7 +182,7 @@ module ShopifyCLI
173
182
 
174
183
  context.puts(context.message("core.app.create.rails.adding_shopify_gem"))
175
184
  File.open(File.join(context.root, "Gemfile"), "a") do |f|
176
- f.puts "\ngem 'shopify_app', '>=17.0.3'"
185
+ f.puts "\ngem 'shopify_app', '>=18.1.0'"
177
186
  end
178
187
  CLI::UI::Frame.open(context.message("core.app.create.rails.running_bundle_install")) do
179
188
  syscall(%w(bundle install))
@@ -188,7 +197,7 @@ module ShopifyCLI
188
197
  syscall(%w(rails db:migrate RAILS_ENV=development))
189
198
  end
190
199
 
191
- unless File.exist?(File.join(context.root, "config/webpacker.yml"))
200
+ if install_webpacker?
192
201
  CLI::UI::Frame.open(context.message("core.app.create.rails.running_webpacker_install")) do
193
202
  syscall(%w(rails webpacker:install))
194
203
  end
@@ -208,6 +217,21 @@ module ShopifyCLI
208
217
  def install_gem(name, version = nil)
209
218
  Rails::Gem.install(context, name, version)
210
219
  end
220
+
221
+ def install_webpacker?
222
+ rails_version < ::Semantic::Version.new("7.0.0") &&
223
+ !File.exist?(File.join(context.root, "config/webpacker.yml"))
224
+ end
225
+
226
+ def rails_version
227
+ output, status = context.capture2e("rails", "--version")
228
+ unless status.success?
229
+ context.abort(context.message("core.app.create.rails.error.install_failure", "rails"))
230
+ end
231
+
232
+ version = output.scan(/Rails \d+\.\d+\.\d+/).first.split(" ").last
233
+ ::Semantic::Version.new(version)
234
+ end
211
235
  end
212
236
  end
213
237
  end
@@ -7,36 +7,58 @@ module ShopifyCLI
7
7
  class IncludeFilter
8
8
  include Filter::PathMatcher
9
9
 
10
- def initialize(pattern = nil)
11
- @pattern = pattern
10
+ attr_reader :globs, :regexes
11
+
12
+ def initialize(patterns = [])
13
+ @patterns = patterns.nil? ? [] : patterns.compact.reject(&:empty?)
14
+
15
+ regexes, globs = patterns_to_regexes_and_globs(@patterns)
16
+
17
+ @regexes = regexes
18
+ @globs = globs
12
19
  end
13
20
 
14
21
  def match?(path)
15
- return true unless present?(@pattern)
22
+ return true unless present?(@patterns)
23
+
24
+ path = path.to_s
25
+
26
+ return true if path.empty?
16
27
 
17
- if regex_pattern?
18
- regex_match?(regex_pattern, path)
19
- else
20
- glob_match?(glob_pattern, path)
28
+ regexes.each do |regex|
29
+ return true if regex_match?(regex, path)
21
30
  end
31
+
32
+ globs.each do |glob|
33
+ return true if glob_match?(glob, path)
34
+ end
35
+
36
+ false
22
37
  end
23
38
 
24
39
  private
25
40
 
26
- def present?(pattern)
27
- !pattern.nil? && !pattern.empty?
41
+ def present?(patterns)
42
+ !patterns.nil? && !patterns.empty?
28
43
  end
29
44
 
30
- def regex_pattern?
31
- @is_regex_pattern ||= regex?(@pattern)
32
- end
45
+ # Take in string patterns and convert them to either
46
+ # regex patterns or glob patterns so that they are handled in an expected manner.
47
+ def patterns_to_regexes_and_globs(patterns)
48
+ new_regexes = []
49
+ new_globs = []
33
50
 
34
- def regex_pattern
35
- @regex_pattern ||= as_regex(@pattern)
36
- end
51
+ patterns
52
+ .map(&:strip)
53
+ .each do |pattern|
54
+ if regex?(pattern)
55
+ new_regexes << as_regex(pattern)
56
+ else
57
+ new_globs << as_glob(pattern)
58
+ end
59
+ end
37
60
 
38
- def glob_pattern
39
- @glob_pattern ||= as_glob(@pattern)
61
+ [new_regexes, new_globs]
40
62
  end
41
63
  end
42
64
  end
@@ -0,0 +1,7 @@
1
+ module ShopifyCLI
2
+ module Utilities
3
+ def self.version_dropping_pre_and_build(version)
4
+ Semantic::Version.new("#{version.major}.#{version.minor}.#{version.patch}")
5
+ end
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module ShopifyCLI
2
- VERSION = "2.10.2"
2
+ VERSION = "2.11.0"
3
3
  end
data/lib/shopify_cli.rb CHANGED
@@ -136,6 +136,7 @@ module ShopifyCLI
136
136
  autoload :Tasks, "shopify_cli/tasks"
137
137
  autoload :TransformDataStructure, "shopify_cli/transform_data_structure"
138
138
  autoload :Tunnel, "shopify_cli/tunnel"
139
+ autoload :Utilities, "shopify_cli/utilities"
139
140
 
140
141
  require "shopify_cli/messages/messages"
141
142
  Context.load_messages(ShopifyCLI::Messages::MESSAGES)
@@ -227,7 +227,7 @@ module CLI
227
227
  end
228
228
 
229
229
  def which(cmd, env)
230
- exts = os == :windows ? env.fetch('PATHEXT', ['']).split(';') : ['']
230
+ exts = (os == :windows && env['PATHEXT']&.split(';')) || ['']
231
231
  env.fetch('PATH', '').split(File::PATH_SEPARATOR).each do |path|
232
232
  exts.each do |ext|
233
233
  exe = File.join(path, "#{cmd}#{ext}")
@@ -168,9 +168,13 @@ module CLI
168
168
  @block_that_might_raise = block_that_might_raise
169
169
  end
170
170
 
171
- def retry_after(exception = StandardError, retries: 1, &before_retry)
171
+ def retry_after(exception = StandardError, retries: 1, only: nil, &before_retry)
172
172
  @block_that_might_raise.call
173
173
  rescue exception => e
174
+ should_retry = only ? only.call : true
175
+
176
+ raise unless should_retry
177
+
174
178
  raise if (retries -= 1) < 0
175
179
  if before_retry
176
180
  if before_retry.arity == 0
@@ -21,7 +21,6 @@ module Semantic
21
21
  @version = version_str
22
22
  end
23
23
 
24
-
25
24
  def build=(b)
26
25
  @build = (!b.nil? && b.empty?) ? nil : b
27
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.10.2
4
+ version: 2.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-31 00:00:00.000000000 Z
11
+ date: 2022-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -118,6 +118,9 @@ files:
118
118
  - ".github/CONTRIBUTING.md"
119
119
  - ".github/DESIGN.md"
120
120
  - ".github/ISSUE_TEMPLATE.md"
121
+ - ".github/ISSUE_TEMPLATE/bug_report.yaml"
122
+ - ".github/ISSUE_TEMPLATE/enhancement.yaml"
123
+ - ".github/ISSUE_TEMPLATE/feature.yaml"
121
124
  - ".github/PULL_REQUEST_TEMPLATE.md"
122
125
  - ".github/probots.yml"
123
126
  - ".github/workflows/shopify.yml"
@@ -273,7 +276,6 @@ files:
273
276
  - lib/project_types/php/forms/create.rb
274
277
  - lib/project_types/php/messages/messages.rb
275
278
  - lib/project_types/rails/cli.rb
276
- - lib/project_types/rails/commands/create.rb
277
279
  - lib/project_types/rails/forms/create.rb
278
280
  - lib/project_types/rails/gem.rb
279
281
  - lib/project_types/rails/messages/messages.rb
@@ -405,6 +407,7 @@ files:
405
407
  - lib/shopify_cli/heroku.rb
406
408
  - lib/shopify_cli/http_request.rb
407
409
  - lib/shopify_cli/identity_auth.rb
410
+ - lib/shopify_cli/identity_auth/env_auth_token.rb
408
411
  - lib/shopify_cli/identity_auth/servlet.rb
409
412
  - lib/shopify_cli/js_deps.rb
410
413
  - lib/shopify_cli/js_system.rb
@@ -488,6 +491,7 @@ files:
488
491
  - lib/shopify_cli/thread_pool/job.rb
489
492
  - lib/shopify_cli/transform_data_structure.rb
490
493
  - lib/shopify_cli/tunnel.rb
494
+ - lib/shopify_cli/utilities.rb
491
495
  - lib/shopify_cli/version.rb
492
496
  - shopify-cli.gemspec
493
497
  - shopify-dev