shopify-cli 2.20.0 → 2.22.0

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: 9fb2bcf8db165a28ff5753227eb1aae9d2d83e65e8a2cee8a8a2ed4e7f8d7d4b
4
- data.tar.gz: 5ab1e805308119941d84932997959926011281ea4a2b48d5517ca43c3794661c
3
+ metadata.gz: 4fdf2b1a1c6ff2b21a3adb26654fda425436a5660d27b487dd1473fc2530b02c
4
+ data.tar.gz: 572fa0ba305ec75391c3aac020f1bb72c0874a8d138c7b05da8aaf0fdba68719
5
5
  SHA512:
6
- metadata.gz: a6c2ba75cadbc318cae8615890386c1c3aa8100405d12e070627470448d367daf96a65390e6afad6b6d70ae8bdbc7e27f8d7dbdccf5b69e4fde12f6bca681b94
7
- data.tar.gz: 66699ed47aa46b23f3dfe4dba39a9e15c23e135db254a22db2e4800d0865be49b23bca70eb9733a497bd2a87a2e8aa6db00e887da53a4f83881f719983eda906
6
+ metadata.gz: bb78577fab62082d1fb27eacb1865a690c04a8985fea4af5684399e84a942d025e79b36792c1c382704231f8e73c67e71edd9cd055898de0aa48099b2d5dfb2e
7
+ data.tar.gz: 7e19eb12d7e1cfc5d22002bde244451f21277547180a13617f3211de1b657099e12b85efa46ce8f5649954336cd24c672c98e9ac807af00212f7ea921e57f37f
@@ -0,0 +1,22 @@
1
+ name: Contributor License Agreement (CLA)
2
+
3
+ on:
4
+ pull_request_target:
5
+ types: [opened, synchronize]
6
+ issue_comment:
7
+ types: [created]
8
+
9
+ jobs:
10
+ cla:
11
+ runs-on: ubuntu-latest
12
+ if: |
13
+ (github.event.issue.pull_request
14
+ && !github.event.issue.pull_request.merged_at
15
+ && contains(github.event.comment.body, 'signed')
16
+ )
17
+ || (github.event.pull_request && !github.event.pull_request.merged)
18
+ steps:
19
+ - uses: Shopify/shopify-cla-action@v1
20
+ with:
21
+ github-token: ${{ secrets.GITHUB_TOKEN }}
22
+ cla-token: ${{ secrets.CLA_TOKEN }}
@@ -22,7 +22,6 @@ jobs:
22
22
  - 2.6.6
23
23
  - 2.7.5
24
24
  os:
25
- - macos-10.15
26
25
  - macos-11
27
26
  - ubuntu-20.04
28
27
  - ubuntu-18.04
