shopify-cli 2.15.0 → 2.15.3
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.
- checksums.yaml +4 -4
- data/.github/workflows/stale.yml +7 -2
- data/.vscode/settings.json +1 -2
- data/CHANGELOG.md +70 -19
- data/Gemfile +1 -0
- data/Gemfile.lock +39 -7
- data/Rakefile +48 -0
- data/ext/javy/hashes/javy-arm-macos-v0.3.0.gz.sha256 +1 -0
- data/ext/javy/hashes/javy-x86_64-linux-v0.3.0.gz.sha256 +1 -0
- data/ext/javy/hashes/javy-x86_64-macos-v0.3.0.gz.sha256 +1 -0
- data/ext/javy/hashes/javy-x86_64-windows-v0.3.0.gz.sha256 +1 -0
- data/ext/javy/version +1 -1
- data/ext/shopify-extensions/version +1 -1
- data/lib/project_types/extension/commands/check.rb +6 -1
- data/lib/project_types/extension/forms/questions/ask_template.rb +5 -8
- data/lib/project_types/extension/messages/messages.rb +11 -3
- data/lib/project_types/extension/models/development_server_requirements.rb +14 -7
- data/lib/project_types/extension/models/server_config/root.rb +2 -0
- data/lib/project_types/extension/models/specification_handlers/beacon_extension.rb +57 -0
- data/lib/project_types/extension/models/specification_handlers/beacon_extension_utils/script_config.rb +33 -0
- data/lib/project_types/extension/models/specification_handlers/beacon_extension_utils/script_config_repository.rb +75 -0
- data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +16 -1
- data/lib/project_types/extension/tasks/configure_options.rb +2 -1
- data/lib/project_types/extension/tasks/convert_server_config.rb +13 -2
- data/lib/project_types/extension/tasks/merge_server_config.rb +5 -2
- data/lib/project_types/script/cli.rb +1 -0
- data/lib/project_types/script/config/extension_points.yml +18 -0
- data/lib/project_types/script/layers/application/create_script.rb +14 -6
- data/lib/project_types/script/layers/infrastructure/errors.rb +17 -0
- data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +6 -21
- data/lib/project_types/script/layers/infrastructure/script_service.rb +2 -0
- data/lib/project_types/script/layers/infrastructure/sparse_checkout_details.rb +35 -0
- data/lib/project_types/script/messages/messages.rb +3 -0
- data/lib/project_types/script/ui/error_handler.rb +11 -0
- data/lib/project_types/theme/cli.rb +1 -0
- data/lib/project_types/theme/commands/check.rb +4 -1
- data/lib/project_types/theme/commands/open.rb +2 -2
- data/lib/project_types/theme/commands/push.rb +1 -3
- data/lib/project_types/theme/commands/serve.rb +1 -0
- data/lib/project_types/theme/commands/share.rb +56 -0
- data/lib/project_types/theme/messages/messages.rb +71 -11
- data/lib/shopify_cli/changelog.rb +148 -0
- data/lib/shopify_cli/command.rb +7 -0
- data/lib/shopify_cli/command_options/command_serve_options.rb +10 -0
- data/lib/shopify_cli/commands/app/serve.rb +7 -7
- data/lib/shopify_cli/commands/login.rb +5 -2
- data/lib/shopify_cli/context.rb +13 -0
- data/lib/shopify_cli/git.rb +36 -0
- data/lib/shopify_cli/identity_auth.rb +24 -4
- data/lib/shopify_cli/messages/messages.rb +26 -5
- data/lib/shopify_cli/release.rb +194 -0
- data/lib/shopify_cli/sed.rb +19 -0
- data/lib/shopify_cli/services/app/create/rails_service.rb +10 -2
- data/lib/shopify_cli/services/app/serve/node_service.rb +2 -25
- data/lib/shopify_cli/services/app/serve/php_service.rb +2 -25
- data/lib/shopify_cli/services/app/serve/rails_service.rb +8 -28
- data/lib/shopify_cli/services/app/serve/serve_service.rb +57 -0
- data/lib/shopify_cli/services.rb +1 -0
- data/lib/shopify_cli/tasks/update_dashboard_urls.rb +7 -9
- data/lib/shopify_cli/theme/dev_server/hot-reload.js +40 -13
- data/lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/hot_reload/sections_index.rb +51 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload.rb +6 -1
- data/lib/shopify_cli/theme/dev_server/local_assets.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/remote_watcher/json_files_update_job.rb +35 -0
- data/lib/shopify_cli/theme/dev_server/remote_watcher.rb +44 -0
- data/lib/shopify_cli/theme/dev_server/watcher.rb +2 -8
- data/lib/shopify_cli/theme/dev_server.rb +18 -5
- data/lib/shopify_cli/theme/file.rb +15 -4
- data/lib/shopify_cli/theme/syncer/checksums.rb +60 -0
- data/lib/shopify_cli/theme/syncer/forms/apply_to_all.rb +39 -0
- data/lib/shopify_cli/theme/syncer/forms/apply_to_all_form.rb +35 -0
- data/lib/shopify_cli/theme/syncer/forms/base_strategy_form.rb +62 -0
- data/lib/shopify_cli/theme/syncer/forms/select_delete_strategy.rb +27 -0
- data/lib/shopify_cli/theme/syncer/forms/select_update_strategy.rb +28 -0
- data/lib/shopify_cli/theme/syncer/ignore_helper.rb +33 -0
- data/lib/shopify_cli/theme/syncer/json_delete_handler.rb +51 -0
- data/lib/shopify_cli/theme/syncer/json_update_handler.rb +82 -0
- data/lib/shopify_cli/theme/syncer/merger.rb +53 -0
- data/lib/shopify_cli/theme/syncer/operation.rb +1 -1
- data/lib/shopify_cli/theme/syncer.rb +79 -63
- data/lib/shopify_cli/theme/theme.rb +26 -4
- data/lib/shopify_cli/theme/theme_admin_api.rb +23 -8
- data/lib/shopify_cli/thread_pool/job.rb +10 -2
- data/lib/shopify_cli/thread_pool.rb +15 -3
- data/lib/shopify_cli/tunnel.rb +9 -0
- data/lib/shopify_cli/version.rb +1 -1
- data/shopify-cli.gemspec +3 -1
- data/vendor/deps/cli-ui/lib/cli/ui/os.rb +8 -0
- metadata +30 -3
|
@@ -8,8 +8,9 @@ module Theme
|
|
|
8
8
|
Usage: {{command:%1$s theme [ %2$s ]}}
|
|
9
9
|
HELP
|
|
10
10
|
ensure_user_error: "You are not authorized to edit themes on %s.",
|
|
11
|
-
ensure_user_try_this:
|
|
12
|
-
|
|
11
|
+
ensure_user_try_this: <<~ENSURE_USER,
|
|
12
|
+
Check if your user is activated, has permission to edit themes at the store, and try to re-login.
|
|
13
|
+
ENSURE_USER
|
|
13
14
|
init: {
|
|
14
15
|
help: <<~HELP,
|
|
15
16
|
{{command:%s theme init}}: Clones a Git repository to use as a starting point for building a new theme.
|
|
@@ -101,13 +102,14 @@ module Theme
|
|
|
101
102
|
Usage: {{command:%s theme serve [ ROOT ]}}
|
|
102
103
|
|
|
103
104
|
Options:
|
|
104
|
-
{{command:--port=PORT}}
|
|
105
|
-
{{command:--poll}}
|
|
106
|
-
{{command:--host=HOST}}
|
|
107
|
-
{{command:--
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
{{command:--port=PORT}} Local port to serve theme preview from.
|
|
106
|
+
{{command:--poll}} Force polling to detect file changes.
|
|
107
|
+
{{command:--host=HOST}} Set which network interface the web server listens on. The default value is 127.0.0.1.
|
|
108
|
+
{{command:--theme-editor-sync}} Synchronize Theme Editor updates in the local theme files.
|
|
109
|
+
{{command:--live-reload=MODE}} The live reload mode switches the server behavior when a file is modified:
|
|
110
|
+
- {{command:hot-reload}} Hot reloads local changes to CSS and sections (default)
|
|
111
|
+
- {{command:full-page}} Always refreshes the entire page
|
|
112
|
+
- {{command:off}} Deactivate live reload
|
|
111
113
|
HELP
|
|
112
114
|
reload_mode_is_not_valid: "The live reload mode `%s` is not valid.",
|
|
113
115
|
try_a_valid_reload_mode: "Try a valid live reload mode: %s.",
|
|
@@ -121,18 +123,56 @@ module Theme
|
|
|
121
123
|
fixed: "Fixed",
|
|
122
124
|
},
|
|
123
125
|
},
|
|
126
|
+
syncer: {
|
|
127
|
+
forms: {
|
|
128
|
+
apply_to_all: {
|
|
129
|
+
title: "Would like apply this to all the other %s files?",
|
|
130
|
+
yes: "Yes",
|
|
131
|
+
no: "No",
|
|
132
|
+
},
|
|
133
|
+
update_strategy: {
|
|
134
|
+
title_context: <<~TITLE,
|
|
135
|
+
|
|
136
|
+
The local file {{command:%s}} is different from the remote version in the development theme."
|
|
137
|
+
TITLE
|
|
138
|
+
title_question: "What would you like to do?",
|
|
139
|
+
keep_remote: "Keep the remote version",
|
|
140
|
+
keep_local: "Keep the local version",
|
|
141
|
+
union_merge: "Merge files (it may break the local file)",
|
|
142
|
+
exit: "Exit",
|
|
143
|
+
},
|
|
144
|
+
delete_strategy: {
|
|
145
|
+
title_context: <<~TITLE,
|
|
146
|
+
|
|
147
|
+
The local file {{command:%s}} has been recently removed, but it's present on your remote development theme.",
|
|
148
|
+
TITLE
|
|
149
|
+
title_question: "What would you like to do?",
|
|
150
|
+
delete: "Delete permanently",
|
|
151
|
+
restore: "Restore with the remote version",
|
|
152
|
+
exit: "Exit",
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
},
|
|
124
156
|
error: {
|
|
125
157
|
address_binding_error: "Couldn't bind to localhost."\
|
|
126
158
|
" To serve your theme, set a different address with {{command:%s theme serve --host=<address>}}",
|
|
159
|
+
invalid_subdirectory: <<~MESSAGE,
|
|
160
|
+
The presence of %s in the directory structure isn't supported.
|
|
161
|
+
|
|
162
|
+
Move any files to a parent folder, then delete unsupported subdirectories.
|
|
163
|
+
|
|
164
|
+
• Required directory structure: https://shopify.dev/themes/architecture#directory-structure-and-component-types
|
|
165
|
+
MESSAGE
|
|
127
166
|
},
|
|
128
167
|
serving: <<~SERVING,
|
|
129
168
|
|
|
130
169
|
Serving %s
|
|
131
170
|
|
|
132
171
|
SERVING
|
|
172
|
+
download_changes: ", and use 'theme pull' to get the changes",
|
|
133
173
|
customize_or_preview: <<~CUSTOMIZE_OR_PREVIEW,
|
|
134
174
|
|
|
135
|
-
Customize this theme in the Theme Editor:
|
|
175
|
+
Customize this theme in the Theme Editor%s:
|
|
136
176
|
{{green:%s}}
|
|
137
177
|
|
|
138
178
|
Share this theme preview:
|
|
@@ -142,7 +182,7 @@ module Theme
|
|
|
142
182
|
CUSTOMIZE_OR_PREVIEW
|
|
143
183
|
ensure_user: <<~ENSURE_USER,
|
|
144
184
|
You are not authorized to edit themes on %s.
|
|
145
|
-
|
|
185
|
+
Check if your user is activated, has permission to edit themes at the store, and try to re-login.
|
|
146
186
|
ENSURE_USER
|
|
147
187
|
address_already_in_use: "The address \"%s\" is already in use.",
|
|
148
188
|
try_port_option: "Use the --port=PORT option to serve the theme in a different port.",
|
|
@@ -152,6 +192,7 @@ module Theme
|
|
|
152
192
|
Check your theme for errors, suggestions, and best practices.
|
|
153
193
|
Usage: {{command:%s check}}
|
|
154
194
|
HELP
|
|
195
|
+
error: "Theme check failed with error:\n%s",
|
|
155
196
|
},
|
|
156
197
|
delete: {
|
|
157
198
|
help: <<~HELP,
|
|
@@ -223,6 +264,9 @@ module Theme
|
|
|
223
264
|
details: <<~DETAILS,
|
|
224
265
|
{{*}} {{bold:%s}}
|
|
225
266
|
|
|
267
|
+
Preview your theme:
|
|
268
|
+
{{green:%s}}
|
|
269
|
+
|
|
226
270
|
Customize your theme in the Theme Editor:
|
|
227
271
|
{{green:%s}}
|
|
228
272
|
|
|
@@ -246,6 +290,22 @@ module Theme
|
|
|
246
290
|
Usage: {{command:%s theme list}}
|
|
247
291
|
HELP
|
|
248
292
|
},
|
|
293
|
+
share: {
|
|
294
|
+
help: <<~HELP,
|
|
295
|
+
{{command:%s theme share}}: Creates a shareable, unpublished, and new theme on your theme library with a randomized name.
|
|
296
|
+
Works like an alias to {{command:theme push -u -t=RANDOMIZED_NAME}}.
|
|
297
|
+
|
|
298
|
+
Usage: {{command:%s theme share [ ROOT ]}}
|
|
299
|
+
HELP
|
|
300
|
+
done: <<~DONE,
|
|
301
|
+
{{green:The {{bold:%s}} theme was pushed successfully}}
|
|
302
|
+
|
|
303
|
+
{{info:Share your theme preview:}}
|
|
304
|
+
{{underline:%s}}
|
|
305
|
+
|
|
306
|
+
DONE
|
|
307
|
+
upload: "Pushing theme files to %s (#%s) on %s",
|
|
308
|
+
},
|
|
249
309
|
},
|
|
250
310
|
}.freeze
|
|
251
311
|
end
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
require "date"
|
|
2
|
+
require "shopify_cli/sed"
|
|
3
|
+
require "octokit"
|
|
4
|
+
|
|
5
|
+
module ShopifyCLI
|
|
6
|
+
class Changelog
|
|
7
|
+
CHANGELOG_FILE = File.join(ShopifyCLI::ROOT, "CHANGELOG.md")
|
|
8
|
+
CHANGE_CATEGORIES = %w(Added Changed Deprecated Removed Fixed Security)
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
load(File.read(CHANGELOG_FILE))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def update_version!(new_version)
|
|
15
|
+
changes[new_version] = changes["Unreleased"]
|
|
16
|
+
changes[new_version][:date] = Date.today.iso8601
|
|
17
|
+
changes["Unreleased"] = { changes: [], date: nil }
|
|
18
|
+
save!
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def update!
|
|
22
|
+
pr = pr_for_current_branch
|
|
23
|
+
category = CLI::UI::Prompt.ask("What type of change?", options: CHANGE_CATEGORIES)
|
|
24
|
+
add_change(category, { pr_id: pr.number, desc: pr.title })
|
|
25
|
+
save!
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def release_notes(version)
|
|
29
|
+
changes[version][:changes].map do |change_category, changes|
|
|
30
|
+
<<~CHANGES
|
|
31
|
+
### #{change_category}
|
|
32
|
+
#{changes.map { |change| entry(**change) }.join("\n")}
|
|
33
|
+
CHANGES
|
|
34
|
+
end.join("\n")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def add_change(category, change)
|
|
38
|
+
changes["Unreleased"][:changes][category] << change
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def entry(pr_id:, desc:)
|
|
42
|
+
"* [##{pr_id}](https://github.com/Shopify/shopify-cli/pull/#{pr_id}): #{desc}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def full_contents
|
|
46
|
+
sorted_changes = changes.each_key.sort_by do |change|
|
|
47
|
+
if change == "Unreleased"
|
|
48
|
+
[Float::INFINITY] * 3 # end of the list
|
|
49
|
+
else
|
|
50
|
+
major, minor, patch = change.split(".").map(&:to_i)
|
|
51
|
+
[major, minor, patch]
|
|
52
|
+
end
|
|
53
|
+
end.reverse
|
|
54
|
+
[
|
|
55
|
+
heading,
|
|
56
|
+
*sorted_changes.each.map { |version| release_notes_with_header(version) }.join,
|
|
57
|
+
remainder,
|
|
58
|
+
].map { |section| section.chomp << "\n" }.join
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def save!
|
|
62
|
+
File.write(CHANGELOG_FILE, full_contents)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
attr_reader :heading, :remainder
|
|
68
|
+
|
|
69
|
+
def release_notes_with_header(version)
|
|
70
|
+
header_line =
|
|
71
|
+
if version == "Unreleased"
|
|
72
|
+
"[Unreleased]"
|
|
73
|
+
else
|
|
74
|
+
date = changes[version][:date]
|
|
75
|
+
"Version #{version}#{" - #{date}" if date}"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
[
|
|
79
|
+
"## #{header_line}",
|
|
80
|
+
release_notes(version),
|
|
81
|
+
].reject(&:empty?).map { |section| section.chomp << "\n\n" }.join
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def changes
|
|
85
|
+
@changes ||= Hash.new do |h, k|
|
|
86
|
+
h[k] = {
|
|
87
|
+
date: nil,
|
|
88
|
+
changes: Hash.new do |h2, k2|
|
|
89
|
+
h2[k2] = []
|
|
90
|
+
end,
|
|
91
|
+
}
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def load(log)
|
|
96
|
+
state = :initial
|
|
97
|
+
change_category = nil
|
|
98
|
+
current_version = nil
|
|
99
|
+
@heading = ""
|
|
100
|
+
@remainder = ""
|
|
101
|
+
log.each_line do |line|
|
|
102
|
+
case state
|
|
103
|
+
when :initial
|
|
104
|
+
if line.chomp == "\#\# [Unreleased]"
|
|
105
|
+
state = :unreleased
|
|
106
|
+
current_version = "Unreleased"
|
|
107
|
+
# Ensure Unreleased changeset exists even if no changes have happened yet
|
|
108
|
+
changes["Unreleased"]
|
|
109
|
+
else
|
|
110
|
+
@heading << line
|
|
111
|
+
end
|
|
112
|
+
when :unreleased, :prior_versions
|
|
113
|
+
if /\A\#\#\# (?<category>\w+)/ =~ line
|
|
114
|
+
change_category = category
|
|
115
|
+
elsif %r{\A\* \[\#(?<id>\d+)\]\(https://github.com/Shopify/shopify-cli/pull/\k<id>\): (?<desc>.+)\n} =~ line
|
|
116
|
+
changes[current_version][:changes][change_category] << { pr_id: id, desc: desc }
|
|
117
|
+
elsif /\A\#\# Version (?<version>\d+\.\d+\.\d+)( - (?<date>\d{4}-\d{2}-\d{2}))?/ =~ line
|
|
118
|
+
current_version = version
|
|
119
|
+
state = :prior_versions
|
|
120
|
+
major, minor, _patch = current_version.split(".")
|
|
121
|
+
if major.to_i <= 2 && minor.to_i < 7
|
|
122
|
+
# Changelog starts to become irregular in 2.6.x
|
|
123
|
+
state = :finished
|
|
124
|
+
end
|
|
125
|
+
changes[current_version][:date] = date unless state == :finished
|
|
126
|
+
elsif !line.match?(/\s*\n/)
|
|
127
|
+
raise "Unrecognized line: #{line.inspect}"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
@remainder << line if state == :finished
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def pr_for_current_branch
|
|
135
|
+
current_branch = %x(git branch --show-current).chomp
|
|
136
|
+
search_term = "repo:Shopify/shopify-cli is:pr is:open head:#{current_branch}"
|
|
137
|
+
results = Octokit::Client.new.search_issues(search_term)
|
|
138
|
+
case results.total_count
|
|
139
|
+
when 0
|
|
140
|
+
raise "PR not opened yet!"
|
|
141
|
+
when (2..)
|
|
142
|
+
raise "Multiple open PRs, not sure which one to use for changelog!"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
results.items.first
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
data/lib/shopify_cli/command.rb
CHANGED
|
@@ -36,6 +36,13 @@ module ShopifyCLI
|
|
|
36
36
|
end
|
|
37
37
|
rescue OptionParser::InvalidOption => error
|
|
38
38
|
arg = error.args.first
|
|
39
|
+
store_name = arg.match(/\A--(?<store_name>.*\.myshopify\.com)\z/)&.[](:store_name)
|
|
40
|
+
if store_name && !arg.match?(/\A--(store|shop)=/)
|
|
41
|
+
# Sometimes it may look like --invalidoption=https://storename.myshopify.com
|
|
42
|
+
store_name = store_name.sub(%r{\A(.*=)?(https?://)?}, "")
|
|
43
|
+
raise ShopifyCLI::Abort,
|
|
44
|
+
@ctx.message("core.errors.option_parser.invalid_option_store_equals", arg, store_name)
|
|
45
|
+
end
|
|
39
46
|
raise ShopifyCLI::Abort, @ctx.message("core.errors.option_parser.invalid_option", arg)
|
|
40
47
|
rescue OptionParser::MissingArgument => error
|
|
41
48
|
arg = error.args.first
|
|
@@ -20,6 +20,10 @@ module ShopifyCLI
|
|
|
20
20
|
end
|
|
21
21
|
host
|
|
22
22
|
end
|
|
23
|
+
|
|
24
|
+
def no_update
|
|
25
|
+
options.flags[:no_update] || false
|
|
26
|
+
end
|
|
23
27
|
end
|
|
24
28
|
end
|
|
25
29
|
|
|
@@ -37,6 +41,12 @@ module ShopifyCLI
|
|
|
37
41
|
parser.on("--port=PORT") { |port| flags[:port] = port }
|
|
38
42
|
end
|
|
39
43
|
end
|
|
44
|
+
|
|
45
|
+
def parse_no_update_option
|
|
46
|
+
options do |parser, flags|
|
|
47
|
+
parser.on("--no-update") { flags[:no_update] = true }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
40
50
|
end
|
|
41
51
|
end
|
|
42
52
|
end
|
|
@@ -8,12 +8,9 @@ module ShopifyCLI
|
|
|
8
8
|
|
|
9
9
|
recommend_default_ruby_range
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
end
|
|
15
|
-
parser.on("--port=PORT") { |port| flags[:port] = port }
|
|
16
|
-
end
|
|
11
|
+
parse_host_option
|
|
12
|
+
parse_port_option
|
|
13
|
+
parse_no_update_option
|
|
17
14
|
|
|
18
15
|
def call(*)
|
|
19
16
|
case detect_app
|
|
@@ -21,18 +18,21 @@ module ShopifyCLI
|
|
|
21
18
|
Services::App::Serve::RailsService.call(
|
|
22
19
|
host: host,
|
|
23
20
|
port: port,
|
|
21
|
+
no_update: no_update,
|
|
24
22
|
context: @ctx
|
|
25
23
|
)
|
|
26
24
|
when :node
|
|
27
25
|
Services::App::Serve::NodeService.call(
|
|
28
26
|
host: host,
|
|
29
27
|
port: port,
|
|
28
|
+
no_update: no_update,
|
|
30
29
|
context: @ctx
|
|
31
30
|
)
|
|
32
31
|
when :php
|
|
33
32
|
Services::App::Serve::PHPService.call(
|
|
34
33
|
host: host,
|
|
35
34
|
port: port,
|
|
35
|
+
no_update: no_update,
|
|
36
36
|
context: @ctx
|
|
37
37
|
)
|
|
38
38
|
end
|
|
@@ -43,7 +43,7 @@ module ShopifyCLI
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def self.extended_help
|
|
46
|
-
ShopifyCLI::Context.message("app.
|
|
46
|
+
ShopifyCLI::Context.message("core.app.serve.extended_help")
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
end
|
|
@@ -30,7 +30,7 @@ module ShopifyCLI
|
|
|
30
30
|
if @ctx.ci? && (password = options.flags[:password] || @ctx.getenv("SHOPIFY_PASSWORD"))
|
|
31
31
|
ShopifyCLI::DB.set(shopify_exchange_token: password)
|
|
32
32
|
else
|
|
33
|
-
IdentityAuth.new(ctx: @ctx).authenticate
|
|
33
|
+
IdentityAuth.new(ctx: @ctx).authenticate(spinner: true)
|
|
34
34
|
org = select_organization
|
|
35
35
|
ShopifyCLI::DB.set(organization_id: org["id"].to_i) unless org.nil?
|
|
36
36
|
Whoami.call([], "whoami")
|
|
@@ -75,7 +75,10 @@ module ShopifyCLI
|
|
|
75
75
|
private
|
|
76
76
|
|
|
77
77
|
def select_organization
|
|
78
|
-
organizations =
|
|
78
|
+
organizations = []
|
|
79
|
+
CLI::UI::Spinner.spin(@ctx.message("core.login.spinner.loading_organizations")) do
|
|
80
|
+
organizations = ShopifyCLI::PartnersAPI::Organizations.fetch_all(@ctx)
|
|
81
|
+
end
|
|
79
82
|
|
|
80
83
|
if organizations.count == 0
|
|
81
84
|
nil
|
data/lib/shopify_cli/context.rb
CHANGED
|
@@ -4,6 +4,7 @@ require "fileutils"
|
|
|
4
4
|
require "rbconfig"
|
|
5
5
|
require "net/http"
|
|
6
6
|
require "json"
|
|
7
|
+
require "bundler"
|
|
7
8
|
|
|
8
9
|
module ShopifyCLI
|
|
9
10
|
##
|
|
@@ -642,6 +643,18 @@ module ShopifyCLI
|
|
|
642
643
|
end
|
|
643
644
|
end
|
|
644
645
|
|
|
646
|
+
# Uses bundle to grab the version of a gem
|
|
647
|
+
#
|
|
648
|
+
# #### Parameters
|
|
649
|
+
# - gem: the name of the gem to check
|
|
650
|
+
#
|
|
651
|
+
# #### Returns
|
|
652
|
+
# - version: a Semantic::Version object with the gem version
|
|
653
|
+
def ruby_gem_version(gem)
|
|
654
|
+
version = Bundler.load.specs.find { |s| s.name == gem }.version
|
|
655
|
+
::Semantic::Version.new(version.to_s)
|
|
656
|
+
end
|
|
657
|
+
|
|
645
658
|
private
|
|
646
659
|
|
|
647
660
|
def ctx_path(fname)
|
data/lib/shopify_cli/git.rb
CHANGED
|
@@ -102,6 +102,42 @@ module ShopifyCLI
|
|
|
102
102
|
branches
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
+
##
|
|
106
|
+
# Run git three-way file merge (it doesn't require an initialized git repository)
|
|
107
|
+
#
|
|
108
|
+
# #### Parameters
|
|
109
|
+
#
|
|
110
|
+
# * `current_file - string path of the current file
|
|
111
|
+
# * `base_file` - string path of the base file
|
|
112
|
+
# * `other_file` - string path of the other file
|
|
113
|
+
# * `opts` - list of "git merge-file" options. Valid values:
|
|
114
|
+
# - "-q" - do not warn about conflicts
|
|
115
|
+
# - "--diff3" - show conflicts
|
|
116
|
+
# - "--ours" - resolve conflicts favoring lines from `current_file`
|
|
117
|
+
# - "--theirs" - resolve conflicts favoring lines from `other_file`
|
|
118
|
+
# - "--union" - resolve conflicts favoring lines from both files
|
|
119
|
+
# - "-p" - send results to standard output instead of
|
|
120
|
+
# overwriting the `current_file`
|
|
121
|
+
# * `ctx` - the current running context of your command, defaults to a new context
|
|
122
|
+
#
|
|
123
|
+
# #### Returns
|
|
124
|
+
#
|
|
125
|
+
# * standard output from git
|
|
126
|
+
#
|
|
127
|
+
# #### Example
|
|
128
|
+
#
|
|
129
|
+
# output = ShopifyCLI::Git.merge_file(current_file, base_file, other_file, opts, ctx: ctx)
|
|
130
|
+
#
|
|
131
|
+
def merge_file(current_file, base_file, other_file, opts = [], ctx: Context.new)
|
|
132
|
+
output, status = ctx.capture2e("git", "merge-file", current_file, base_file, other_file, *opts)
|
|
133
|
+
|
|
134
|
+
unless status.success?
|
|
135
|
+
ctx.abort(ctx.message("core.git.error.merge_failed"))
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
output
|
|
139
|
+
end
|
|
140
|
+
|
|
105
141
|
##
|
|
106
142
|
# will initialize a new repo in the current directory. This will output
|
|
107
143
|
# if it was successful or not.
|
|
@@ -56,8 +56,10 @@ module ShopifyCLI
|
|
|
56
56
|
|
|
57
57
|
attr_accessor :response_query
|
|
58
58
|
|
|
59
|
-
def authenticate
|
|
60
|
-
return if
|
|
59
|
+
def authenticate(spinner: false)
|
|
60
|
+
return if with_spinner(spinner, ctx.message("core.login.spinner.initiating")) do
|
|
61
|
+
attempt_reauthenticate
|
|
62
|
+
end
|
|
61
63
|
|
|
62
64
|
initiate_authentication
|
|
63
65
|
|
|
@@ -66,7 +68,21 @@ module ShopifyCLI
|
|
|
66
68
|
rescue IdentityAuth::Timeout => e
|
|
67
69
|
ctx.abort(e.message)
|
|
68
70
|
end
|
|
69
|
-
|
|
71
|
+
with_spinner(spinner, ctx.message("core.login.spinner.finalizing")) do
|
|
72
|
+
request_exchange_tokens
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def with_spinner(spinner, message, &block)
|
|
77
|
+
result = nil
|
|
78
|
+
if spinner
|
|
79
|
+
CLI::UI::Spinner.spin(message) do
|
|
80
|
+
result = block.call
|
|
81
|
+
end
|
|
82
|
+
else
|
|
83
|
+
result = block.call
|
|
84
|
+
end
|
|
85
|
+
result
|
|
70
86
|
end
|
|
71
87
|
|
|
72
88
|
def fetch_or_auth_partners_token
|
|
@@ -100,10 +116,14 @@ module ShopifyCLI
|
|
|
100
116
|
end
|
|
101
117
|
|
|
102
118
|
def reauthenticate
|
|
103
|
-
return if
|
|
119
|
+
return if attempt_reauthenticate
|
|
104
120
|
ctx.abort(ctx.message("core.identity_auth.error.reauthenticate", ShopifyCLI::TOOL_NAME))
|
|
105
121
|
end
|
|
106
122
|
|
|
123
|
+
def attempt_reauthenticate
|
|
124
|
+
refresh_exchange_tokens || refresh_access_tokens
|
|
125
|
+
end
|
|
126
|
+
|
|
107
127
|
def code_challenge
|
|
108
128
|
@code_challenge ||= Base64.urlsafe_encode64(
|
|
109
129
|
OpenSSL::Digest::SHA256.digest(code_verifier),
|
|
@@ -18,8 +18,15 @@ module ShopifyCLI
|
|
|
18
18
|
missing_node: "Node.js is required to continue. Install Node.js here: https://nodejs.org/en/download.",
|
|
19
19
|
missing_npm: "npm is required to continue. Install npm here: https://www.npmjs.com/get-npm.",
|
|
20
20
|
missing_ruby: "Ruby is required to continue. Install Ruby here: https://www.ruby-lang.org/en/downloads.",
|
|
21
|
+
bundle_info_failure: "Error getting version for %s gem",
|
|
21
22
|
option_parser: {
|
|
22
23
|
invalid_option: "The option {{command:%s}} is not supported.",
|
|
24
|
+
invalid_option_store_equals: <<~MESSAGE,
|
|
25
|
+
The option {{command:%s}} isn't recognized.
|
|
26
|
+
|
|
27
|
+
Try this:
|
|
28
|
+
{{command:--store=%s}}.
|
|
29
|
+
MESSAGE
|
|
23
30
|
missing_argument: "The required argument {{command:%s}} is missing.",
|
|
24
31
|
},
|
|
25
32
|
},
|
|
@@ -257,6 +264,7 @@ module ShopifyCLI
|
|
|
257
264
|
{{bold:Options:}}
|
|
258
265
|
{{cyan:--host=HOST}}: Bypass running tunnel and use custom host. HOST must be HTTPS url.
|
|
259
266
|
{{cyan:--port=PORT}}: Use custom port.
|
|
267
|
+
{{cyan:--no-update}}: Skips the dashboard URL update step
|
|
260
268
|
HELP
|
|
261
269
|
open_info: <<~MESSAGE,
|
|
262
270
|
{{*}} To install and start using your app, open this URL in your browser:
|
|
@@ -277,6 +285,13 @@ module ShopifyCLI
|
|
|
277
285
|
},
|
|
278
286
|
extension: {
|
|
279
287
|
push: {
|
|
288
|
+
beacon_extension: {
|
|
289
|
+
error: {
|
|
290
|
+
file_read_error: "There was a problem reading %s",
|
|
291
|
+
missing_config_key_error: "Configuration is missing key: %s",
|
|
292
|
+
invalid_config_value_error: "Configuration value is invalid: %s",
|
|
293
|
+
},
|
|
294
|
+
},
|
|
280
295
|
checkout_ui_extension: {
|
|
281
296
|
localization: {
|
|
282
297
|
error: {
|
|
@@ -288,6 +303,7 @@ module ShopifyCLI
|
|
|
288
303
|
invalid_file_extension: "Invalid locale filename: `%s`; only .json files are allowed.",
|
|
289
304
|
invalid_locale_code: "Invalid locale filename: `%s`; locale code should be 2 or 3 letters,"\
|
|
290
305
|
" optionally followed by a two-letter region code, e.g. `fr-CA`.",
|
|
306
|
+
invalid_file_encoding: "Invalid file encoding for `%s`; file encoding should be UTF-8.",
|
|
291
307
|
single_default_locale: "There must be one and only one locale identified as the default locale,"\
|
|
292
308
|
" e.g. `en.default.json`",
|
|
293
309
|
},
|
|
@@ -382,6 +398,7 @@ module ShopifyCLI
|
|
|
382
398
|
sparse_checkout_not_set: "Sparse checkout set command failed.",
|
|
383
399
|
pull_failed: "Pull failed.",
|
|
384
400
|
pull_failed_bad_branch: "Pull failed. Branch %s cannot be found. Check the branch name and try again.",
|
|
401
|
+
merge_failed: "The file %s merge failed.",
|
|
385
402
|
},
|
|
386
403
|
|
|
387
404
|
cloning: "Cloning %s into %s…",
|
|
@@ -432,7 +449,7 @@ module ShopifyCLI
|
|
|
432
449
|
login: {
|
|
433
450
|
help: <<~HELP,
|
|
434
451
|
Log in to the Shopify CLI by authenticating with a store or partner organization
|
|
435
|
-
Usage: {{command:%s login [--store
|
|
452
|
+
Usage: {{command:%s login [--store STORE]}}
|
|
436
453
|
HELP
|
|
437
454
|
invalid_shop: <<~MESSAGE,
|
|
438
455
|
Invalid store provided (%s). Please provide the store in the following format: my-store.myshopify.com
|
|
@@ -440,6 +457,11 @@ module ShopifyCLI
|
|
|
440
457
|
shop_prompt: <<~PROMPT,
|
|
441
458
|
What store are you connecting to? (e.g. my-store.myshopify.com; do {{bold:NOT}} include protocol part, e.g., https://)
|
|
442
459
|
PROMPT
|
|
460
|
+
spinner: {
|
|
461
|
+
initiating: "Initiating authentication",
|
|
462
|
+
finalizing: "Finalizing authentication",
|
|
463
|
+
loading_organizations: "Loading available partner organizations",
|
|
464
|
+
},
|
|
443
465
|
},
|
|
444
466
|
|
|
445
467
|
logout: {
|
|
@@ -454,7 +476,7 @@ module ShopifyCLI
|
|
|
454
476
|
switch: {
|
|
455
477
|
help: <<~HELP,
|
|
456
478
|
Switch between development stores in your partner organization
|
|
457
|
-
Usage: {{command:%s switch [--store
|
|
479
|
+
Usage: {{command:%s switch [--store STORE]}}
|
|
458
480
|
HELP
|
|
459
481
|
disabled_as_shopify_org: "Can't switch development stores logged in as {{green:Shopify partners org}}",
|
|
460
482
|
success: "Switched development store to {{green:%s}}",
|
|
@@ -567,7 +589,7 @@ module ShopifyCLI
|
|
|
567
589
|
HELP
|
|
568
590
|
|
|
569
591
|
error: {
|
|
570
|
-
no_shop: "No store found. Please run {{command:%s login --store
|
|
592
|
+
no_shop: "No store found. Please run {{command:%s login --store STORE}} to login to a specific store",
|
|
571
593
|
},
|
|
572
594
|
|
|
573
595
|
customer: {
|
|
@@ -707,7 +729,6 @@ module ShopifyCLI
|
|
|
707
729
|
updated: "{{v}} Whitelist URLS updated in Partners Dashboard}}",
|
|
708
730
|
update_error:
|
|
709
731
|
"{{x}} error: For authentication issues, run {{command:%s logout}} to clear invalid credentials",
|
|
710
|
-
update_prompt: "Do you want to update your application url?",
|
|
711
732
|
},
|
|
712
733
|
select_org_and_shop: {
|
|
713
734
|
authentication_issue: "For authentication issues, run {{command:%s logout}} to clear invalid credentials",
|
|
@@ -803,7 +824,7 @@ module ShopifyCLI
|
|
|
803
824
|
not_logged_in: <<~MESSAGE,
|
|
804
825
|
It doesn't appear that you're logged in. You must log into a partner organization or a store staff account.
|
|
805
826
|
|
|
806
|
-
If trying to log into a store staff account, please use {{command:%s login --store
|
|
827
|
+
If trying to log into a store staff account, please use {{command:%s login --store STORE}} to log in.
|
|
807
828
|
MESSAGE
|
|
808
829
|
logged_in_shop_only: <<~MESSAGE,
|
|
809
830
|
Logged into store {{green:%s}} as staff (no partner organizations available for this login)
|