shopify-cli 2.24.0 → 2.25.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/lib/project_types/extension/commands/serve.rb +57 -3
- data/lib/project_types/extension/extension_project.rb +8 -1
- data/lib/project_types/extension/loaders/project.rb +3 -2
- data/lib/project_types/extension/messages/messages.rb +21 -6
- data/lib/project_types/extension/models/server_config/development_renderer.rb +1 -1
- data/lib/project_types/extension/models/specification_handlers/theme_app_extension.rb +18 -6
- data/lib/project_types/theme/commands/serve.rb +15 -3
- data/lib/project_types/theme/messages/messages.rb +4 -2
- data/lib/shopify_cli/commands/logout.rb +13 -2
- data/lib/shopify_cli/environment.rb +1 -1
- data/lib/shopify_cli/file_system_listener.rb +30 -0
- data/lib/shopify_cli/git.rb +116 -33
- data/lib/shopify_cli/identity_auth.rb +1 -0
- data/lib/shopify_cli/project.rb +1 -1
- data/lib/shopify_cli/tasks/ensure_project_type.rb +3 -1
- data/lib/shopify_cli/theme/dev_server/cdn_fonts.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/certificate_manager.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/errors.rb +9 -0
- data/lib/shopify_cli/theme/dev_server/header_hash.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/hooks/file_change_hook.rb +77 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload/remote_file_deleter.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/{hot-reload-no-script.html → hot_reload/resources/hot-reload-no-script.html} +0 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload/resources/hot_reload.js +48 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload/resources/sse_client.js +43 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload/resources/theme.js +114 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload/resources/theme_extension.js +121 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload/script_injector.rb +57 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload/sections_index.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/hot_reload.rb +8 -76
- data/lib/shopify_cli/theme/dev_server/local_assets.rb +28 -28
- data/lib/shopify_cli/theme/dev_server/proxy.rb +33 -25
- data/lib/shopify_cli/theme/dev_server/proxy_param_builder.rb +82 -0
- data/lib/shopify_cli/theme/dev_server/reload_mode.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/remote_watcher/json_files_update_job.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/remote_watcher.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/sse.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/watcher.rb +8 -9
- data/lib/shopify_cli/theme/dev_server/web_server.rb +1 -1
- data/lib/shopify_cli/theme/dev_server.rb +287 -99
- data/lib/shopify_cli/theme/extension/app_extension.rb +40 -0
- data/lib/shopify_cli/theme/extension/dev_server/hooks/file_change_hook.rb +68 -0
- data/lib/shopify_cli/theme/extension/dev_server/hot_reload/script_injector.rb +30 -0
- data/lib/shopify_cli/theme/extension/dev_server/hot_reload.rb +13 -0
- data/lib/shopify_cli/theme/extension/dev_server/local_assets.rb +30 -0
- data/lib/shopify_cli/theme/{dev_server/proxy/template_param_builder.rb → extension/dev_server/proxy_param_builder.rb} +26 -16
- data/lib/shopify_cli/theme/extension/dev_server/watcher.rb +47 -0
- data/lib/shopify_cli/theme/extension/dev_server.rb +150 -0
- data/lib/shopify_cli/theme/extension/host_theme.rb +104 -0
- data/lib/shopify_cli/theme/extension/syncer/extension_serve_job.rb +133 -0
- data/lib/shopify_cli/theme/extension/syncer/operation.rb +21 -0
- data/lib/shopify_cli/theme/extension/syncer.rb +81 -0
- data/lib/shopify_cli/theme/extension/ui/host_theme_progress_bar.rb +35 -0
- data/lib/shopify_cli/theme/ignore_helper.rb +31 -0
- data/lib/shopify_cli/theme/root.rb +62 -0
- data/lib/shopify_cli/theme/syncer.rb +12 -6
- data/lib/shopify_cli/theme/theme.rb +10 -52
- data/lib/shopify_cli/version.rb +1 -1
- metadata +27 -7
- data/.github/workflows/triage.yml +0 -22
- data/lib/shopify_cli/theme/dev_server/hot-reload.js +0 -194
- data/lib/shopify_cli/theme/syncer/ignore_helper.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dadea44d5b05c23d4e74988aac50cae2713ee0809ad3b92b0a32a2ae51915a35
|
4
|
+
data.tar.gz: efaccb6aee8feb1bd714f4b6d2fa2ded67e522ac49eedaaa592fc3dbc066b04d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d283f76d8b288ad25487a50f86ff9482abef14f4d9ad7d95e006ea36a976f4cfb2410235e5a18cf12ea5c19d225117fd0516735b574c7c63551809422a102e19
|
7
|
+
data.tar.gz: 63e45bf4543a6743859c02a766e8b61c682703145d6230410d5200f76d9ca207c7ae996a1dc89dd8e918dfbb21d17aa17dd834f694df274f96a9fab29a4af606
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@ 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.25.0 - 2022-09-14
|
6
|
+
|
7
|
+
### Added
|
8
|
+
* [#2600](https://github.com/Shopify/shopify-cli/pull/2600): Add support to the `SIGTERM` signal
|
9
|
+
* [#2602](https://github.com/Shopify/shopify-cli/pull/2602): Add `--only/--ignore` support to the `theme serve` command
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
* [#2607](https://github.com/Shopify/shopify-cli/pull/2607): Fix proxy to redirect to host and port set by cli
|
13
|
+
|
5
14
|
## Version 2.24.0 - 2022-08-29
|
6
15
|
|
7
16
|
### Fixed
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Shopify CLI 2.0
|
2
2
|
|
3
|
-
<a href=""><img src="https://github.com/shopify/shopify-cli/workflows/
|
3
|
+
<a href="https://github.com/Shopify/shopify-cli/actions/workflows/shopify.yml"><img src="https://github.com/shopify/shopify-cli/actions/workflows/shopify.yml/badge.svg" alt="Shopify"></a>
|
4
4
|
<img src="https://img.shields.io/github/v/release/shopify/shopify-cli?include_prereleases&style=flat-square" alt="Latest Version">
|
5
5
|
<img src="https://img.shields.io/github/forks/shopify/shopify-cli?style=flat-square" alt="GitHub forks">
|
6
6
|
<img src="https://img.shields.io/github/stars/shopify/shopify-cli?style=flat-square" alt="GitHub stars">
|
@@ -17,6 +17,24 @@ module Extension
|
|
17
17
|
parser.on("-p", "--port=PORT", "Specify the port to use") do |port|
|
18
18
|
flags[:port] = port.to_i
|
19
19
|
end
|
20
|
+
parser.on("-T", "--theme=NAME_OR_ID", "Theme ID or name of the theme app extension host theme.") do |theme|
|
21
|
+
flags[:theme] = theme
|
22
|
+
end
|
23
|
+
parser.on("--api-key=API_KEY", "Connect your extension and app by inserting your app's API key") do |api_key|
|
24
|
+
flags[:api_key] = api_key.gsub('"', "")
|
25
|
+
end
|
26
|
+
parser.on("--api-secret=API_SECRET", "The API secret of the app the script is registered with.") do |api_secret|
|
27
|
+
flags[:api_secret] = api_secret.gsub('"', "")
|
28
|
+
end
|
29
|
+
parser.on("--extension-id=EXTENSION_ID", "The id of the extension's registration.") do |registration_id|
|
30
|
+
flags[:registration_id] = registration_id.gsub('"', "")
|
31
|
+
end
|
32
|
+
parser.on("--extension-title=EXTENSION_TITLE", "The title of the extension") do |extension_title|
|
33
|
+
flags[:extension_title] = extension_title.gsub('"', "")
|
34
|
+
end
|
35
|
+
parser.on("--extension-type=EXTENSION_TYPE", "The type of the extension") do |extension_type|
|
36
|
+
flags[:extension_type] = extension_type.gsub('"', "")
|
37
|
+
end
|
20
38
|
end
|
21
39
|
|
22
40
|
class RuntimeConfiguration
|
@@ -26,13 +44,27 @@ module Extension
|
|
26
44
|
property :resource_url, accepts: String, default: nil
|
27
45
|
property! :tunnel_requested, accepts: [true, false], reader: :tunnel_requested?, default: true
|
28
46
|
property :port, accepts: (1...(2**16))
|
47
|
+
property :theme, accepts: String, default: nil
|
48
|
+
property :api_key, accepts: String, default: nil
|
49
|
+
property :api_secret, accepts: String, default: nil
|
50
|
+
property :registration_id, accepts: String, default: nil
|
51
|
+
property :extension_title, accepts: String, default: nil
|
52
|
+
property :extension_type, accepts: String, default: nil
|
29
53
|
end
|
30
54
|
|
31
|
-
def call(
|
55
|
+
def call(args, _command_name)
|
56
|
+
@ctx.root = args.first || @ctx.root
|
57
|
+
|
32
58
|
config = RuntimeConfiguration.new(
|
33
59
|
tunnel_requested: tunnel_requested?,
|
34
60
|
resource_url: options.flags[:resource_url],
|
35
|
-
port: options.flags[:port]
|
61
|
+
port: options.flags[:port],
|
62
|
+
theme: options.flags[:theme],
|
63
|
+
api_key: options.flags[:api_key],
|
64
|
+
api_secret: options.flags[:api_secret],
|
65
|
+
registration_id: options.flags[:registration_id],
|
66
|
+
extension_title: options.flags[:extension_title],
|
67
|
+
extension_type: options.flags[:extension_type],
|
36
68
|
)
|
37
69
|
|
38
70
|
ShopifyCLI::Result
|
@@ -49,6 +81,23 @@ module Extension
|
|
49
81
|
|
50
82
|
private
|
51
83
|
|
84
|
+
def project
|
85
|
+
return super unless options.flags[:extension_type]
|
86
|
+
|
87
|
+
@project ||= Extension::Loaders::Project.load(
|
88
|
+
context: options.flags[:context],
|
89
|
+
directory: @ctx.root,
|
90
|
+
api_key: options.flags[:api_key],
|
91
|
+
api_secret: options.flags[:api_secret],
|
92
|
+
registration_id: options.flags[:registration_id],
|
93
|
+
env: {
|
94
|
+
ExtensionProjectKeys::TITLE_KEY => options.flags[:extension_title],
|
95
|
+
ExtensionProjectKeys::REGISTRATION_ID_KEY => options.flags[:registration_id],
|
96
|
+
ExtensionProjectKeys::SPECIFICATION_IDENTIFIER_KEY => options.flags[:extension_type],
|
97
|
+
}
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
52
101
|
def tunnel_requested?
|
53
102
|
tunnel = options.flags[:tunnel]
|
54
103
|
tunnel.nil? || !!tunnel
|
@@ -87,7 +136,12 @@ module Extension
|
|
87
136
|
context: @ctx,
|
88
137
|
tunnel_url: runtime_configuration.tunnel_url,
|
89
138
|
port: runtime_configuration.port,
|
90
|
-
|
139
|
+
theme: runtime_configuration.theme,
|
140
|
+
api_key: runtime_configuration.api_key,
|
141
|
+
api_secret: runtime_configuration.api_secret,
|
142
|
+
registration_id: runtime_configuration.registration_id,
|
143
|
+
resource_url: runtime_configuration.resource_url,
|
144
|
+
project: project,
|
91
145
|
)
|
92
146
|
runtime_configuration
|
93
147
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "shopify_cli"
|
3
|
+
require "shopify_cli/environment"
|
3
4
|
require "securerandom"
|
4
5
|
|
5
6
|
module Extension
|
@@ -82,7 +83,13 @@ module Extension
|
|
82
83
|
end
|
83
84
|
|
84
85
|
def specification_identifier
|
85
|
-
|
86
|
+
key = ExtensionProjectKeys::SPECIFICATION_IDENTIFIER_KEY
|
87
|
+
|
88
|
+
if ShopifyCLI::Environment.run_as_subprocess?
|
89
|
+
get_extra_field(key)
|
90
|
+
else
|
91
|
+
config[key]
|
92
|
+
end
|
86
93
|
end
|
87
94
|
|
88
95
|
def registration_id?
|
@@ -3,12 +3,13 @@
|
|
3
3
|
module Extension
|
4
4
|
module Loaders
|
5
5
|
module Project
|
6
|
-
def self.load(context:, directory:, api_key:, registration_id:, api_secret:)
|
6
|
+
def self.load(context:, directory:, api_key:, registration_id:, api_secret:, env: {})
|
7
7
|
env_overrides = {
|
8
8
|
"SHOPIFY_API_KEY" => api_key,
|
9
9
|
"SHOPIFY_API_SECRET" => api_secret,
|
10
10
|
"EXTENSION_ID" => registration_id,
|
11
|
-
}.compact
|
11
|
+
}.compact.merge(env)
|
12
|
+
|
12
13
|
env_file_present = env_file_exists?(directory)
|
13
14
|
env = if env_file_present
|
14
15
|
ShopifyCLI::Resources::EnvFile.read(directory, overrides: env_overrides)
|
@@ -102,15 +102,32 @@ module Extension
|
|
102
102
|
serve: {
|
103
103
|
help: <<~HELP,
|
104
104
|
Serve your extension in a local simulator for development.
|
105
|
-
Usage: {{command:%s extension serve}}
|
105
|
+
Usage: {{command:%s extension serve [ ROOT ]}}
|
106
106
|
Options:
|
107
|
-
|
107
|
+
{{command:-p, --port=PORT}} Local port of the development serve.
|
108
|
+
{{command:-T, --theme=NAME_OR_ID}} Theme ID or name of the host theme.
|
109
|
+
{{command:--tunnel=TUNNEL}} Establish an ngrok tunnel (default: false).
|
110
|
+
{{command:--api-key=API_KEY}} Connect your extension and app by inserting your app's API key (which you can get from your app setup page on shopify.dev).
|
111
|
+
{{command:--api-secret=API_SECRET}} The API secret of the app the script is registered with.
|
112
|
+
{{command:--extension-id=EXTENSION_ID}} The id of the extension's registration.
|
108
113
|
HELP
|
109
|
-
frame_title: "
|
114
|
+
frame_title: "Viewing extension…",
|
110
115
|
no_available_ports_found: "No available ports found to run extension.",
|
111
116
|
serve_failure_message: "Failed to run extension code.",
|
112
117
|
serve_missing_information: "Missing shop or api_key.",
|
113
118
|
tunnel_already_running: "A tunnel running on another port has been detected. Close the tunnel and try again.",
|
119
|
+
preview_message: <<~PREVIEW_MESSAGE,
|
120
|
+
Enable your theme app extension:
|
121
|
+
{{green:%s}}
|
122
|
+
|
123
|
+
Setup your theme app extension in the host theme:
|
124
|
+
{{green:%s}}
|
125
|
+
|
126
|
+
Preview your theme app extension:
|
127
|
+
{{green:%s}}
|
128
|
+
|
129
|
+
(Use Ctrl-C to stop)
|
130
|
+
PREVIEW_MESSAGE
|
114
131
|
},
|
115
132
|
tunnel: {
|
116
133
|
duplicate_session: <<~MESSAGE,
|
@@ -267,9 +284,7 @@ module Extension
|
|
267
284
|
{{*}} You’re ready to start building {{green:%s}}!
|
268
285
|
MESSAGE
|
269
286
|
},
|
270
|
-
|
271
|
-
unsupported: "shopify extension serve is not supported for theme app extensions",
|
272
|
-
},
|
287
|
+
|
273
288
|
},
|
274
289
|
},
|
275
290
|
}
|
@@ -25,7 +25,7 @@ module Extension
|
|
25
25
|
when "checkout_post_purchase"
|
26
26
|
new(name: "@shopify/post-purchase-ui-extensions", version: "^0.13.2")
|
27
27
|
when "pos_ui_extension"
|
28
|
-
new(name: "@shopify/retail-ui-extensions", version: "^0.
|
28
|
+
new(name: "@shopify/retail-ui-extensions", version: "^0.12.0")
|
29
29
|
when "web_pixel_extension"
|
30
30
|
nil
|
31
31
|
else
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "base64"
|
3
3
|
require "json"
|
4
|
+
require "shopify_cli/theme/extension/dev_server"
|
4
5
|
|
5
6
|
module Extension
|
6
7
|
module Models
|
@@ -64,16 +65,27 @@ module Extension
|
|
64
65
|
"Theme App Extension"
|
65
66
|
end
|
66
67
|
|
67
|
-
def choose_port?(
|
68
|
-
|
68
|
+
def choose_port?(_ctx)
|
69
|
+
false
|
69
70
|
end
|
70
71
|
|
71
|
-
def establish_tunnel?(
|
72
|
-
|
72
|
+
def establish_tunnel?(_ctx)
|
73
|
+
false
|
73
74
|
end
|
74
75
|
|
75
|
-
def serve(
|
76
|
-
ctx
|
76
|
+
def serve(**options)
|
77
|
+
@ctx = options[:context]
|
78
|
+
root = options[:context]&.root
|
79
|
+
project = options[:project]
|
80
|
+
properties = options
|
81
|
+
.slice(:port, :theme)
|
82
|
+
.compact
|
83
|
+
.merge({
|
84
|
+
project: project,
|
85
|
+
specification_handler: self,
|
86
|
+
})
|
87
|
+
|
88
|
+
ShopifyCLI::Theme::Extension::DevServer.start(@ctx, root, **properties)
|
77
89
|
end
|
78
90
|
|
79
91
|
private
|
@@ -1,6 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "shopify_cli/theme/dev_server"
|
3
3
|
require "project_types/theme/commands/common/root_helper"
|
4
|
+
require "shopify_cli/theme/ignore_filter"
|
5
|
+
require "shopify_cli/theme/include_filter"
|
6
|
+
require "project_types/theme/conversions/include_glob"
|
7
|
+
require "project_types/theme/conversions/ignore_glob"
|
4
8
|
|
5
9
|
module Theme
|
6
10
|
class Command
|
@@ -12,6 +16,9 @@ module Theme
|
|
12
16
|
DEFAULT_HTTP_HOST = "127.0.0.1"
|
13
17
|
|
14
18
|
options do |parser, flags|
|
19
|
+
Conversions::IncludeGlob.register(parser)
|
20
|
+
Conversions::IgnoreGlob.register(parser)
|
21
|
+
|
15
22
|
parser.on("--host=HOST") { |host| flags[:host] = host.to_s }
|
16
23
|
parser.on("--port=PORT") { |port| flags[:port] = port.to_i }
|
17
24
|
parser.on("--poll") { flags[:poll] = true }
|
@@ -19,6 +26,14 @@ module Theme
|
|
19
26
|
parser.on("--theme-editor-sync") { flags[:editor_sync] = true }
|
20
27
|
parser.on("--stable") { flags[:stable] = true }
|
21
28
|
parser.on("-t", "--theme=NAME_OR_ID") { |theme| flags[:theme] = theme }
|
29
|
+
parser.on("-o", "--only=PATTERN", Conversions::IncludeGlob) do |pattern|
|
30
|
+
flags[:includes] ||= []
|
31
|
+
flags[:includes] |= pattern
|
32
|
+
end
|
33
|
+
parser.on("-x", "--ignore=PATTERN", Conversions::IgnoreGlob) do |pattern|
|
34
|
+
flags[:ignores] ||= []
|
35
|
+
flags[:ignores] |= pattern
|
36
|
+
end
|
22
37
|
end
|
23
38
|
|
24
39
|
def call(_args, name)
|
@@ -31,9 +46,6 @@ module Theme
|
|
31
46
|
ShopifyCLI::Theme::DevServer.start(@ctx, root, host: host, **flags) do |syncer|
|
32
47
|
UI::SyncProgressBar.new(syncer).progress(:upload_theme!, delay_low_priority_files: true)
|
33
48
|
end
|
34
|
-
rescue ShopifyCLI::Theme::DevServer::AddressBindingError
|
35
|
-
raise ShopifyCLI::Abort,
|
36
|
-
ShopifyCLI::Context.message("theme.serve.error.address_binding_error", ShopifyCLI::TOOL_NAME)
|
37
49
|
end
|
38
50
|
|
39
51
|
def self.as_reload_mode(mode)
|
@@ -138,6 +138,8 @@ module Theme
|
|
138
138
|
viewing_theme: "Viewing theme…",
|
139
139
|
syncing_theme: "Syncing theme #%s on %s",
|
140
140
|
open_fail: "Couldn't open the theme",
|
141
|
+
stop_signal: "Stop signal: \"%s\"",
|
142
|
+
stopping: "Stopping…",
|
141
143
|
auth: {
|
142
144
|
error_message: <<~ERROR_MESSAGE,
|
143
145
|
It looks like you are using credentials that do not work with {{command:%s theme serve}}.
|
@@ -230,8 +232,6 @@ module Theme
|
|
230
232
|
},
|
231
233
|
},
|
232
234
|
error: {
|
233
|
-
address_binding_error: "Couldn't bind to localhost."\
|
234
|
-
" To serve your theme, set a different address with {{command:%s theme serve --host=<address>}}",
|
235
235
|
invalid_subdirectory: <<~MESSAGE,
|
236
236
|
The presence of %s in the directory structure isn't supported.
|
237
237
|
|
@@ -262,6 +262,8 @@ module Theme
|
|
262
262
|
ENSURE_USER
|
263
263
|
address_already_in_use: "The address \"%s\" is already in use.",
|
264
264
|
try_port_option: "Use the --port=PORT option to serve the theme in a different port.",
|
265
|
+
binding_error: "Couldn't bind to localhost." \
|
266
|
+
" To serve your theme, set a different address with {{command:%s theme serve --host=<address>}}",
|
265
267
|
},
|
266
268
|
check: {
|
267
269
|
help: <<~HELP,
|
@@ -1,11 +1,14 @@
|
|
1
1
|
require "shopify_cli"
|
2
2
|
require "shopify_cli/theme/development_theme"
|
3
|
+
require "shopify_cli/theme/extension/host_theme"
|
3
4
|
|
4
5
|
module ShopifyCLI
|
5
6
|
module Commands
|
6
7
|
class Logout < ShopifyCLI::Command
|
7
8
|
def call(*)
|
8
9
|
try_delete_development_theme
|
10
|
+
try_delete_host_theme
|
11
|
+
|
9
12
|
ShopifyCLI::IdentityAuth.delete_tokens_and_keys
|
10
13
|
ShopifyCLI::DB.del(:shop) if has_shop?
|
11
14
|
ShopifyCLI::DB.del(:organization_id) if has_organization_id?
|
@@ -31,8 +34,16 @@ module ShopifyCLI
|
|
31
34
|
return unless has_shop?
|
32
35
|
|
33
36
|
ShopifyCLI::Theme::DevelopmentTheme.delete(@ctx)
|
34
|
-
rescue ShopifyCLI::API::APIRequestError, ShopifyCLI::Abort, ShopifyCLI::AbortSilent
|
35
|
-
|
37
|
+
rescue ShopifyCLI::API::APIRequestError, ShopifyCLI::Abort, ShopifyCLI::AbortSilent => e
|
38
|
+
@ctx.debug("[Logout Error]: #{e.message}")
|
39
|
+
end
|
40
|
+
|
41
|
+
def try_delete_host_theme
|
42
|
+
return unless has_shop?
|
43
|
+
|
44
|
+
ShopifyCLI::Theme::Extension::HostTheme.delete(@ctx)
|
45
|
+
rescue ShopifyCLI::API::APIRequestError, ShopifyCLI::Abort, ShopifyCLI::AbortSilent => e
|
46
|
+
@ctx.debug("[Logout Error]: #{e.message}")
|
36
47
|
end
|
37
48
|
end
|
38
49
|
end
|
@@ -159,7 +159,7 @@ module ShopifyCLI
|
|
159
159
|
env_variable_truthy?(
|
160
160
|
Constants::EnvironmentVariables::MONORAIL_REAL_EVENTS,
|
161
161
|
env_variables: env_variables
|
162
|
-
)
|
162
|
+
) && !run_as_subprocess?(env_variables: env_variables)
|
163
163
|
end
|
164
164
|
|
165
165
|
def self.auth_token(env_variables: ENV)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "listen"
|
3
|
+
require "observer"
|
4
|
+
|
5
|
+
module ShopifyCLI
|
6
|
+
class FileSystemListener
|
7
|
+
include Observable
|
8
|
+
|
9
|
+
def initialize(root:, force_poll:, ignore_regex:)
|
10
|
+
@root = root
|
11
|
+
@force_poll = force_poll
|
12
|
+
@ignore_regex = ignore_regex
|
13
|
+
|
14
|
+
@listener = Listen.to(@root, force_polling: @force_poll, ignore: @ignore_regex) do |updated, added, removed|
|
15
|
+
changed
|
16
|
+
notify_observers(updated, added, removed)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def start
|
21
|
+
@listener.start
|
22
|
+
rescue ArgumentError
|
23
|
+
# Ignore errors during the transition of 'listen' events
|
24
|
+
end
|
25
|
+
|
26
|
+
def stop
|
27
|
+
@listener.stop
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/shopify_cli/git.rb
CHANGED
@@ -46,12 +46,77 @@ module ShopifyCLI
|
|
46
46
|
end
|
47
47
|
|
48
48
|
##
|
49
|
-
#
|
50
|
-
# it will also output progress of the cloning process.
|
49
|
+
# returns array with components of git clone command
|
51
50
|
#
|
52
51
|
# #### Parameters
|
53
52
|
#
|
54
|
-
# * `
|
53
|
+
# * `repo` - repo url without branch name
|
54
|
+
# * `dest` - a filepath to where the repo should be cloned to
|
55
|
+
# * `branch` - branch name when cloning
|
56
|
+
#
|
57
|
+
# #### Returns
|
58
|
+
#
|
59
|
+
# * array of strings
|
60
|
+
#
|
61
|
+
# #### Example
|
62
|
+
#
|
63
|
+
# ["clone", "--single-branch", "--branch", "test-branch", "test-app"]
|
64
|
+
#
|
65
|
+
def git_clone_command(repo, dest, branch)
|
66
|
+
if branch
|
67
|
+
["clone", "--single-branch", "--branch", branch, repo, dest]
|
68
|
+
else
|
69
|
+
["clone", "--single-branch", repo, dest]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# calls git to clone a new repo into a supplied destination,
|
75
|
+
# it will also call a supplied block with the percentage of clone completion
|
76
|
+
#
|
77
|
+
# #### Parameters
|
78
|
+
#
|
79
|
+
# * `repo_with_branch` - a git url for git to clone the repo from
|
80
|
+
# * `dest` - a filepath to where the repo should be cloned to
|
81
|
+
# * `ctx` - the current running context of your command, defaults to a new context.
|
82
|
+
#
|
83
|
+
# #### Returns
|
84
|
+
#
|
85
|
+
# * `sha_string` - string of the sha of the most recent commit to the repo
|
86
|
+
#
|
87
|
+
# #### Example
|
88
|
+
#
|
89
|
+
# ShopifyCLI::Git.raw_clone('git@github.com:shopify/test.git', 'test-app')
|
90
|
+
#
|
91
|
+
def raw_clone(repo_with_branch, dest, ctx: Context.new)
|
92
|
+
if Dir.exist?(dest) && !Dir.empty?(dest)
|
93
|
+
ctx.abort(ctx.message("core.git.error.directory_exists"))
|
94
|
+
else
|
95
|
+
msg = []
|
96
|
+
# require at usage point to not slow down CLI startup
|
97
|
+
# https://github.com/Shopify/shopify-cli/pull/698#discussion_r444342445
|
98
|
+
require "open3"
|
99
|
+
|
100
|
+
repo, branch = repo_with_branch.split("#")
|
101
|
+
git_cmd = git_clone_command(repo, dest, branch)
|
102
|
+
|
103
|
+
success = Open3.popen3("git", *git_cmd, "--progress") do |_stdin, _stdout, stderr, thread|
|
104
|
+
msg = clone_progress(stderr, bar: nil)
|
105
|
+
|
106
|
+
thread.value
|
107
|
+
end.success?
|
108
|
+
|
109
|
+
ctx.abort((msg.join("\n"))) unless success
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# calls git to clone a new repo into a supplied destination,
|
115
|
+
# it will also output progress of the cloning process into a new progress bar
|
116
|
+
#
|
117
|
+
# #### Parameters
|
118
|
+
#
|
119
|
+
# * `repo_with_branch` - a git url for git to clone the repo from
|
55
120
|
# * `dest` - a filepath to where the repo should be cloned to
|
56
121
|
# * `ctx` - the current running context of your command, defaults to a new context.
|
57
122
|
#
|
@@ -63,17 +128,30 @@ module ShopifyCLI
|
|
63
128
|
#
|
64
129
|
# ShopifyCLI::Git.clone('git@github.com:shopify/test.git', 'test-app')
|
65
130
|
#
|
66
|
-
def clone(
|
67
|
-
if Dir.exist?(dest)
|
131
|
+
def clone(repo_with_branch, dest, ctx: Context.new)
|
132
|
+
if Dir.exist?(dest) && !Dir.empty?(dest)
|
68
133
|
ctx.abort(ctx.message("core.git.error.directory_exists"))
|
69
134
|
else
|
70
|
-
|
135
|
+
msg = []
|
136
|
+
# require at usage point to not slow down CLI startup
|
137
|
+
# https://github.com/Shopify/shopify-cli/pull/698#discussion_r444342445
|
138
|
+
require "open3"
|
139
|
+
|
140
|
+
repo, branch = repo_with_branch.split("#")
|
141
|
+
git_cmd = git_clone_command(repo, dest, branch)
|
142
|
+
|
71
143
|
success_message = ctx.message("core.git.cloned", dest)
|
144
|
+
|
72
145
|
CLI::UI::Frame.open(ctx.message("core.git.cloning", repo, dest), success_text: success_message) do
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
146
|
+
CLI::UI::Progress.progress do |bar|
|
147
|
+
success = Open3.popen3("git", *git_cmd, "--progress") do |_stdin, _stdout, stderr, thread|
|
148
|
+
msg = clone_progress(stderr, bar: bar)
|
149
|
+
|
150
|
+
thread.value
|
151
|
+
end.success?
|
152
|
+
|
153
|
+
ctx.abort((msg.join("\n"))) unless success
|
154
|
+
bar.tick(set_percent: 1.0)
|
77
155
|
end
|
78
156
|
end
|
79
157
|
end
|
@@ -197,6 +275,34 @@ module ShopifyCLI
|
|
197
275
|
end
|
198
276
|
end
|
199
277
|
|
278
|
+
##
|
279
|
+
# handles showing the progress of the git clone command.
|
280
|
+
# if block given, assumes passing percent to block, otherwise
|
281
|
+
# increments bar for progress bar
|
282
|
+
#
|
283
|
+
# #### Parameters
|
284
|
+
#
|
285
|
+
# * `stderr` - Open3.popen3 output stream
|
286
|
+
# * `bar` - progress bar object to set percent
|
287
|
+
#
|
288
|
+
def clone_progress(stderr, bar: nil)
|
289
|
+
msg = []
|
290
|
+
|
291
|
+
while (line = stderr.gets)
|
292
|
+
msg << line.chomp
|
293
|
+
next unless line.strip.start_with?("Receiving objects:")
|
294
|
+
percent = (line.match(/Receiving objects:\s+(\d+)/)[1].to_f / 100).round(2)
|
295
|
+
|
296
|
+
if block_given?
|
297
|
+
yield percent
|
298
|
+
elsif !bar.nil?
|
299
|
+
bar.tick(set_percent: percent)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
msg
|
304
|
+
end
|
305
|
+
|
200
306
|
private
|
201
307
|
|
202
308
|
def exec(*args, dir: Dir.pwd, default: nil, ctx: Context.new)
|
@@ -209,29 +315,6 @@ module ShopifyCLI
|
|
209
315
|
def rev_parse(*args, dir: nil, ctx: Context.new)
|
210
316
|
exec("rev-parse", *args, dir: dir, ctx: ctx)
|
211
317
|
end
|
212
|
-
|
213
|
-
def clone_progress(*git_command, ctx:)
|
214
|
-
CLI::UI::Progress.progress do |bar|
|
215
|
-
msg = []
|
216
|
-
require "open3"
|
217
|
-
|
218
|
-
success = Open3.popen3("git", *git_command, "--progress") do |_stdin, _stdout, stderr, thread|
|
219
|
-
while (line = stderr.gets)
|
220
|
-
msg << line.chomp
|
221
|
-
next unless line.strip.start_with?("Receiving objects:")
|
222
|
-
percent = (line.match(/Receiving objects:\s+(\d+)/)[1].to_f / 100).round(2)
|
223
|
-
bar.tick(set_percent: percent)
|
224
|
-
next
|
225
|
-
end
|
226
|
-
|
227
|
-
thread.value
|
228
|
-
end.success?
|
229
|
-
|
230
|
-
ctx.abort(msg.join("\n")) unless success
|
231
|
-
bar.tick(set_percent: 1.0)
|
232
|
-
success
|
233
|
-
end
|
234
|
-
end
|
235
318
|
end
|
236
319
|
end
|
237
320
|
end
|
@@ -87,6 +87,7 @@ module ShopifyCLI
|
|
87
87
|
|
88
88
|
def fetch_or_auth_partners_token
|
89
89
|
if EnvAuthToken.partners_token_present?
|
90
|
+
return Environment.auth_token if Environment.run_as_subprocess?
|
90
91
|
return EnvAuthToken.fetch_exchanged_partners_token do |env_token|
|
91
92
|
exchange_partners_auth_token(env_token)
|
92
93
|
end
|
data/lib/shopify_cli/project.rb
CHANGED
@@ -109,7 +109,7 @@ module ShopifyCLI
|
|
109
109
|
|
110
110
|
def at(dir)
|
111
111
|
proj_dir = directory(dir)
|
112
|
-
|
112
|
+
if !proj_dir && !ShopifyCLI::Environment.run_as_subprocess?
|
113
113
|
raise(ShopifyCLI::Abort, Context.message("core.project.error.not_in_project"))
|
114
114
|
end
|
115
115
|
@at ||= Hash.new { |h, k| h[k] = new(directory: k) }
|
@@ -4,7 +4,9 @@ module ShopifyCLI
|
|
4
4
|
module Tasks
|
5
5
|
class EnsureProjectType < ShopifyCLI::Task
|
6
6
|
def call(ctx, project_type)
|
7
|
-
|
7
|
+
if project_type.to_sym == ShopifyCLI::Project.current_project_type || Environment.run_as_subprocess?
|
8
|
+
return true
|
9
|
+
end
|
8
10
|
ctx.abort(ctx.message("core.tasks.ensure_project_type.wrong_project_type", project_type))
|
9
11
|
end
|
10
12
|
end
|