data/CHANGELOG.md CHANGED
@@ -2,6 +2,30 @@ 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.22.0 - 2022-08-08
6
+
7
+ ### Fixed
8
+ * [#2512](https://github.com/Shopify/shopify-cli/pull/2512): Add the `-t/--theme` parameter to the `shopify theme serve -h` message
9
+ * [#2505](https://github.com/Shopify/shopify-cli/pull/2505): Show warning messages when `shopify theme push/pull` has errors
10
+
11
+ ## Version 2.21.0 - 2022-08-03
12
+
13
+ ### Fixed
14
+ * [#2453](https://github.com/Shopify/shopify-cli/pull/2453): Fix [#2382](https://github.com/Shopify/shopify-cli/issues/2382): Ensure we wait 24 hours to show update message again
15
+ * [#2463](https://github.com/Shopify/shopify-cli/pull/2463): Fix for "Keep the remote version" deletes files on new development theme
16
+ * [#2405](https://github.com/Shopify/shopify-cli/pull/2405): Fix `theme serve` to trigger page refresh when a file is deleted
17
+ * [#2489](https://github.com/Shopify/shopify-cli/pull/2489): Fix `theme serve` to hot reload many occurrences of a stylesheet
18
+
19
+ ### Added
20
+ * [#2496](https://github.com/Shopify/shopify-cli/pull/2496): Accept storefront renderer token from ENV variable
21
+
22
+ ## Version 2.20.1 - 2022-07-18
23
+
24
+ ### Fixed
25
+ * [#2458](https://github.com/Shopify/shopify-cli/pull/2458): Fix shop URL in unauthorized error message
26
+ * [#2459](https://github.com/Shopify/shopify-cli/pull/2459): Fix `.json` file ignore issues with `shopify theme push`
27
+ * [#2460](https://github.com/Shopify/shopify-cli/pull/2460): Fix job retries for .json theme file dependencies and support wider range of asset API errors
28
+
5
29
  ## Version 2.20.0 - 2022-07-11
6
30
 
7
31
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shopify-cli (2.20.0)
4
+ shopify-cli (2.22.0)
5
5
  bugsnag (~> 6.22)
6
6
  listen (~> 3.7.0)
7
7
  theme-check (~> 1.10.3)
@@ -52,7 +52,11 @@ module Theme
52
52
  CLI::UI::Frame.open(@ctx.message("theme.pull.pulling", theme.name, theme.id, theme.shop)) do
53
53
  UI::SyncProgressBar.new(syncer).progress(:download_theme!, delete: delete)
54
54
  end
55
- @ctx.done(@ctx.message("theme.pull.done"))
55
+ if syncer.has_any_error?
56
+ @ctx.warn(@ctx.message("theme.pull.done_with_errors"))
57
+ else
58
+ @ctx.done(@ctx.message("theme.pull.done"))
59
+ end
56
60
  rescue ShopifyCLI::API::APIRequestNotFoundError
57
61
  @ctx.abort(@ctx.message("theme.pull.theme_not_found", "##{theme.id}"))
58
62
  ensure
@@ -63,20 +63,12 @@ module Theme
63
63
  syncer.start_threads
64
64
  if options.flags[:json]
65
65
  syncer.upload_theme!(delete: delete)
66
- puts(JSON.generate(theme: theme.to_h))
67
66
  else
68
67
  CLI::UI::Frame.open(@ctx.message("theme.push.info.pushing", theme.name, theme.id, theme.shop)) do
69
68
  UI::SyncProgressBar.new(syncer).progress(:upload_theme!, delete: delete)
70
69
  end
71
-
72
- if options.flags[:publish]
73
- theme.publish
74
- @ctx.done(@ctx.message("theme.publish.done", theme.preview_url))
75
- else
76
- @ctx.done(@ctx.message("theme.push.done", theme.preview_url, theme.editor_url))
77
- end
78
70
  end
79
- raise ShopifyCLI::AbortSilent if syncer.has_any_error?
71
+ push_completion_handler(theme, syncer.has_any_error?)
80
72
  ensure
81
73
  syncer.shutdown
82
74
  end
@@ -90,6 +82,23 @@ module Theme
90
82
 
91
83
  private
92
84
 
85
+ def push_completion_handler(theme, has_errors)
86
+ if options.flags[:json]
87
+ output = { theme: theme.to_h }
88
+ output[:warning] = "Theme pushed with errors." if has_errors
89
+
90
+ puts(JSON.generate(output))
91
+ elsif options.flags[:publish]
92
+ theme.publish
93
+ return @ctx.done(@ctx.message("theme.publish.done", theme.preview_url)) unless has_errors
94
+ @ctx.warn(@ctx.message("theme.publish.done_with_errors", theme.preview_url))
95
+ else
96
+ return @ctx.done(@ctx.message("theme.push.done", theme.preview_url, theme.editor_url)) unless has_errors
97
+ @ctx.warn(@ctx.message("theme.push.done_with_errors", theme.preview_url, theme.editor_url))
98
+ end
99
+ raise ShopifyCLI::AbortSilent if has_errors
100
+ end
101
+
93
102
  def find_theme(root, theme_id: nil, theme: nil, live: nil, development: nil, unpublished: nil, **_args)
94
103
  if theme_id
95
104
  @ctx.warn(@ctx.message("theme.push.deprecated_themeid"))
@@ -11,7 +11,7 @@ module Theme
11
11
  unauthorized_error: <<~EOD,
12
12
  You can't use Shopify CLI with development stores if you only have Partner staff member access. If you want to use Shopify CLI to work on a development store, then you should be the store owner or create a staff account on the store.
13
13
 
14
- If you're the store owner, then you need to log in to the store directly using the store URL at least once (for example, using %s.myshopify.com/admin) before you log in using Shopify CLI. Logging in to the Shopify admin directly connects the development store with your Shopify login.
14
+ If you're the store owner, then you need to log in to the store directly using the store URL at least once (for example, using %s/admin) before you log in using Shopify CLI. Logging in to the Shopify admin directly connects the development store with your Shopify login.
15
15
  EOD
16
16
  ensure_user_try_this: <<~ENSURE_USER,
17
17
  Check if your user is activated, has permission to edit themes at the store, and try to re-login.
@@ -43,6 +43,7 @@ module Theme
43
43
  Run without arguments to select theme from a list.
44
44
  HELP
45
45
  done: "Your theme is now live at %s",
46
+ done_with_errors: "{{warning:Your theme was published with errors and is now live at %s.}}",
46
47
  not_found: "Theme #%s does not exist",
47
48
  no_themes_error: "You don't have any theme to be published.",
48
49
  no_themes_resolution: "Try to create an unpublished theme with {{command:theme push -u -t <theme_name>}}.",
@@ -102,6 +103,15 @@ module Theme
102
103
  {{info:Customize this theme in the Theme Editor:}}
103
104
  {{underline:%s}}
104
105
  DONE
106
+ done_with_errors: <<~WARN,
107
+ {{yellow:Your theme was pushed with errors.}}
108
+
109
+ {{info:View your theme:}}
110
+ {{underline:%s}}
111
+
112
+ {{info:Customize this theme in the Theme Editor:}}
113
+ {{underline:%s}}
114
+ WARN
105
115
  name: "Theme name",
106
116
  },
107
117
  serve: {
@@ -112,14 +122,15 @@ module Theme
112
122
  Usage: {{command:%s theme serve [ ROOT ]}}
113
123
 
114
124
  Options:
115
- {{command:--port=PORT}} Local port to serve theme preview from.
116
- {{command:--poll}} Force polling to detect file changes.
117
- {{command:--host=HOST}} Set which network interface the web server listens on. The default value is 127.0.0.1.
118
- {{command:--theme-editor-sync}} Synchronize Theme Editor updates in the local theme files.
119
- {{command:--live-reload=MODE}} The live reload mode switches the server behavior when a file is modified:
120
- - {{command:hot-reload}} Hot reloads local changes to CSS and sections (default)
121
- - {{command:full-page}} Always refreshes the entire page
122
- - {{command:off}} Deactivate live reload
125
+ {{command:-t, --theme=NAME_OR_ID}} Theme ID or name of the remote theme.
126
+ {{command:--port=PORT}} Local port to serve theme preview from.
127
+ {{command:--poll}} Force polling to detect file changes.
128
+ {{command:--host=HOST}} Set which network interface the web server listens on. The default value is 127.0.0.1.
129
+ {{command:--theme-editor-sync}} Synchronize Theme Editor updates in the local theme files.
130
+ {{command:--live-reload=MODE}} The live reload mode switches the server behavior when a file is modified:
131
+ - {{command:hot-reload}} Hot reloads local changes to CSS and sections (default)
132
+ - {{command:full-page}} Always refreshes the entire page
133
+ - {{command:off}} Deactivate live reload
123
134
  HELP
124
135
  reload_mode_is_not_valid: "The live reload mode `%s` is not valid.",
125
136
  try_a_valid_reload_mode: "Try a valid live reload mode: %s.",
@@ -318,7 +329,8 @@ module Theme
318
329
  HELP
319
330
  select: "Select a theme to pull from",
320
331
  pulling: "Pulling theme files from %s (#%s) on %s",
321
- done: "Theme pulled successfully",
332
+ done: "Theme pulled successfully.",
333
+ done_with_errors: "{{warning:Your theme was pulled with errors.}}",
322
334
  deprecated_themeid: <<~WARN,
323
335
  {{warning:The {{command:-i, --themeid}} flag is deprecated. Use {{command:-t, --theme}} instead.}}
324
336
  WARN
@@ -54,6 +54,7 @@ module ShopifyCLI
54
54
  # Authentication
55
55
  AUTH_TOKEN = "SHOPIFY_CLI_AUTH_TOKEN"
56
56
  ADMIN_AUTH_TOKEN = "SHOPIFY_CLI_ADMIN_AUTH_TOKEN"
57
+ STOREFRONT_RENDERER_AUTH_TOKEN = "SHOPIFY_CLI_STOREFRONT_RENDERER_AUTH_TOKEN"
57
58
 
58
59
  # Monorail
59
60
  MONORAIL_REAL_EVENTS = "MONORAIL_REAL_EVENTS"
@@ -628,9 +628,10 @@ module ShopifyCLI
628
628
  thread = Thread.new { retrieve_latest_gem_version }
629
629
  at_exit { thread.join }
630
630
  end
631
+ latest_version =
632
+ ShopifyCLI::Config.get(VERSION_CHECK_SECTION, LATEST_VERSION_FIELD, default: ShopifyCLI::VERSION)
633
+ latest_version if ::Semantic::Version.new(latest_version) > ::Semantic::Version.new(ShopifyCLI::VERSION)
631
634
  end
632
- latest_version = ShopifyCLI::Config.get(VERSION_CHECK_SECTION, LATEST_VERSION_FIELD, default: ShopifyCLI::VERSION)
633
- latest_version if ::Semantic::Version.new(latest_version) > ::Semantic::Version.new(ShopifyCLI::VERSION)
634
635
  end
635
636
 
636
637
  # Returns file extension depending on OS
@@ -170,6 +170,10 @@ module ShopifyCLI
170
170
  env_variables[Constants::EnvironmentVariables::ADMIN_AUTH_TOKEN]
171
171
  end
172
172
 
173
+ def self.storefront_renderer_auth_token(env_variables: ENV)
174
+ env_variables[Constants::EnvironmentVariables::STOREFRONT_RENDERER_AUTH_TOKEN]
175
+ end
176
+
173
177
  def self.store(env_variables: ENV)
174
178
  env_variables[Constants::EnvironmentVariables::STORE]
175
179
  end
@@ -30,7 +30,7 @@ module ShopifyCLI
30
30
  def parse(directory)
31
31
  File.read(path(directory))
32
32
  .gsub("\r\n", "\n").split("\n").each_with_object({}) do |line, output|
33
- match = /\A([A-Za-z_0-9]+)\s*=\s*(.*)\z/.match(line)
33
+ match = /\A(#*\s*[A-Za-z_0-9]+)\s*=\s*(.*)\z/.match(line)
34
34
  if match
35
35
  key = match[1]
36
36
  output[key] = case match[2]
@@ -14,7 +14,7 @@
14
14
  function connect() {
15
15
  const eventSource = new EventSource('/hot-reload');
16
16
 
17
- eventSource.onmessage = handleUpdate;
17
+ eventSource.onmessage = onMessage;
18
18
 
19
19
  eventSource.onopen = () => console.log('[HotReload] SSE connected.');
20
20
 
@@ -97,10 +97,23 @@
97
97
  window.location.reload();
98
98
  }
99
99
 
100
- function handleUpdate(message) {
101
- var data = JSON.parse(message.data);
100
+ function onMessage(message) {
101
+ const data = JSON.parse(message.data);
102
+ if (data.reload_page) {
103
+ refreshPage([]);
104
+ return;
105
+ }
106
+
107
+ handleUpdate(data);
108
+ }
109
+
110
+ function handleUpdate(data) {
102
111
  var modifiedFiles = data.modified;
103
112
 
113
+ if (modifiedFiles === undefined) {
114
+ return;
115
+ }
116
+
104
117
  if (isRefreshRequired(modifiedFiles)) {
105
118
  refreshPage(modifiedFiles);
106
119
  } else {
@@ -114,13 +127,15 @@
114
127
 
115
128
  function reloadCssFile(filename) {
116
129
  // Find a stylesheet link starting with /assets (locally-served only) containing the filename
117
- let link = document.querySelector(`link[href^="/assets"][href*="${filename}"][rel="stylesheet"]`);
130
+ let links = document.querySelectorAll(`link[href^="/assets"][href*="${filename}"][rel="stylesheet"]`);
118
131
 
119
- if (!link) {
132
+ if (!links.length) {
120
133
  console.log(`[HotReload] Could not find link for stylesheet ${filename}`);
121
134
  } else {
122
- link.href = new URL(link.href).pathname + `?v=${Date.now()}`;
123
- console.log(`[HotReload] Reloaded stylesheet ${filename}`);
135
+ links.forEach(link => {
136
+ link.href = new URL(link.href).pathname + `?v=${Date.now()}`;
137
+ console.log(`[HotReload] Reloaded stylesheet ${filename}`);
138
+ })
124
139
  }
125
140
  }
126
141
 
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyCLI
4
+ module Theme
5
+ module DevServer
6
+ class HotReload
7
+ class RemoteFileDeleter
8
+ def initialize(ctx, theme:, streams:)
9
+ @ctx = ctx
10
+ @theme = theme
11
+ @streams = streams
12
+ end
13
+
14
+ def delete(file)
15
+ retries = 6
16
+
17
+ until retries.zero?
18
+ retries -= 1
19
+
20
+ _status, body = fetch_asset(file)
21
+ retries = 0 if deleted_file?(body)
22
+
23
+ wait
24
+ end
25
+
26
+ notify(file)
27
+ end
28
+
29
+ private
30
+
31
+ def api_client
32
+ @api_client ||= ThemeAdminAPI.new(@ctx, @theme.shop)
33
+ end
34
+
35
+ def deleted_file?(body)
36
+ remote_checksum = body.dig("asset", "checksum")
37
+
38
+ remote_checksum.nil?
39
+ end
40
+
41
+ def notify(file)
42
+ @streams.broadcast(JSON.generate(deleted: [file]))
43
+ @ctx.debug("[RemoteFileDeleter] Deleted #{file}")
44
+ end
45
+
46
+ def wait
47
+ sleep(1)
48
+ end
49
+
50
+ def fetch_asset(file)
51
+ api_client.get(
52
+ path: "themes/#{@theme.id}/assets.json",
53
+ query: URI.encode_www_form("asset[key]" => file.relative_path),
54
+ )
55
+ rescue ShopifyCLI::API::APIRequestNotFoundError
56
+ [404, {}]
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "hot_reload/remote_file_reloader"
4
+ require_relative "hot_reload/remote_file_deleter"
4
5
  require_relative "hot_reload/sections_index"
5
6
 
6
7
  module ShopifyCLI
@@ -14,6 +15,7 @@ module ShopifyCLI
14
15
  @mode = mode
15
16
  @streams = SSE::Streams.new
16
17
  @remote_file_reloader = RemoteFileReloader.new(ctx, theme: @theme, streams: @streams)
18
+ @remote_file_deleter = RemoteFileDeleter.new(ctx, theme: @theme, streams: @streams)
17
19
  @sections_index = SectionsIndex.new(@theme)
18
20
  @watcher = watcher
19
21
  @watcher.add_observer(self, :notify_streams_of_file_change)
@@ -36,13 +38,20 @@ module ShopifyCLI
36
38
  @streams.close
37
39
  end
38
40
 
39
- def notify_streams_of_file_change(modified, added, _removed)
41
+ def notify_streams_of_file_change(modified, added, removed)
40
42
  files = (modified + added)
41
43
  .reject { |file| @ignore_filter&.ignore?(file) }
42
44
  .map { |file| @theme[file] }
43
45
 
44
46
  files -= liquid_css_files = files.select(&:liquid_css?)
45
47
 
48
+ deleted_files = removed
49
+ .reject { |file| @ignore_filter&.ignore?(file) }
50
+ .map { |file| @theme[file] }
51
+
52
+ remote_delete(deleted_files) unless deleted_files.empty?
53
+ reload_page(removed) unless deleted_files.empty?
54
+
46
55
  hot_reload(files) unless files.empty?
47
56
  remote_reload(liquid_css_files)
48
57
  end
@@ -55,8 +64,21 @@ module ShopifyCLI
55
64
  @ctx.debug("[HotReload] Modified #{paths.join(", ")}")
56
65
  end
57
66
 
67
+ def reload_page(removed)
68
+ @streams.broadcast(JSON.generate(reload_page: true))
69
+ @ctx.debug("[ReloadPage] Deleted #{removed.join(", ")}")
70
+ end
71
+
72
+ def remote_delete(files)
73
+ files.each do |file|
74
+ @ctx.debug("delete file each -> file.relative_path #{file.relative_path}")
75
+ @remote_file_deleter.delete(file)
76
+ end
77
+ end
78
+
58
79
  def remote_reload(files)
59
80
  files.each do |file|
81
+ @ctx.debug("reload file each -> file.relative_path #{file.relative_path}")
60
82
  @remote_file_reloader.reload(file)
61
83
  end
62
84
  end
@@ -94,6 +94,7 @@ module ShopifyCLI
94
94
  end
95
95
 
96
96
  def bearer_token
97
+ Environment.storefront_renderer_auth_token ||
97
98
  ShopifyCLI::DB.get(:storefront_renderer_production_exchange_token) ||
98
99
  raise(KeyError, "storefront_renderer_production_exchange_token missing")
99
100
  end
@@ -10,7 +10,7 @@ module ShopifyCLI
10
10
  def enqueue_json_updates(files)
11
11
  # Update remote JSON files and delays `delayed_files` update
12
12
  files = files
13
- .select { |file| !ignore_file?(file) && file.exist? && checksums.file_has_changed?(file) }
13
+ .select { |file| ready_to_update?(file) }
14
14
  .sort_by { |file| delayed_files.include?(file) ? 1 : 0 }
15
15
  .reject { |file| overwrite_json? && delayed_files.include?(file) }
16
16
 
@@ -26,7 +26,7 @@ module ShopifyCLI
26
26
  return unless overwrite_json?
27
27
  # Update delayed files synchronously
28
28
  delayed_files.each do |file|
29
- update(file) if checksums.file_has_changed?(file)
29
+ update(file) if ready_to_update?(file)
30
30
  end
31
31
  end
32
32
 
@@ -86,6 +86,10 @@ module ShopifyCLI
86
86
  def ask_update_strategy(file)
87
87
  Forms::SelectUpdateStrategy.ask(@ctx, [], file: file, exists_remotely: file_exist_remotely?(file)).strategy
88
88
  end
89
+
90
+ def ready_to_update?(file)
91
+ !ignore_file?(file) && file.exist? && checksums.file_has_changed?(file)
92
+ end
89
93
  end
90
94
  end
91
95
  end
@@ -366,17 +366,23 @@ module ShopifyCLI
366
366
  checksums.reject_duplicated_checksums!
367
367
  end
368
368
 
369
- def parse_api_errors(exception)
369
+ def parse_api_errors(operation, exception)
370
370
  parsed_body = if exception&.response&.is_a?(Hash)
371
371
  exception&.response&.[](:body)
372
372
  else
373
373
  JSON.parse(exception&.response&.body)
374
374
  end
375
- message = parsed_body.dig("errors", "asset") || parsed_body["message"] || exception.message
375
+
376
+ errors = parsed_body.dig("errors") # either nil or another type
377
+ errors = errors.dig("asset") if errors&.is_a?(Hash)
378
+
379
+ message = errors || parsed_body["message"] || exception.message
376
380
  # Truncate to first lines
377
381
  [message].flatten.map { |m| m.split("\n", 2).first }
378
382
  rescue JSON::ParserError
379
383
  [exception.message]
384
+ rescue StandardError => e
385
+ ["The asset #{operation.file} is could not be synced (cause: #{e.message})."]
380
386
  end
381
387
 
382
388
  def backoff_if_near_limit!(used, limit)
@@ -387,7 +393,11 @@ module ShopifyCLI
387
393
  end
388
394
 
389
395
  def overwrite_json?
390
- @overwrite_json
396
+ theme_created_at_runtime? || @overwrite_json
397
+ end
398
+
399
+ def theme_created_at_runtime?
400
+ @theme.created_at_runtime?
391
401
  end
392
402
 
393
403
  def backingoff?
@@ -400,7 +410,7 @@ module ShopifyCLI
400
410
  end
401
411
 
402
412
  def handle_operation_error(operation, error)
403
- error_suffix = ":\n " + parse_api_errors(error).join("\n ")
413
+ error_suffix = ":\n " + parse_api_errors(operation, error).join("\n ")
404
414
  report_error(operation, error_suffix)
405
415
  end
406
416
 
@@ -120,6 +120,7 @@ module ShopifyCLI
120
120
  )
121
121
 
122
122
  @id = body["theme"]["id"]
123
+ @created_at_runtime = true
123
124
  end
124
125
 
125
126
  def delete
@@ -147,6 +148,10 @@ module ShopifyCLI
147
148
  development? && id != ShopifyCLI::DB.get(:development_theme_id)
148
149
  end
149
150
 
151
+ def created_at_runtime?
152
+ @created_at_runtime ||= false
153
+ end
154
+
150
155
  def to_h
151
156
  {
152
157
  id: id,
@@ -10,7 +10,7 @@ module ShopifyCLI
10
10
  class ThemeAdminAPIThrottler
11
11
  class BulkJob < ShopifyCLI::ThreadPool::Job
12
12
  JOB_TIMEOUT = 0.2 # 200ms
13
- MAX_RETRIES = 5
13
+ MAX_RETRIES = 10
14
14
 
15
15
  attr_reader :bulk
16
16
 
@@ -1,3 +1,3 @@
1
1
  module ShopifyCLI
2
- VERSION = "2.20.0"
2
+ VERSION = "2.22.0"
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.20.0
4
+ version: 2.22.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-07-11 00:00:00.000000000 Z
11
+ date: 2022-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -124,7 +124,7 @@ files:
124
124
  - ".github/ISSUE_TEMPLATE/enhancement.yaml"
125
125
  - ".github/ISSUE_TEMPLATE/feature.yaml"
126
126
  - ".github/PULL_REQUEST_TEMPLATE.md"
127
- - ".github/probots.yml"
127
+ - ".github/workflows/cla.yml"
128
128
  - ".github/workflows/shopify.yml"
129
129
  - ".github/workflows/stale.yml"
130
130
  - ".github/workflows/triage.yml"
@@ -507,6 +507,7 @@ files:
507
507
  - lib/shopify_cli/theme/dev_server/hot-reload-no-script.html
508
508
  - lib/shopify_cli/theme/dev_server/hot-reload.js
509
509
  - lib/shopify_cli/theme/dev_server/hot_reload.rb
510
+ - lib/shopify_cli/theme/dev_server/hot_reload/remote_file_deleter.rb
510
511
  - lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb
511
512
  - lib/shopify_cli/theme/dev_server/hot_reload/sections_index.rb
512
513
  - lib/shopify_cli/theme/dev_server/local_assets.rb
data/.github/probots.yml DELETED
@@ -1,3 +0,0 @@
1
- # .github/probots.yml
2
- enabled:
3
- - cla