shopify-cli 2.31.0 → 2.32.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 671907fe67b2c0ee4ff9c99a55bfbf53562f15f7540c23c6fb07ddb9b46398df
4
- data.tar.gz: 5a327f5060b50fa1761a20d5ca1601cab1fc44e7f3e1b7ab62e6747b9a92a164
3
+ metadata.gz: cedba2d3c1257478768278fcf18b239d18d49b56dd11ce9cb4eb60810f9bd46c
4
+ data.tar.gz: 252212433092e2df2f821782a58b57f8864bac936d04cac6f51a74a1891b3e59
5
5
  SHA512:
6
- metadata.gz: 2baa5372dc8502fe0764378b556b043eb136415ee9f94f1ea42fead7e367f46bdc0114b6e79f0eef99cb92270117561f004d09157e9bce3b45912aaead4bd20a
7
- data.tar.gz: 42819560813ed73fc39d09e68d5e7d07a68ca6b70af5666abca8741740f6d2fb912d500a28bd5ba9dbcb076ad0f9444097157a778cabd506abca06c6db302021
6
+ metadata.gz: c8d241e1d4353e2dd8e750fb81b47f936a9c35e7117e785ca50444acbf918956925a04657229b2afd84e8bad930d7bdd9cfe5cd0e67f6cf055f6899f91f27d0a
7
+ data.tar.gz: b3eb6d62f7fbc3c566161a8a1c09ed5d7679eda82a81eb0622fe7cc7ef9af391677f8281795fbff40ddec5b63fc529381165de02a91103fc851e96b2baa84d7c
data/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@ From version 2.6.0, the sections in this file adhere to the [keep a changelog](h
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## Version 2.32.1 - 2022-12-05
6
+
7
+ ### Fixed
8
+ * [#2694](https://github.com/Shopify/shopify-cli/pull/2694): Add sunset warnings
9
+
10
+ ## Version 2.32.0 - 2022-11-14
11
+
12
+ ### Added
13
+ * [#2680](https://github.com/Shopify/shopify-cli/pull/2680): Validate on `shopify theme share/pull/push/serve` if users are running the command in a theme/empty directory
14
+
15
+ ### Fixed
16
+ * [#2683](https://github.com/Shopify/shopify-cli/pull/2683): Fix timeout issue with the `shopify theme push` command and the `--json` flag
17
+ * [#2688](https://github.com/Shopify/shopify-cli/pull/2688): Fix `shopify theme push` to report pushes with errors
18
+
5
19
  ## Version 2.31.0 - 2022-11-07
6
20
 
7
21
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shopify-cli (2.31.0)
4
+ shopify-cli (2.32.1)
5
5
  bugsnag (~> 6.22)
6
6
  listen (~> 3.7.0)
7
7
  theme-check (~> 1.11.0)
@@ -101,7 +101,7 @@ GEM
101
101
  mocha (1.13.0)
102
102
  multi_test (0.1.2)
103
103
  multipart-post (2.1.1)
104
- nokogiri (1.13.8)
104
+ nokogiri (1.13.9)
105
105
  mini_portile2 (~> 2.8.0)
106
106
  racc (~> 1.4)
107
107
  octokit (4.22.0)
data/README.md CHANGED
@@ -11,17 +11,11 @@
11
11
  <img src="https://img.shields.io/badge/License-MIT-green.svg" alt="License">
12
12
  <img src="https://img.shields.io/badge/Powered%20by-Ruby-red" alt="Powered by Ruby">
13
13
 
14
-
15
14
  Shopify CLI 2.0 is a command line to help you build on Shopify. It's available as a Ruby gem and can be run and installed on Mac, Linux, and Windows systems.
16
15
 
17
- ## Note on Shopify CLI 2.0 versus Shopify CLI 3.0 ##
18
-
19
- Use 2.0 for developing themes. For developing apps and custom storefronts, we recommend using [Shopify CLI 3.0](https://github.com/Shopify/cli).
20
-
21
-
22
- ## Installation
16
+ ## CLI Deprecation & Sunset
23
17
 
24
- Check out our [installation steps](docs/users/installation.md).
18
+ Note that Shopify 2.0 is deprecated and will be [sunset on May 31, 2023](https://shopify.dev/changelog/cli-2-0-to-be-sunset-on-may-31-2023). We encourage using [Shopify CLI 3.0](https://github.com/Shopify/cli) to develop apps, custom storefronts, and themes.
25
19
 
26
20
  ## Contributing 👩‍💻
27
21
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "project_types/theme/models/specification_handlers/theme"
4
+
3
5
  module Theme
4
6
  class Command
5
7
  module Common
@@ -35,8 +37,28 @@ module Theme
35
37
  "."
36
38
  end
37
39
 
40
+ def valid_theme_directory?(root)
41
+ Theme::Models::SpecificationHandlers::Theme.new(root).valid? ||
42
+ current_directory_confirmed?
43
+ end
44
+
45
+ def exist_and_not_empty?(root)
46
+ Dir.exist?(root) && !Dir[File.join(root, "*")].empty?
47
+ end
48
+
38
49
  private
39
50
 
51
+ def current_directory_confirmed?
52
+ raise "Current theme directory can't be confirmed during tests" if @ctx.testing?
53
+
54
+ Forms::ConfirmStore.ask(
55
+ @ctx,
56
+ [],
57
+ title: @ctx.message("theme.confirm_current_directory"),
58
+ force: options.flags[:force],
59
+ ).confirmed?
60
+ end
61
+
40
62
  def default_argv(options)
41
63
  options.parser.default_argv.compact
42
64
  end
@@ -34,10 +34,13 @@ module Theme
34
34
  flags[:ignores] ||= []
35
35
  flags[:ignores] |= pattern
36
36
  end
37
+ parser.on("-f", "--force") { flags[:force] = true }
37
38
  end
38
39
 
39
40
  def call(_args, name)
40
41
  root = root_value(options, name)
42
+ return if exist_and_not_empty?(root) && !valid_theme_directory?(root)
43
+
41
44
  delete = !options.flags[:nodelete]
42
45
  theme = find_theme(root, **options.flags)
43
46
  return if theme.nil?
@@ -39,10 +39,13 @@ module Theme
39
39
  flags[:ignores] ||= []
40
40
  flags[:ignores] |= pattern
41
41
  end
42
+ parser.on("-f", "--force") { flags[:force] = true }
42
43
  end
43
44
 
44
45
  def call(_args, name)
45
46
  root = root_value(options, name)
47
+ return unless valid_theme_directory?(root)
48
+
46
49
  delete = !options.flags[:nodelete]
47
50
  theme = find_theme(root, **options.flags)
48
51
  return if theme.nil?
@@ -34,12 +34,15 @@ module Theme
34
34
  flags[:ignores] ||= []
35
35
  flags[:ignores] |= pattern
36
36
  end
37
+ parser.on("-f", "--force") { flags[:force] = true }
37
38
  end
38
39
 
39
40
  def call(_args, name)
40
41
  valid_authentication_method!
41
42
 
42
43
  root = root_value(options, name)
44
+ return unless valid_theme_directory?(root)
45
+
43
46
  flags = options.flags.dup
44
47
  host = flags[:host] || DEFAULT_HTTP_HOST
45
48
 
@@ -11,8 +11,14 @@ module Theme
11
11
 
12
12
  recommend_default_ruby_range
13
13
 
14
+ options do |parser, flags|
15
+ parser.on("-f", "--force") { flags[:force] = true }
16
+ end
17
+
14
18
  def call(_args, name)
15
19
  root = root_value(options, name)
20
+ return unless valid_theme_directory?(root)
21
+
16
22
  theme = create_theme(root)
17
23
 
18
24
  upload(theme)
@@ -18,6 +18,8 @@ module Theme
18
18
  ENSURE_USER
19
19
  stable_flag_suggestion: "If the current command isn't working as expected," \
20
20
  " we suggest re-running the command with the {{command: --stable}} flag",
21
+ confirm_current_directory: "It doesn’t seem like you’re running this command in a theme directory. " \
22
+ "Are you sure you want to proceed?",
21
23
  init: {
22
24
  help: <<~HELP,
23
25
  {{command:%s theme init}}: Clones a Git repository to use as a starting point for building a new theme.
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Theme
4
+ module Models
5
+ module SpecificationHandlers
6
+ class Theme
7
+ REQUIRED_FOLDERS = %w(config layout sections templates)
8
+
9
+ def initialize(root)
10
+ @root = root
11
+ end
12
+
13
+ def valid?
14
+ REQUIRED_FOLDERS.all? { |required_folder| Dir.exist?(File.join(@root, required_folder)) }
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -5,28 +5,7 @@ module ShopifyCLI
5
5
  module EntryPoint
6
6
  class << self
7
7
  def call(args, ctx = Context.new)
8
- # Only instruct the user to update the CLI, or warn them that they're
9
- # using CLI2 not CLI3, if they're running CLI2 directly. Otherwise the
10
- # warnings will be confusing and/or incorrect.
11
- unless Environment.run_as_subprocess?
12
- if ctx.development? && !ctx.testing?
13
- ctx.warn(
14
- ctx.message(
15
- "core.warning.development_version",
16
- File.join(ShopifyCLI::ROOT, "bin", ShopifyCLI::TOOL_NAME)
17
- )
18
- )
19
- # because `!ctx.new_version.nil?` will change the config by calling ::Config.set
20
- # it's important to keep the checks in this order so that we don't trigger it while testing
21
- # since changing the config will throw errors
22
- elsif !ctx.testing? && !ctx.new_version.nil?
23
- ctx.warn(ctx.message("core.warning.new_version", ShopifyCLI::VERSION, ctx.new_version))
24
- end
25
-
26
- if ShopifyCLI::Core::CliVersion.using_3_0?
27
- ctx.warn(ctx.message("core.warning.in_3_0_directory"))
28
- end
29
- end
8
+ show_warnings(ctx, args.join(" "))
30
9
 
31
10
  ProjectType.load_all
32
11
 
@@ -38,6 +17,47 @@ module ShopifyCLI
38
17
  executor.call(command, command_name, args)
39
18
  end
40
19
  end
20
+
21
+ def show_warnings(ctx, args)
22
+ # Only instruct the user to update the CLI, or warn them that they're
23
+ # using CLI2 not CLI3, if they're running CLI2 directly. Otherwise the
24
+ # warnings will be confusing and/or incorrect.
25
+ return if Environment.run_as_subprocess?
26
+
27
+ show_sunset_warning(ctx, args)
28
+
29
+ if ctx.development? && !ctx.testing?
30
+ ctx.warn(
31
+ ctx.message(
32
+ "core.warning.development_version",
33
+ File.join(ShopifyCLI::ROOT, "bin", ShopifyCLI::TOOL_NAME)
34
+ )
35
+ )
36
+ # because `!ctx.new_version.nil?` will change the config by calling ::Config.set
37
+ # it's important to keep the checks in this order so that we don't trigger it while testing
38
+ # since changing the config will throw errors
39
+ elsif !ctx.testing? && !ctx.new_version.nil?
40
+ ctx.warn(ctx.message("core.warning.new_version", ShopifyCLI::VERSION, ctx.new_version))
41
+ end
42
+
43
+ if ShopifyCLI::Core::CliVersion.using_3_0?
44
+ ctx.warn(ctx.message("core.warning.in_3_0_directory"))
45
+ end
46
+ end
47
+
48
+ def show_sunset_warning(ctx, args)
49
+ return if ctx.testing?
50
+
51
+ if args.start_with?("app create") || args.start_with?("app extension create")
52
+ ctx.warn(ctx.message("core.warning.sunset_create_app"))
53
+ elsif args.start_with?("app")
54
+ ctx.warn(ctx.message("core.warning.sunset_app"))
55
+ elsif args.start_with?("theme")
56
+ ctx.warn(ctx.message("core.warning.sunset_theme"))
57
+ else
58
+ ctx.warn(ctx.message("core.warning.sunset"))
59
+ end
60
+ end
41
61
  end
42
62
  end
43
63
  end
@@ -804,6 +804,22 @@ module ShopifyCLI
804
804
  Already have CLI 3.0 installed? Run it using your node package manager, as explained here:
805
805
  {{underline:https://shopify.dev/apps/tools/cli/cli-2#running-shopify-cli-2-x-and-3-x-in-the-same-environment}}
806
806
  MESSAGE
807
+
808
+ sunset: <<~MESSAGE,
809
+ {{*}} {{yellow:Note that CLI 2.x will be sunset on May 31, 2023.}}
810
+ MESSAGE
811
+
812
+ sunset_create_app: <<~MESSAGE,
813
+ {{*}} {{yellow:Note that this CLI 2.x command will be sunset on April 28, 2023. Check here for instructions on how to migrate over to CLI 3.x: {{underline:https://shopify.dev/apps/tools/cli/migrate}}.}}
814
+ MESSAGE
815
+
816
+ sunset_app: <<~MESSAGE,
817
+ {{*}} {{yellow:Note that CLI 2.x will be sunset on May 31, 2023. Check here for instructions on how to migrate over to CLI 3.x: {{underline:https://shopify.dev/apps/tools/cli/migrate}}.}}
818
+ MESSAGE
819
+
820
+ sunset_theme: <<~MESSAGE,
821
+ {{*}} {{yellow:Note that CLI 2.x will be sunset on May 31, 2023. Check here for instructions on how to migrate over to CLI 3.x: {{underline:https://shopify.dev/themes/tools/cli/migrate}}.}}
822
+ MESSAGE
807
823
  },
808
824
  reporting: {
809
825
  help: <<~HELP,
@@ -26,13 +26,11 @@ module ShopifyCLI
26
26
  :ignore_file?,
27
27
  :overwrite_json?,
28
28
  :bulk_updates_activated?,
29
-
30
29
  # enqueue
31
30
  :enqueue_deletes,
32
31
  :enqueue_get,
33
32
  :enqueue_union_merges,
34
33
  :enqueue_updates,
35
-
36
34
  # checksums
37
35
  :checksums,
38
36
  :update_checksums,
@@ -112,7 +110,7 @@ module ShopifyCLI
112
110
  retries = 0
113
111
  pending_items = files.map { |file| bulk_item(file) }
114
112
 
115
- while pending_items.any? && retries < 4
113
+ while pending_items.any? && retries < 2
116
114
  bulk = Bulk.new(ctx, theme, api_client)
117
115
 
118
116
  files
@@ -183,7 +181,7 @@ module ShopifyCLI
183
181
  [
184
182
  theme["config/settings_schema.json"],
185
183
  theme["config/settings_data.json"],
186
- ]
184
+ ],
187
185
  )
188
186
  end
189
187
 
@@ -212,13 +210,19 @@ module ShopifyCLI
212
210
  end
213
211
 
214
212
  def update_progress_bar(size, total)
215
- @update_progress_bar_block.call(size, total)
213
+ @update_progress_bar_block&.call(size, total)
216
214
  end
217
215
 
218
216
  # Handler errors
219
217
 
220
- def report(file, _error)
221
- error_message = "The asset #{file.relative_path} could not be uploaded.\n#{e.inspect}"
218
+ def report(file, error)
219
+ file_path = file.relative_path
220
+
221
+ error_message = syncer
222
+ .parse_api_errors(file, error)
223
+ .map { |msg| "#{file_path}: #{msg}" }
224
+ .join("\n")
225
+
222
226
  syncer.report_file_error(file, error_message)
223
227
  end
224
228
  end
@@ -121,6 +121,7 @@ module ShopifyCLI
121
121
 
122
122
  def wait!
123
123
  raise ThreadError, "No syncer threads" if @threads.empty?
124
+
124
125
  total = size
125
126
  last_size = size
126
127
  until empty? || @queue.closed?
@@ -134,7 +135,7 @@ module ShopifyCLI
134
135
 
135
136
  def fetch_checksums!
136
137
  _status, response = api_client.get(
137
- path: "themes/#{@theme.id}/assets.json"
138
+ path: "themes/#{@theme.id}/assets.json",
138
139
  )
139
140
  update_checksums(response)
140
141
  end
@@ -151,6 +152,7 @@ module ShopifyCLI
151
152
  loop do
152
153
  operation = @queue.pop
153
154
  break if operation.nil? # shutdown was called
155
+
154
156
  perform(operation)
155
157
  rescue Exception => e # rubocop:disable Lint/RescueException
156
158
  error_suffix = ": #{e}"
@@ -195,7 +197,7 @@ module ShopifyCLI
195
197
  end
196
198
 
197
199
  def handle_operation_error(operation, error)
198
- error_suffix = ":\n " + parse_api_errors(operation, error).join("\n ")
200
+ error_suffix = ":\n " + parse_api_errors(operation.file, error).join("\n ")
199
201
  report_error(operation, error_suffix)
200
202
  end
201
203
 
@@ -206,6 +208,7 @@ module ShopifyCLI
206
208
  def update_checksums(api_response)
207
209
  api_response.values.flatten.each do |asset|
208
210
  next unless asset["key"]
211
+
209
212
  checksums[asset["key"]] = asset["checksum"]
210
213
  end
211
214
 
@@ -219,6 +222,33 @@ module ShopifyCLI
219
222
  @error_reporter.report(error_message)
220
223
  end
221
224
 
225
+ def parse_api_errors(file, exception)
226
+ parsed_body = {}
227
+
228
+ if exception.respond_to?(:response)
229
+ response = exception.response
230
+
231
+ parsed_body = if response&.is_a?(Hash)
232
+ response&.[](:body)
233
+ else
234
+ JSON.parse(response&.body)
235
+ end
236
+ end
237
+
238
+ errors = parsed_body.dig("errors") # either nil or another type
239
+ errors = errors.dig("asset") if errors&.is_a?(Hash)
240
+
241
+ message = errors || parsed_body["message"] || exception.message
242
+ # Truncate to first lines
243
+ [message].flatten.map { |m| m.split("\n", 2).first }
244
+ rescue JSON::ParserError
245
+ [exception.message]
246
+ rescue StandardError => e
247
+ cause = "(cause: #{e.message})"
248
+ backtrace = e.backtrace.join("\n")
249
+ ["The asset #{file} could not be synced #{cause} #{backtrace}"]
250
+ end
251
+
222
252
  private
223
253
 
224
254
  def report_error(operation, error_suffix = "")
@@ -256,6 +286,7 @@ module ShopifyCLI
256
286
 
257
287
  def perform(operation)
258
288
  return if @queue.closed?
289
+
259
290
  wait_for_backoff!
260
291
  @ctx.debug(operation.to_s)
261
292
 
@@ -263,7 +294,6 @@ module ShopifyCLI
263
294
 
264
295
  report_performed_operation(operation)
265
296
  backoff_if_near_limit!(response)
266
-
267
297
  rescue StandardError => error
268
298
  handle_operation_error(operation, error)
269
299
  ensure
@@ -283,7 +313,7 @@ module ShopifyCLI
283
313
 
284
314
  _status, body, response = api_client.put(
285
315
  path: path,
286
- body: JSON.generate(asset: asset)
316
+ body: JSON.generate(asset: asset),
287
317
  )
288
318
  file.warnings = body.dig("asset", "warnings")
289
319
 
@@ -315,7 +345,7 @@ module ShopifyCLI
315
345
  path: "themes/#{@theme.id}/assets.json",
316
346
  body: JSON.generate(asset: {
317
347
  key: file.relative_path,
318
- })
348
+ }),
319
349
  )
320
350
 
321
351
  response
@@ -342,33 +372,6 @@ module ShopifyCLI
342
372
  response
343
373
  end
344
374
 
345
- def parse_api_errors(operation, exception)
346
- parsed_body = {}
347
-
348
- if exception.respond_to?(:response)
349
- response = exception.response
350
-
351
- parsed_body = if response&.is_a?(Hash)
352
- response&.[](:body)
353
- else
354
- JSON.parse(response&.body)
355
- end
356
- end
357
-
358
- errors = parsed_body.dig("errors") # either nil or another type
359
- errors = errors.dig("asset") if errors&.is_a?(Hash)
360
-
361
- message = errors || parsed_body["message"] || exception.message
362
- # Truncate to first lines
363
- [message].flatten.map { |m| m.split("\n", 2).first }
364
- rescue JSON::ParserError
365
- [exception.message]
366
- rescue StandardError => e
367
- cause = "(cause: #{e.message})"
368
- backtrace = e.backtrace.join("\n")
369
- ["The asset #{operation.file} could not be synced #{cause} #{backtrace}"]
370
- end
371
-
372
375
  def theme_created_at_runtime?
373
376
  @theme.created_at_runtime?
374
377
  end
@@ -61,6 +61,7 @@ module ShopifyCLI
61
61
  if empty_response?(error)
62
62
  return permission_error
63
63
  elsif unauthorized_response?(error)
64
+ @ctx.debug("[#{self.class}] (#{error.class}) cause: #{response_body(error)}")
64
65
  raise ShopifyCLI::Abort, @ctx.message("theme.unauthorized_error", @shop)
65
66
  end
66
67
 
@@ -1,3 +1,3 @@
1
1
  module ShopifyCLI
2
- VERSION = "2.31.0"
2
+ VERSION = "2.32.1"
3
3
  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.31.0
4
+ version: 2.32.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-07 00:00:00.000000000 Z
11
+ date: 2022-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -328,6 +328,7 @@ files:
328
328
  - lib/project_types/theme/forms/confirm_store.rb
329
329
  - lib/project_types/theme/forms/select.rb
330
330
  - lib/project_types/theme/messages/messages.rb
331
+ - lib/project_types/theme/models/specification_handlers/theme.rb
331
332
  - lib/project_types/theme/presenters/theme_presenter.rb
332
333
  - lib/project_types/theme/presenters/themes_presenter.rb
333
334
  - lib/project_types/theme/ui/sync_progress_bar.rb