shopify-cli 2.15.0 → 2.15.3
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|