shopify-cli 2.14.0 → 2.15.2
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/CONTRIBUTING.md +1 -1
- data/.github/workflows/stale.yml +46 -0
- data/CHANGELOG.md +24 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +39 -7
- data/Rakefile +40 -0
- data/ext/shopify-extensions/version +1 -1
- data/lib/project_types/extension/forms/questions/ask_template.rb +5 -8
- data/lib/project_types/extension/messages/messages.rb +11 -1
- data/lib/project_types/extension/models/development_server_requirements.rb +13 -7
- data/lib/project_types/extension/models/server_config/root.rb +2 -0
- data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +13 -0
- data/lib/project_types/script/config/extension_points.yml +18 -0
- data/lib/project_types/script/layers/infrastructure/errors.rb +17 -0
- data/lib/project_types/script/layers/infrastructure/script_service.rb +2 -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/commands/pull.rb +2 -2
- data/lib/project_types/theme/commands/push.rb +2 -2
- data/lib/project_types/theme/commands/serve.rb +1 -0
- data/lib/project_types/theme/conversions/base_glob.rb +20 -5
- data/lib/project_types/theme/messages/messages.rb +47 -8
- data/lib/shopify_cli/changelog.rb +76 -0
- data/lib/shopify_cli/command.rb +8 -7
- data/lib/shopify_cli/environment.rb +19 -11
- data/lib/shopify_cli/git.rb +36 -0
- data/lib/shopify_cli/messages/messages.rb +16 -9
- data/lib/shopify_cli/release.rb +194 -0
- data/lib/shopify_cli/sed.rb +19 -0
- data/lib/shopify_cli/services/app/create/node_service.rb +2 -14
- data/lib/shopify_cli/services/app/create/php_service.rb +1 -6
- data/lib/shopify_cli/services/app/create/rails_service.rb +4 -12
- 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 +34 -0
- data/lib/shopify_cli/theme/dev_server/remote_watcher.rb +44 -0
- data/lib/shopify_cli/theme/dev_server/watcher.rb +1 -1
- data/lib/shopify_cli/theme/dev_server.rb +15 -3
- 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 +12 -4
- data/lib/shopify_cli/theme/theme_admin_api.rb +24 -23
- 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
- metadata +21 -4
- data/lib/project_types/rails/ruby.rb +0 -17
@@ -0,0 +1,76 @@
|
|
1
|
+
require "shopify_cli/sed"
|
2
|
+
|
3
|
+
module ShopifyCLI
|
4
|
+
class Changelog
|
5
|
+
CHANGELOG_FILE = File.join(ShopifyCLI::ROOT, "CHANGELOG.md")
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
load(File.read(CHANGELOG_FILE))
|
9
|
+
end
|
10
|
+
|
11
|
+
def update_version!(new_version)
|
12
|
+
Sed.new.replace_inline(
|
13
|
+
CHANGELOG_FILE,
|
14
|
+
"## \\[Unreleased\\]",
|
15
|
+
"## [Unreleased]\\n\\n## Version #{new_version}"
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
def release_notes(version)
|
20
|
+
changes[version].map do |change_category, changes|
|
21
|
+
<<~CHANGES
|
22
|
+
### #{change_category}
|
23
|
+
#{changes.map { |change| entry(**change) }.join("\n")}
|
24
|
+
CHANGES
|
25
|
+
end.join("\n")
|
26
|
+
end
|
27
|
+
|
28
|
+
def entry(pr_id:, desc:)
|
29
|
+
"* [##{pr_id}](https://github.com/Shopify/shopify-cli/pull/#{pr_id}): #{desc}"
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def changes
|
35
|
+
@changes ||= Hash.new do |h, k|
|
36
|
+
h[k] = Hash.new do |h2, k2|
|
37
|
+
h2[k2] = []
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def load(log)
|
43
|
+
state = :initial
|
44
|
+
change_category = nil
|
45
|
+
current_version = nil
|
46
|
+
@remainder = ""
|
47
|
+
log.each_line do |line|
|
48
|
+
case state
|
49
|
+
when :initial
|
50
|
+
next unless line.chomp == "\#\# [Unreleased]"
|
51
|
+
state = :unreleased
|
52
|
+
current_version = "Unreleased"
|
53
|
+
when :unreleased, :last_version
|
54
|
+
if /\A\#\#\# (?<category>\w+)/ =~ line
|
55
|
+
change_category = category
|
56
|
+
elsif %r{\A\* \[\#(?<pr_id>\d+)\]\(https://github.com/Shopify/shopify-cli/pull/\d+\): (?<desc>.+)\n} =~ line
|
57
|
+
changes[current_version][change_category] << { pr_id: pr_id, desc: desc }
|
58
|
+
elsif /\A\#\# Version (?<version>\d+\.\d+\.\d+)/ =~ line
|
59
|
+
current_version = version
|
60
|
+
state =
|
61
|
+
case state
|
62
|
+
when :unreleased
|
63
|
+
:last_version
|
64
|
+
else
|
65
|
+
:finished
|
66
|
+
end
|
67
|
+
elsif !line.match?(/\s*\n/)
|
68
|
+
raise "Unrecognized line: #{line.inspect}"
|
69
|
+
end
|
70
|
+
when :finished
|
71
|
+
@remainder << line
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
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
|
@@ -102,16 +109,10 @@ module ShopifyCLI
|
|
102
109
|
def check_node_version
|
103
110
|
return unless @compatible_node_range
|
104
111
|
|
105
|
-
context = Context.new
|
106
|
-
if context.which("node").nil?
|
107
|
-
raise ShopifyCLI::Abort, context.message("core.errors.missing_node")
|
108
|
-
end
|
109
|
-
|
110
112
|
check_version(
|
111
113
|
Environment.node_version,
|
112
114
|
range: @compatible_node_range,
|
113
|
-
runtime: "Node"
|
114
|
-
context: context
|
115
|
+
runtime: "Node"
|
115
116
|
)
|
116
117
|
end
|
117
118
|
|
@@ -12,23 +12,31 @@ module ShopifyCLI
|
|
12
12
|
]
|
13
13
|
|
14
14
|
def self.ruby_version(context: Context.new)
|
15
|
-
|
16
|
-
raise ShopifyCLI::Abort,
|
17
|
-
|
18
|
-
::Semantic::Version.new(
|
15
|
+
output, status = context.capture2e("ruby", "--version")
|
16
|
+
raise ShopifyCLI::Abort, context.message("core.errors.missing_ruby") unless status.success?
|
17
|
+
version = output.match(/ruby (\d+\.\d+\.\d+)/)[1]
|
18
|
+
::Semantic::Version.new(version)
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.node_version(context: Context.new)
|
22
|
-
|
23
|
-
raise ShopifyCLI::Abort,
|
24
|
-
|
25
|
-
::Semantic::Version.new(
|
22
|
+
output, status = context.capture2e("node", "--version")
|
23
|
+
raise ShopifyCLI::Abort, context.message("core.errors.missing_node") unless status.success?
|
24
|
+
version = output.match(/v(\d+\.\d+\.\d+)/)[1]
|
25
|
+
::Semantic::Version.new(version)
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.npm_version(context: Context.new)
|
29
|
-
|
30
|
-
raise ShopifyCLI::Abort,
|
31
|
-
|
29
|
+
output, status = context.capture2e("npm", "--version")
|
30
|
+
raise ShopifyCLI::Abort, context.message("core.errors.missing_npm") unless status.success?
|
31
|
+
version = output.match(/(\d+\.\d+\.\d+)/)[1]
|
32
|
+
::Semantic::Version.new(version)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.rails_version(context: Context.new)
|
36
|
+
output, status = context.capture2e("rails", "--version")
|
37
|
+
context.abort(context.message("core.app.create.rails.error.install_failure", "rails")) unless status.success?
|
38
|
+
version = output.match(/Rails (\d+\.\d+\.\d+)/)[1]
|
39
|
+
::Semantic::Version.new(version)
|
32
40
|
end
|
33
41
|
|
34
42
|
def self.interactive=(interactive)
|
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.
|
@@ -15,9 +15,17 @@ module ShopifyCLI
|
|
15
15
|
},
|
16
16
|
core: {
|
17
17
|
errors: {
|
18
|
-
missing_node: "Node is required to continue. Install
|
18
|
+
missing_node: "Node.js is required to continue. Install Node.js here: https://nodejs.org/en/download.",
|
19
|
+
missing_npm: "npm is required to continue. Install npm here: https://www.npmjs.com/get-npm.",
|
20
|
+
missing_ruby: "Ruby is required to continue. Install Ruby here: https://www.ruby-lang.org/en/downloads.",
|
19
21
|
option_parser: {
|
20
22
|
invalid_option: "The option {{command:%s}} is not supported.",
|
23
|
+
invalid_option_store_equals: <<~MESSAGE,
|
24
|
+
The option {{command:%s}} isn't recognized.
|
25
|
+
|
26
|
+
Try this:
|
27
|
+
{{command:--store=%s}}.
|
28
|
+
MESSAGE
|
21
29
|
missing_argument: "The required argument {{command:%s}} is missing.",
|
22
30
|
},
|
23
31
|
},
|
@@ -95,8 +103,6 @@ module ShopifyCLI
|
|
95
103
|
HELP
|
96
104
|
error: {
|
97
105
|
node_required: "node is required to create an app project. Download at https://nodejs.org/en/download.",
|
98
|
-
node_version_failure: "Failed to get the current node version. Please make sure it is installed as " \
|
99
|
-
"per the instructions at https://nodejs.org/en.",
|
100
106
|
npm_required: "npm is required to create an app project. Download at https://www.npmjs.com/get-npm.",
|
101
107
|
npm_version_failure: "Failed to get the current npm version. Please make sure it is installed as per " \
|
102
108
|
"the instructions at https://www.npmjs.com/get-npm.",
|
@@ -131,8 +137,6 @@ module ShopifyCLI
|
|
131
137
|
{{underline:https://getcomposer.org/download/}}
|
132
138
|
COMPOSER
|
133
139
|
npm_required: "npm is required to create an app project. Download at https://www.npmjs.com/get-npm.",
|
134
|
-
npm_version_failure: "Failed to get the current npm version. Please make sure it is installed as per " \
|
135
|
-
"the instructions at https://www.npmjs.com/get-npm.",
|
136
140
|
app_setup: "Failed to set up the app",
|
137
141
|
},
|
138
142
|
|
@@ -283,6 +287,8 @@ module ShopifyCLI
|
|
283
287
|
localization: {
|
284
288
|
error: {
|
285
289
|
bundle_too_large: "Total size of all locale files must be less than %s.",
|
290
|
+
duplicate_locale_code: "Duplicate locale found: `%s`; locale codes"\
|
291
|
+
" should be unique and are case insensitive.",
|
286
292
|
file_empty: "Locale file `%s` is empty.",
|
287
293
|
file_too_large: "Locale file `%s` too large; size must be less than %s.",
|
288
294
|
invalid_file_extension: "Invalid locale filename: `%s`; only .json files are allowed.",
|
@@ -382,6 +388,7 @@ module ShopifyCLI
|
|
382
388
|
sparse_checkout_not_set: "Sparse checkout set command failed.",
|
383
389
|
pull_failed: "Pull failed.",
|
384
390
|
pull_failed_bad_branch: "Pull failed. Branch %s cannot be found. Check the branch name and try again.",
|
391
|
+
merge_failed: "The file %s merge failed.",
|
385
392
|
},
|
386
393
|
|
387
394
|
cloning: "Cloning %s into %s…",
|
@@ -432,7 +439,7 @@ module ShopifyCLI
|
|
432
439
|
login: {
|
433
440
|
help: <<~HELP,
|
434
441
|
Log in to the Shopify CLI by authenticating with a store or partner organization
|
435
|
-
Usage: {{command:%s login [--store
|
442
|
+
Usage: {{command:%s login [--store STORE]}}
|
436
443
|
HELP
|
437
444
|
invalid_shop: <<~MESSAGE,
|
438
445
|
Invalid store provided (%s). Please provide the store in the following format: my-store.myshopify.com
|
@@ -454,7 +461,7 @@ module ShopifyCLI
|
|
454
461
|
switch: {
|
455
462
|
help: <<~HELP,
|
456
463
|
Switch between development stores in your partner organization
|
457
|
-
Usage: {{command:%s switch [--store
|
464
|
+
Usage: {{command:%s switch [--store STORE]}}
|
458
465
|
HELP
|
459
466
|
disabled_as_shopify_org: "Can't switch development stores logged in as {{green:Shopify partners org}}",
|
460
467
|
success: "Switched development store to {{green:%s}}",
|
@@ -567,7 +574,7 @@ module ShopifyCLI
|
|
567
574
|
HELP
|
568
575
|
|
569
576
|
error: {
|
570
|
-
no_shop: "No store found. Please run {{command:%s login --store
|
577
|
+
no_shop: "No store found. Please run {{command:%s login --store STORE}} to login to a specific store",
|
571
578
|
},
|
572
579
|
|
573
580
|
customer: {
|
@@ -803,7 +810,7 @@ module ShopifyCLI
|
|
803
810
|
not_logged_in: <<~MESSAGE,
|
804
811
|
It doesn't appear that you're logged in. You must log into a partner organization or a store staff account.
|
805
812
|
|
806
|
-
If trying to log into a store staff account, please use {{command:%s login --store
|
813
|
+
If trying to log into a store staff account, please use {{command:%s login --store STORE}} to log in.
|
807
814
|
MESSAGE
|
808
815
|
logged_in_shop_only: <<~MESSAGE,
|
809
816
|
Logged into store {{green:%s}} as staff (no partner organizations available for this login)
|
@@ -0,0 +1,194 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "fileutils"
|
3
|
+
require "shopify_cli/sed"
|
4
|
+
require "shopify_cli/changelog"
|
5
|
+
require "octokit"
|
6
|
+
|
7
|
+
module ShopifyCLI
|
8
|
+
class Release
|
9
|
+
def initialize(new_version, github_access_token)
|
10
|
+
@new_version = new_version
|
11
|
+
@changelog = ShopifyCLI::Changelog.new
|
12
|
+
@github = Octokit::Client.new(access_token: github_access_token)
|
13
|
+
end
|
14
|
+
|
15
|
+
def prepare!
|
16
|
+
ensure_updated_main
|
17
|
+
create_release_branch
|
18
|
+
update_changelog
|
19
|
+
update_versions_in_files
|
20
|
+
commit_packaging
|
21
|
+
pr = create_pr
|
22
|
+
system("open #{pr["html_url"]}")
|
23
|
+
end
|
24
|
+
|
25
|
+
def package!
|
26
|
+
ensure_updated_main
|
27
|
+
ensure_correct_gem_version
|
28
|
+
Rake::Task["package"].invoke
|
29
|
+
update_homebrew
|
30
|
+
create_github_release
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
attr_reader :new_version, :changelog, :github
|
36
|
+
|
37
|
+
def ensure_updated_main
|
38
|
+
# We can't be sure what is the correct action to take if changes have been
|
39
|
+
# made but not committed. Ensure the user handles the situation before
|
40
|
+
# moving on.
|
41
|
+
unless %x(git status --porcelain).empty?
|
42
|
+
raise <<~MESSAGE
|
43
|
+
Uncommitted changes have been made to the repository.
|
44
|
+
Please make sure `git status` does not show any changes before continuing.
|
45
|
+
MESSAGE
|
46
|
+
end
|
47
|
+
system_or_fail("git checkout main", "check out main branch")
|
48
|
+
unless system("git pull")
|
49
|
+
raise "git pull failed, cannot be sure there aren't new commits!"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_release_branch
|
54
|
+
puts "Checking out release branch"
|
55
|
+
system_or_fail("git checkout -b #{release_branch_name}", "check out release branch")
|
56
|
+
end
|
57
|
+
|
58
|
+
def update_changelog
|
59
|
+
if release_notes("Unreleased").empty?
|
60
|
+
puts "No unreleased CHANGELOG updates found!"
|
61
|
+
else
|
62
|
+
puts "Updating CHANGELOG"
|
63
|
+
changelog.update_version!(new_version)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def update_versions_in_files
|
68
|
+
version_file = File.join(ShopifyCLI::ROOT, "lib/shopify_cli/version.rb")
|
69
|
+
puts "Updating version.rb"
|
70
|
+
ShopifyCLI::Sed.new.replace_inline(version_file, ShopifyCLI::VERSION, new_version)
|
71
|
+
gemfile_lock = File.join(ShopifyCLI::ROOT, "Gemfile.lock")
|
72
|
+
puts "Updating Gemfile.lock"
|
73
|
+
ShopifyCLI::Sed.new.replace_inline(
|
74
|
+
gemfile_lock,
|
75
|
+
"shopify-cli (#{ShopifyCLI::VERSION})",
|
76
|
+
"shopify-cli (#{new_version})",
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
def commit_packaging
|
81
|
+
puts "Committing"
|
82
|
+
system_or_fail("git commit -am 'Packaging for release v#{new_version}'", "commit")
|
83
|
+
system_or_fail("git push -u origin #{release_branch_name}", "push branch")
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_pr
|
87
|
+
repo = "Shopify/shopify-cli"
|
88
|
+
github.create_pull_request(
|
89
|
+
repo,
|
90
|
+
"main",
|
91
|
+
release_branch_name,
|
92
|
+
"Packaging for release v#{new_version}",
|
93
|
+
release_notes("Unreleased")
|
94
|
+
).tap { |results| puts "Created #{repo} PR ##{results["number"]}" }
|
95
|
+
end
|
96
|
+
|
97
|
+
def ensure_correct_gem_version
|
98
|
+
response = Net::HTTP.get(URI("https://rubygems.org/api/v1/versions/shopify-cli/latest.json"))
|
99
|
+
latest_version = JSON.parse(response)["version"]
|
100
|
+
unless latest_version == new_version
|
101
|
+
raise "Attempted to update to #{new_version}, but latest on RubyGems is #{latest_version}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def update_homebrew
|
106
|
+
ensure_updated_homebrew_repo
|
107
|
+
update_homebrew_repo
|
108
|
+
pr = create_homebrew_pr
|
109
|
+
system("open #{pr["html_url"]}")
|
110
|
+
end
|
111
|
+
|
112
|
+
def ensure_updated_homebrew_repo
|
113
|
+
unless File.exist?(homebrew_path)
|
114
|
+
system_or_fail("/opt/dev/bin/dev clone homebrew-shopify", "clone homebrew-shopify repo")
|
115
|
+
end
|
116
|
+
|
117
|
+
Dir.chdir(homebrew_path) do
|
118
|
+
system_or_fail("git checkout master && git pull", "pull latest homebrew-shopify")
|
119
|
+
system_or_fail("git checkout -b #{homebrew_release_branch}", "check out homebrew branch")
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def update_homebrew_repo
|
124
|
+
source_file = File.join(package_dir, "shopify-cli.rb")
|
125
|
+
FileUtils.copy(source_file, homebrew_path)
|
126
|
+
Dir.chdir(homebrew_path) do
|
127
|
+
system_or_fail("git commit -am '#{homebrew_update_message}'", "commit homebrew update")
|
128
|
+
system_or_fail("git push -u origin #{homebrew_release_branch}", "push homebrew branch")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def create_homebrew_pr
|
133
|
+
repo = "Shopify/homebrew-shopify"
|
134
|
+
github.create_pull_request(
|
135
|
+
repo,
|
136
|
+
"master",
|
137
|
+
homebrew_release_branch,
|
138
|
+
homebrew_update_message,
|
139
|
+
homebrew_release_notes
|
140
|
+
).tap { |results| puts "Created #{repo} PR ##{results["number"]}" }
|
141
|
+
end
|
142
|
+
|
143
|
+
def create_github_release
|
144
|
+
release = github.create_release(
|
145
|
+
"Shopify/shopify-cli",
|
146
|
+
"v#{new_version}",
|
147
|
+
{
|
148
|
+
name: "Version #{new_version}",
|
149
|
+
body: release_notes(new_version),
|
150
|
+
}
|
151
|
+
)
|
152
|
+
%w(.deb -1.noarch.rpm).each do |suffix|
|
153
|
+
github.upload_asset(
|
154
|
+
release["url"],
|
155
|
+
File.join(package_dir, "shopify-cli-#{new_version}#{suffix}")
|
156
|
+
)
|
157
|
+
end
|
158
|
+
system("open #{release["html_url"]}")
|
159
|
+
end
|
160
|
+
|
161
|
+
def homebrew_path
|
162
|
+
@homebrew_path ||= %x(/opt/dev/bin/dev project-path homebrew-shopify).chomp
|
163
|
+
end
|
164
|
+
|
165
|
+
def homebrew_update_message
|
166
|
+
@homebrew_update_message ||= "Update Shopify CLI to #{new_version}"
|
167
|
+
end
|
168
|
+
|
169
|
+
def package_dir
|
170
|
+
@package_dir ||= File.join(ShopifyCLI::ROOT, "packaging", "builds", new_version)
|
171
|
+
end
|
172
|
+
|
173
|
+
def homebrew_release_branch
|
174
|
+
"release_#{new_version.split(".").join("_")}_of_shopify-cli"
|
175
|
+
end
|
176
|
+
|
177
|
+
def homebrew_release_notes
|
178
|
+
"I'm releasing a new version of the Shopify CLI, " \
|
179
|
+
"[#{new_version}](https://github.com/Shopify/shopify-cli/releases/tag/v#{new_version})"
|
180
|
+
end
|
181
|
+
|
182
|
+
def release_branch_name
|
183
|
+
@release_branch_name ||= "release_#{new_version.split(".").join("_")}"
|
184
|
+
end
|
185
|
+
|
186
|
+
def release_notes(version)
|
187
|
+
changelog.release_notes(version)
|
188
|
+
end
|
189
|
+
|
190
|
+
def system_or_fail(command, action)
|
191
|
+
raise "Failed to #{action}!" unless system(command)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ShopifyCLI
|
2
|
+
class Sed
|
3
|
+
class SedError < StandardError; end
|
4
|
+
|
5
|
+
def replace_inline(filename, pattern, output)
|
6
|
+
command =
|
7
|
+
case CLI::Kit::System.os
|
8
|
+
when :mac
|
9
|
+
"sed -i ''"
|
10
|
+
when :linux
|
11
|
+
"sed -i"
|
12
|
+
else
|
13
|
+
raise "Unrecognized system!"
|
14
|
+
end
|
15
|
+
success = system("#{command} 's/#{pattern}/#{output}/' #{filename}")
|
16
|
+
raise SedError unless success
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -88,24 +88,12 @@ module ShopifyCLI
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def check_node
|
91
|
-
|
92
|
-
context.abort(context.message("core.app.create.node.error.node_required")) if cmd_path.nil?
|
93
|
-
|
94
|
-
version, stat = context.capture2e("node", "-v")
|
95
|
-
unless stat.success?
|
96
|
-
context.abort(context.message("core.app.create.node.error.node_version_failure"))
|
97
|
-
end
|
98
|
-
|
91
|
+
version = ShopifyCLI::Environment.node_version(context: context)
|
99
92
|
context.done(context.message("core.app.create.node.node_version", version))
|
100
93
|
end
|
101
94
|
|
102
95
|
def check_npm
|
103
|
-
|
104
|
-
context.abort(context.message("core.app.create.node.error.npm_required")) if cmd_path.nil?
|
105
|
-
|
106
|
-
version, stat = context.capture2e("npm", "-v")
|
107
|
-
context.abort(context.message("core.app.create.node.error.npm_version_failure")) unless stat.success?
|
108
|
-
|
96
|
+
version = ShopifyCLI::Environment.npm_version(context: context)
|
109
97
|
context.done(context.message("core.app.create.node.npm_version", version))
|
110
98
|
end
|
111
99
|
|
@@ -69,12 +69,7 @@ module ShopifyCLI
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def check_npm
|
72
|
-
|
73
|
-
context.abort(context.message("core.app.create.php.error.npm_required")) if cmd_path.nil?
|
74
|
-
|
75
|
-
version, stat = context.capture2e("npm", "-v")
|
76
|
-
context.abort(context.message("core.app.create.php.error.npm_version_failure")) unless stat.success?
|
77
|
-
|
72
|
+
version = ShopifyCLI::Environment.npm_version(context: context)
|
78
73
|
context.done(context.message("core.app.create.php.npm_version", version))
|
79
74
|
end
|
80
75
|
|
@@ -108,7 +108,7 @@ module ShopifyCLI
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def check_ruby
|
111
|
-
ruby_version =
|
111
|
+
ruby_version = Environment.ruby_version(context: context)
|
112
112
|
return if ruby_version.satisfies?("~>2.5") || ruby_version.satisfies?("~>3.1.0")
|
113
113
|
context.abort(context.message("core.app.create.rails.error.invalid_ruby_version"))
|
114
114
|
end
|
@@ -219,18 +219,10 @@ module ShopifyCLI
|
|
219
219
|
end
|
220
220
|
|
221
221
|
def install_webpacker?
|
222
|
-
rails_version
|
223
|
-
|
224
|
-
end
|
225
|
-
|
226
|
-
def rails_version
|
227
|
-
output, status = context.capture2e("rails", "--version")
|
228
|
-
unless status.success?
|
229
|
-
context.abort(context.message("core.app.create.rails.error.install_failure", "rails"))
|
230
|
-
end
|
222
|
+
rails_version = Environment.rails_version(context: context)
|
223
|
+
webpacker_config = File.exist?(File.join(context.root, "config/webpacker.yml"))
|
231
224
|
|
232
|
-
|
233
|
-
::Semantic::Version.new(version)
|
225
|
+
rails_version < ::Semantic::Version.new("7.0.0") && !webpacker_config
|
234
226
|
end
|
235
227
|
end
|
236
228
|
end
|
@@ -15,17 +15,37 @@
|
|
15
15
|
eventSource.onerror = () => eventSource.close();
|
16
16
|
}
|
17
17
|
|
18
|
+
function sectionNamesByType(type) {
|
19
|
+
const namespace = window.__SHOPIFY_CLI_ENV__;
|
20
|
+
return namespace.section_names_by_type[type] || [];
|
21
|
+
}
|
22
|
+
|
18
23
|
function reloadMode() {
|
19
|
-
|
24
|
+
const namespace = window.__SHOPIFY_CLI_ENV__;
|
20
25
|
return namespace.mode;
|
21
26
|
}
|
22
27
|
|
28
|
+
function querySelectDOMSections(idSuffix) {
|
29
|
+
const elements = document.querySelectorAll(`[id^='shopify-section'][id$='${idSuffix}']`);
|
30
|
+
return Array.from(elements);
|
31
|
+
}
|
32
|
+
|
33
|
+
function fetchDOMSections(name) {
|
34
|
+
const domSections = sectionNamesByType(name).flatMap((n) => querySelectDOMSections(n));
|
35
|
+
|
36
|
+
if (domSections.length > 0) {
|
37
|
+
return domSections;
|
38
|
+
}
|
39
|
+
|
40
|
+
return querySelectDOMSections(name);
|
41
|
+
}
|
42
|
+
|
23
43
|
function isFullPageReloadMode(){
|
24
|
-
return reloadMode() ===
|
44
|
+
return reloadMode() === 'full-page';
|
25
45
|
}
|
26
46
|
|
27
47
|
function isReloadModeActive(){
|
28
|
-
return reloadMode() !==
|
48
|
+
return reloadMode() !== 'off';
|
29
49
|
}
|
30
50
|
|
31
51
|
function isRefreshRequired(files) {
|
@@ -104,26 +124,28 @@
|
|
104
124
|
constructor(filename) {
|
105
125
|
this.filename = filename;
|
106
126
|
this.name = filename.split('/').pop().replace('.liquid', '');
|
107
|
-
this.
|
127
|
+
this.elements = fetchDOMSections(this.name);
|
108
128
|
}
|
109
129
|
|
110
130
|
valid() {
|
111
|
-
return this.filename.startsWith('sections/') && this.
|
131
|
+
return this.filename.startsWith('sections/') && this.elements.length > 0;
|
112
132
|
}
|
113
133
|
|
114
|
-
async
|
115
|
-
|
116
|
-
|
134
|
+
async refreshElement(element) {
|
135
|
+
|
136
|
+
const sectionId = element.id.replace(/^shopify-section-/, '');
|
137
|
+
const url = new URL(window.location.href);
|
138
|
+
|
139
|
+
url.searchParams.append('section_id', sectionId);
|
140
|
+
|
141
|
+
const response = await fetch(url);
|
117
142
|
|
118
143
|
try {
|
119
|
-
const response = await fetch(url);
|
120
144
|
if (response.headers.get('x-templates-from-params') == '1') {
|
121
145
|
const html = await response.text();
|
122
|
-
|
123
|
-
|
124
|
-
console.log(`[HotReload] Reloaded ${this.name} section`);
|
146
|
+
element.outerHTML = html;
|
125
147
|
} else {
|
126
|
-
window.location.reload()
|
148
|
+
window.location.reload();
|
127
149
|
|
128
150
|
console.log(`[HotReload] Hot-reloading not supported, fully reloading ${this.name} section`);
|
129
151
|
}
|
@@ -132,6 +154,11 @@
|
|
132
154
|
console.log(`[HotReload] Failed to reload ${this.name} section: ${e.message}`);
|
133
155
|
}
|
134
156
|
}
|
157
|
+
|
158
|
+
async refresh() {
|
159
|
+
console.log(`[HotReload] Reloaded ${this.name} sections`);
|
160
|
+
this.elements.forEach(this.refreshElement);
|
161
|
+
}
|
135
162
|
}
|
136
163
|
|
137
164
|
if (isReloadModeActive()) {
|
@@ -51,7 +51,7 @@ module ShopifyCLI
|
|
51
51
|
def fetch_asset(file)
|
52
52
|
api_client.get(
|
53
53
|
path: "themes/#{@theme.id}/assets.json",
|
54
|
-
query: URI.encode_www_form("asset[key]" => file.relative_path
|
54
|
+
query: URI.encode_www_form("asset[key]" => file.relative_path),
|
55
55
|
)
|
56
56
|
rescue ShopifyCLI::API::APIRequestNotFoundError
|
57
57
|
[404, {}]
|