shopify-cli 2.3.0 → 2.4.0

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/workflows/shopify.yml +106 -0
  4. data/.gitignore +2 -0
  5. data/CHANGELOG.md +6 -0
  6. data/CONTRIBUTING.md +23 -0
  7. data/Dockerfile +19 -0
  8. data/Gemfile +1 -0
  9. data/Gemfile.lock +50 -13
  10. data/Rakefile +66 -0
  11. data/dev.yml +11 -1
  12. data/ext/shopify-extensions/extconf.rb +21 -0
  13. data/ext/shopify-extensions/shopify_extensions.rb +152 -0
  14. data/ext/shopify-extensions/version +1 -0
  15. data/lib/project_types/extension/cli.rb +14 -0
  16. data/lib/project_types/extension/commands/build.rb +30 -2
  17. data/lib/project_types/extension/commands/create.rb +25 -0
  18. data/lib/project_types/extension/forms/create.rb +4 -1
  19. data/lib/project_types/extension/forms/questions/ask_template.rb +44 -0
  20. data/lib/project_types/extension/messages/messages.rb +3 -0
  21. data/lib/project_types/extension/models/development_server.rb +35 -0
  22. data/lib/project_types/extension/models/development_server_requirements.rb +17 -0
  23. data/lib/project_types/extension/models/server_config/base.rb +31 -0
  24. data/lib/project_types/extension/models/server_config/development.rb +23 -0
  25. data/lib/project_types/extension/models/server_config/development_entries.rb +38 -0
  26. data/lib/project_types/extension/models/server_config/development_renderer.rb +30 -0
  27. data/lib/project_types/extension/models/server_config/extension.rb +35 -0
  28. data/lib/project_types/extension/models/server_config/root.rb +18 -0
  29. data/lib/project_types/extension/models/server_config/user.rb +10 -0
  30. data/lib/project_types/extension/tasks/choose_next_available_port.rb +1 -1
  31. data/lib/project_types/extension/tasks/run_extension_command.rb +58 -0
  32. data/lib/project_types/node/commands/create.rb +1 -5
  33. data/lib/project_types/rails/commands/create.rb +1 -5
  34. data/lib/project_types/script/cli.rb +2 -0
  35. data/lib/project_types/script/layers/application/push_script.rb +10 -1
  36. data/lib/project_types/script/layers/domain/push_package.rb +0 -12
  37. data/lib/project_types/script/layers/infrastructure/api_clients.rb +89 -0
  38. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +1 -1
  39. data/lib/project_types/script/layers/infrastructure/script_service.rb +26 -141
  40. data/lib/project_types/script/layers/infrastructure/script_uploader.rb +27 -0
  41. data/lib/project_types/script/tasks/ensure_env.rb +2 -2
  42. data/lib/project_types/script/ui/error_handler.rb +1 -1
  43. data/lib/shopify-cli/constants.rb +26 -0
  44. data/lib/shopify-cli/environment.rb +60 -0
  45. data/lib/shopify-cli/git.rb +2 -2
  46. data/lib/shopify-cli/identity_auth.rb +16 -23
  47. data/lib/shopify-cli/partners_api.rb +3 -27
  48. data/lib/shopify-cli/theme/dev_server/hot_reload.rb +4 -5
  49. data/lib/shopify-cli/theme/development_theme.rb +16 -2
  50. data/lib/shopify-cli/version.rb +1 -1
  51. data/lib/shopify_cli.rb +4 -2
  52. data/shopify-cli.gemspec +3 -3
  53. metadata +29 -9
  54. data/.github/workflows/build.yml +0 -28
@@ -9,18 +9,21 @@ module Script
9
9
  class ScriptService
10
10
  include SmartProperties
11
11
  property! :ctx, accepts: ShopifyCli::Context
12
+ property! :api_key, accepts: String
12
13
 
13
- def push(
14
+ def initialize(*args, ctx:, api_key:, **kwargs)
15
+ super(*args, ctx: ctx, api_key: api_key, **kwargs)
16
+ @client = ApiClients.default_client(ctx, api_key)
17
+ end
18
+
19
+ def set_app_script(
14
20
  uuid:,
15
21
  extension_point_type:,
16
- script_content:,
17
- api_key: nil,
18
22
  force: false,
19
23
  metadata:,
20
- script_json:
24
+ script_json:,
25
+ module_upload_url:
21
26
  )
22
- url = UploadScript.new(ctx).call(api_key, script_content)
23
-
24
27
  query_name = "app_script_set"
25
28
  variables = {
26
29
  uuid: uuid,
@@ -33,9 +36,9 @@ module Script
33
36
  scriptJsonVersion: script_json.version,
34
37
  configurationUi: script_json.configuration_ui,
35
38
  configurationDefinition: script_json.configuration&.to_json,
36
- moduleUploadUrl: url,
39
+ moduleUploadUrl: module_upload_url,
37
40
  }
38
- resp_hash = MakeRequest.new(ctx).call(query_name: query_name, api_key: api_key, variables: variables)
41
+ resp_hash = make_request(query_name: query_name, variables: variables)
39
42
  user_errors = resp_hash["data"]["appScriptSet"]["userErrors"]
40
43
 
41
44
  return resp_hash["data"]["appScriptSet"]["appScript"]["uuid"] if user_errors.empty?
@@ -63,149 +66,31 @@ module Script
63
66
  end
64
67
  end
65
68
 
66
- def get_app_scripts(api_key:, extension_point_type:)
69
+ def get_app_scripts(extension_point_type:)
67
70
  query_name = "get_app_scripts"
68
71
  variables = { appKey: api_key, extensionPointName: extension_point_type.upcase }
69
- response = MakeRequest.new(ctx).call(
70
- query_name: query_name,
71
- api_key: api_key,
72
- variables: variables
73
- )
72
+ response = make_request(query_name: query_name, variables: variables)
74
73
  response["data"]["appScripts"]
75
74
  end
76
75
 
77
- class ScriptServiceAPI < ShopifyCli::API
78
- property(:api_key, accepts: String)
79
-
80
- LOCAL_INSTANCE_URL = "https://script-service.myshopify.io"
81
-
82
- def self.query(ctx, query_name, api_key: nil, variables: {})
83
- api_client(ctx, api_key).query(query_name, variables: variables)
84
- end
85
-
86
- def self.api_client(ctx, api_key)
87
- instance_url = spin_instance_url || LOCAL_INSTANCE_URL
88
- new(
89
- ctx: ctx,
90
- url: "#{instance_url}/graphql",
91
- token: "",
92
- api_key: api_key
93
- )
94
- end
95
-
96
- def self.spin_instance_url
97
- workspace = ENV["SPIN_WORKSPACE"]
98
- namespace = ENV["SPIN_NAMESPACE"]
99
- return if workspace.nil? || namespace.nil?
100
-
101
- "https://script-service.#{workspace}.#{namespace}.us.spin.dev"
102
- end
76
+ def generate_module_upload_url
77
+ query_name = "module_upload_url_generate"
78
+ variables = {}
79
+ response = make_request(query_name: query_name, variables: variables)
80
+ user_errors = response["data"]["moduleUploadUrlGenerate"]["userErrors"]
103
81
 
104
- def auth_headers(*)
105
- tokens = { "APP_KEY" => api_key }.compact.to_json
106
- { "X-Shopify-Authenticated-Tokens" => tokens }
107
- end
82
+ raise Errors::GraphqlError, user_errors if user_errors.any?
83
+ response["data"]["moduleUploadUrlGenerate"]["url"]
108
84
  end
109
- private_constant(:ScriptServiceAPI)
110
-
111
- class PartnersProxyAPI < ShopifyCli::PartnersAPI
112
- def query(query_name, variables: {})
113
- variables[:query] = load_query(query_name)
114
- super("script_service_proxy", variables: variables)
115
- end
116
- end
117
- private_constant(:PartnersProxyAPI)
118
-
119
- class MakeRequest
120
- attr_reader :ctx
121
85
 
122
- def initialize(ctx)
123
- @ctx = ctx
124
- end
86
+ private
125
87
 
126
- def self.bypass_partners_proxy
127
- !ENV["BYPASS_PARTNERS_PROXY"].nil?
128
- end
88
+ def make_request(query_name:, variables: {})
89
+ response = @client.query(query_name, variables: variables)
90
+ raise Errors::EmptyResponseError if response.nil?
91
+ raise Errors::GraphqlError, response["errors"] if response.key?("errors")
129
92
 
130
- def call(query_name:, variables: nil, **options)
131
- resp = if MakeRequest.bypass_partners_proxy
132
- ScriptServiceAPI.query(ctx, query_name, variables: variables, **options)
133
- else
134
- proxy_through_partners(query_name: query_name, variables: variables, **options)
135
- end
136
- raise_if_graphql_failed(resp)
137
- resp
138
- end
139
-
140
- def proxy_through_partners(query_name:, variables: nil, **options)
141
- options[:variables] = variables.to_json if variables
142
- resp = PartnersProxyAPI.query(ctx, query_name, **options)
143
- raise_if_graphql_failed(resp)
144
- JSON.parse(resp["data"]["scriptServiceProxy"])
145
- end
146
-
147
- def raise_if_graphql_failed(response)
148
- raise Errors::EmptyResponseError if response.nil?
149
-
150
- return unless response.key?("errors")
151
- case error_code(response["errors"])
152
- when "forbidden"
153
- raise Errors::ForbiddenError
154
- when "forbidden_on_shop"
155
- raise Errors::ShopAuthenticationError
156
- when "app_not_installed_on_shop"
157
- raise Errors::AppNotInstalledError
158
- else
159
- raise Errors::GraphqlError, response["errors"]
160
- end
161
- end
162
-
163
- def error_code(errors)
164
- errors.map do |e|
165
- code = e.dig("extensions", "code")
166
- return code if code
167
- end
168
- end
169
- end
170
-
171
- class UploadScript
172
- attr_reader :ctx
173
-
174
- def initialize(ctx)
175
- @ctx = ctx
176
- end
177
-
178
- def call(api_key, script_content)
179
- apply_module_upload_url(api_key).tap do |url|
180
- upload(url, script_content)
181
- end
182
- end
183
-
184
- private
185
-
186
- def apply_module_upload_url(api_key)
187
- query_name = "module_upload_url_generate"
188
- variables = {}
189
- resp_hash = MakeRequest.new(ctx).call(query_name: query_name, api_key: api_key, variables: variables)
190
- user_errors = resp_hash["data"]["moduleUploadUrlGenerate"]["userErrors"]
191
-
192
- raise Errors::GraphqlError, user_errors if user_errors.any?
193
- resp_hash["data"]["moduleUploadUrlGenerate"]["url"]
194
- end
195
-
196
- def upload(url, script_content)
197
- url = URI(url)
198
-
199
- https = Net::HTTP.new(url.host, url.port)
200
- https.use_ssl = true
201
-
202
- request = Net::HTTP::Put.new(url)
203
- request["Content-Type"] = "application/wasm"
204
- request.body = script_content
205
-
206
- response = https.request(request)
207
- raise Errors::ScriptUploadError unless response.code == "200"
208
- end
93
+ response
209
94
  end
210
95
  end
211
96
  end
@@ -0,0 +1,27 @@
1
+ module Script
2
+ module Layers
3
+ module Infrastructure
4
+ class ScriptUploader
5
+ def initialize(script_service)
6
+ @script_service = script_service
7
+ end
8
+
9
+ def upload(script_content)
10
+ @script_service.generate_module_upload_url.tap do |url|
11
+ url = URI(url)
12
+
13
+ https = Net::HTTP.new(url.host, url.port)
14
+ https.use_ssl = true
15
+
16
+ request = Net::HTTP::Put.new(url)
17
+ request["Content-Type"] = "application/wasm"
18
+ request.body = script_content
19
+
20
+ response = https.request(request)
21
+ raise Errors::ScriptUploadError unless response.code == "200"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -89,8 +89,8 @@ module Script
89
89
  end
90
90
 
91
91
  def ask_script_uuid(app, extension_point_type)
92
- script_service = Layers::Infrastructure::ScriptService.new(ctx: ctx)
93
- scripts = script_service.get_app_scripts(api_key: app["apiKey"], extension_point_type: extension_point_type)
92
+ script_service = Layers::Infrastructure::ScriptService.new(ctx: ctx, api_key: app["apiKey"])
93
+ scripts = script_service.get_app_scripts(extension_point_type: extension_point_type)
94
94
 
95
95
  return nil unless scripts.count > 0 &&
96
96
  CLI::UI::Prompt.confirm(ctx.message("script.application.ensure_env.ask_connect_to_existing_script"))
@@ -99,7 +99,7 @@ module Script
99
99
  cause_of_error: ShopifyCli::Context.message("script.error.invalid_extension_cause", e.type),
100
100
  help_suggestion: ShopifyCli::Context.message(
101
101
  "script.error.invalid_extension_help",
102
- Script::Layers::Application::ExtensionPoints.types.join(", ")
102
+ Script::Layers::Application::ExtensionPoints.available_types.join(", ")
103
103
  ),
104
104
  }
105
105
  when Layers::Domain::Errors::ScriptNotFoundError
@@ -0,0 +1,26 @@
1
+ module ShopifyCli
2
+ module Constants
3
+ module EnvironmentVariables
4
+ # When true the CLI points to a local instance of
5
+ # the partners dashboard and identity.
6
+ LOCAL_PARTNERS = "SHOPIFY_APP_CLI_LOCAL_PARTNERS"
7
+
8
+ # When true the CLI points to a spin instance of spin
9
+ SPIN_PARTNERS = "SHOPIFY_APP_CLI_SPIN_PARTNERS"
10
+
11
+ SPIN_WORKSPACE = "SPIN_WORKSPACE"
12
+
13
+ SPIN_NAMESPACE = "SPIN_NAMESPACE"
14
+
15
+ SPIN_HOST = "SPIN_HOST"
16
+
17
+ # Set to true when running tests.
18
+ RUNNING_TESTS = "RUNNING_SHOPIFY_CLI_TESTS"
19
+ end
20
+
21
+ module Identity
22
+ CLIENT_ID_DEV = "e5380e02-312a-7408-5718-e07017e9cf52"
23
+ CLIENT_ID = "fbdb2649-e327-4907-8f67-908d24cfd7e3"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,60 @@
1
+ module ShopifyCli
2
+ # The environment module provides an interface to get information from
3
+ # the environment in which the CLI runs
4
+ module Environment
5
+ TRUTHY_ENV_VARIABLE_VALUES = ["1", "true", "TRUE", "yes", "YES"]
6
+ def self.use_local_partners_instance?(env_variables: ENV)
7
+ env_variable_truthy?(
8
+ Constants::EnvironmentVariables::LOCAL_PARTNERS,
9
+ env_variables: env_variables
10
+ )
11
+ end
12
+
13
+ def self.use_spin_partners_instance?(env_variables: ENV)
14
+ env_variable_truthy?(
15
+ Constants::EnvironmentVariables::SPIN_PARTNERS,
16
+ env_variables: env_variables
17
+ )
18
+ end
19
+
20
+ def self.running_tests?(env_variables: ENV)
21
+ env_variable_truthy?(
22
+ Constants::EnvironmentVariables::RUNNING_TESTS,
23
+ env_variables: env_variables
24
+ )
25
+ end
26
+
27
+ def self.partners_domain(env_variables: ENV)
28
+ if use_local_partners_instance?(env_variables: env_variables)
29
+ "partners.myshopify.io"
30
+ elsif use_spin_partners_instance?(env_variables: env_variables)
31
+ "partners.#{spin_url(env_variables: env_variables)}"
32
+ else
33
+ "partners.shopify.com"
34
+ end
35
+ end
36
+
37
+ def self.spin_url(env_variables: ENV)
38
+ spin_workspace = spin_workspace(env_variables: env_variables)
39
+ spin_namespace = spin_namespace(env_variables: env_variables)
40
+ spin_host = spin_host(env_variables: env_variables)
41
+ "#{spin_workspace}.#{spin_namespace}.#{spin_host}"
42
+ end
43
+
44
+ def self.env_variable_truthy?(variable_name, env_variables: ENV)
45
+ TRUTHY_ENV_VARIABLE_VALUES.include?(env_variables[variable_name.to_s])
46
+ end
47
+
48
+ def self.spin_workspace(env_variables: ENV)
49
+ env_variables[Constants::EnvironmentVariables::SPIN_WORKSPACE]
50
+ end
51
+
52
+ def self.spin_namespace(env_variables: ENV)
53
+ env_variables[Constants::EnvironmentVariables::SPIN_NAMESPACE]
54
+ end
55
+
56
+ def self.spin_host(env_variables: ENV)
57
+ env_variables[Constants::EnvironmentVariables::SPIN_HOST] || "us.spin.dev"
58
+ end
59
+ end
60
+ end
@@ -108,8 +108,8 @@ module ShopifyCli
108
108
  private
109
109
 
110
110
  def exec(*args, dir: Dir.pwd, default: nil, ctx: Context.new)
111
- args = %w(git) + args
112
- out, _, stat = ctx.capture3(*args, chdir: dir)
111
+ args = %w(git) + ["--git-dir", File.join(dir, ".git")] + args
112
+ out, _, stat = ctx.capture3(*args)
113
113
  return default unless stat.success?
114
114
  out.chomp
115
115
  end
@@ -17,7 +17,6 @@ module ShopifyCli
17
17
  class Error < StandardError; end
18
18
  class Timeout < StandardError; end
19
19
  LocalRequest = Struct.new(:method, :path, :query, :protocol)
20
- LOCAL_DEBUG = "SHOPIFY_APP_CLI_LOCAL_PARTNERS"
21
20
 
22
21
  DEFAULT_PORT = 3456
23
22
  REDIRECT_HOST = "http://127.0.0.1:#{DEFAULT_PORT}"
@@ -236,12 +235,17 @@ module ShopifyCli
236
235
  end
237
236
 
238
237
  def auth_url
239
- return "https://accounts.shopify.com/oauth" if ENV[LOCAL_DEBUG].nil?
240
- "https://identity.myshopify.io/oauth"
238
+ if Environment.use_local_partners_instance?
239
+ "https://identity.myshopify.io/oauth"
240
+ elsif Environment.use_spin_partners_instance?
241
+ "https://identity.#{Environment.spin_url}/oauth"
242
+ else
243
+ "https://accounts.shopify.com/oauth"
244
+ end
241
245
  end
242
246
 
243
247
  def client_id_for_application(application_name)
244
- client_ids = if ENV[LOCAL_DEBUG]
248
+ client_ids = if Environment.use_local_partners_instance? || Environment.use_spin_partners_instance?
245
249
  DEV_APPLICATION_CLIENT_IDS
246
250
  else
247
251
  APPLICATION_CLIENT_IDS
@@ -257,26 +261,15 @@ module ShopifyCli
257
261
  end
258
262
 
259
263
  def client_id
260
- return "fbdb2649-e327-4907-8f67-908d24cfd7e3" if ENV[LOCAL_DEBUG].nil?
261
-
262
- ctx.abort(ctx.message("core.identity_auth.error.local_identity_not_running")) unless local_identity_running?
263
-
264
- # Fetch the client ID from the local Identity Dynamic Registration endpoint
265
- response = post_request("/client", {
266
- name: "shopify-cli-development",
267
- public_type: "native",
268
- })
269
-
270
- response["client_id"]
271
- end
272
-
273
- def local_identity_running?
274
- Net::HTTP.start("identity.myshopify.io", 443, use_ssl: true, open_timeout: 1, read_timeout: 10) do |http|
275
- req = Net::HTTP::Get.new(URI.join("https://identity.myshopify.io", "/services/ping"))
276
- http.request(req).is_a?(Net::HTTPSuccess)
264
+ if Environment.use_local_partners_instance? || Environment.use_spin_partners_instance?
265
+ Constants::Identity::CLIENT_ID_DEV
266
+ else
267
+ # In the future we might want to use Identity's dynamic
268
+ # registration. To migrate to a dynamic client ID we
269
+ # need to refactor some code that relies on a static
270
+ # value for the client
271
+ Constants::Identity::CLIENT_ID
277
272
  end
278
- rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::EHOSTDOWN, Errno::EADDRNOTAVAIL, Errno::ECONNREFUSED
279
- false
280
273
  end
281
274
  end
282
275
  end
@@ -8,16 +8,6 @@ module ShopifyCli
8
8
  class PartnersAPI < API
9
9
  autoload :Organizations, "shopify-cli/partners_api/organizations"
10
10
 
11
- # Defines the environment variable that this API looks for to operate on local
12
- # services. If you set this environment variable in your shell then the partners
13
- # API will operate on your local instance
14
- #
15
- # #### Example
16
- #
17
- # SHOPIFY_APP_CLI_LOCAL_PARTNERS=1 shopify create
18
- #
19
- LOCAL_DEBUG = "SHOPIFY_APP_CLI_LOCAL_PARTNERS"
20
-
21
11
  class << self
22
12
  ##
23
13
  # issues a graphql query or mutation to the Shopify Partners Dashboard CLI Schema.
@@ -59,11 +49,11 @@ module ShopifyCli
59
49
  ctx.puts(ctx.message("core.partners_api.error.account_not_found", ShopifyCli::TOOL_NAME))
60
50
  end
61
51
 
62
- def partners_url_for(organization_id, api_client_id, local_debug)
52
+ def partners_url_for(organization_id, api_client_id)
63
53
  if ShopifyCli::Shopifolk.acting_as_shopify_organization?
64
54
  organization_id = "internal"
65
55
  end
66
- "#{partners_endpoint(local_debug)}/#{organization_id}/apps/#{api_client_id}"
56
+ "https://#{Environment.partners_domain}/#{organization_id}/apps/#{api_client_id}"
67
57
  end
68
58
 
69
59
  private
@@ -72,7 +62,7 @@ module ShopifyCli
72
62
  new(
73
63
  ctx: ctx,
74
64
  token: access_token(ctx),
75
- url: "#{endpoint}/api/cli/graphql",
65
+ url: "https://#{Environment.partners_domain}/api/cli/graphql",
76
66
  )
77
67
  end
78
68
 
@@ -83,20 +73,6 @@ module ShopifyCli
83
73
  end
84
74
  end
85
75
 
86
- def endpoint
87
- return "https://partners.shopify.com" if ENV[LOCAL_DEBUG].nil?
88
- "https://partners.myshopify.io/"
89
- end
90
-
91
- def partners_endpoint(local_debug)
92
- domain = if local_debug
93
- "partners.myshopify.io"
94
- else
95
- "partners.shopify.com"
96
- end
97
- "https://#{domain}"
98
- end
99
-
100
76
  def auth_failure_info(ctx, error)
101
77
  if error.response
102
78
  headers = %w(www-authenticate x-request-id)
@@ -34,11 +34,10 @@ module ShopifyCli
34
34
  files = (modified + added).reject { |file| @ignore_filter&.ignore?(file) }
35
35
  .map { |file| @theme[file].relative_path }
36
36
 
37
- @streams.broadcast(JSON.generate(
38
- modified: files,
39
- ))
40
-
41
- @ctx.debug("[HotReload] Modified #{files.join(", ")}")
37
+ unless files.empty?
38
+ @streams.broadcast(JSON.generate(modified: files))
39
+ @ctx.debug("[HotReload] Modified #{files.join(", ")}")
40
+ end
42
41
  end
43
42
 
44
43
  private
@@ -6,13 +6,24 @@ require "securerandom"
6
6
 
7
7
  module ShopifyCli
8
8
  module Theme
9
+ API_NAME_LIMIT = 50
10
+
9
11
  class DevelopmentTheme < Theme
10
12
  def id
11
13
  ShopifyCli::DB.get(:development_theme_id)
12
14
  end
13
15
 
14
16
  def name
15
- ShopifyCli::DB.get(:development_theme_name) || generate_theme_name
17
+ existing_name = ShopifyCli::DB.get(:development_theme_name)
18
+ # Up to version 2.3.0 (included) generated names stored locally
19
+ # could have more than 50 characters and the API rejected them.
20
+ # This code ensures we update the name for those users to ensure
21
+ # the name stays under the limit.
22
+ if existing_name.nil? || existing_name.length > API_NAME_LIMIT
23
+ generate_theme_name
24
+ else
25
+ existing_name
26
+ end
16
27
  end
17
28
 
18
29
  def role
@@ -58,7 +69,10 @@ module ShopifyCli
58
69
  hostname = Socket.gethostname.split(".").shift
59
70
  hash = SecureRandom.hex(3)
60
71
 
61
- theme_name = "Development (#{hash}-#{hostname})"
72
+ theme_name = "Development ()"
73
+ hostname_character_limit = API_NAME_LIMIT - theme_name.length - hash.length - 1
74
+ identifier = "#{hash}-#{hostname[0, hostname_character_limit]}"
75
+ theme_name = "Development (#{identifier})"
62
76
 
63
77
  ShopifyCli::DB.set(development_theme_name: theme_name)
64
78
 
@@ -1,3 +1,3 @@
1
1
  module ShopifyCli
2
- VERSION = "2.3.0"
2
+ VERSION = "2.4.0"
3
3
  end
data/lib/shopify_cli.rb CHANGED
@@ -94,6 +94,8 @@ module ShopifyCli
94
94
  )
95
95
  end
96
96
 
97
+ autoload :Constants, "shopify-cli/constants"
98
+ autoload :Environment, "shopify-cli/environment"
97
99
  autoload :AdminAPI, "shopify-cli/admin_api"
98
100
  autoload :API, "shopify-cli/api"
99
101
  autoload :Command, "shopify-cli/command"
@@ -132,7 +134,7 @@ module ShopifyCli
132
134
  Context.load_messages(ShopifyCli::Messages::MESSAGES)
133
135
 
134
136
  def self.cache_dir
135
- cache_dir = if ENV.key?("RUNNING_SHOPIFY_CLI_TESTS")
137
+ cache_dir = if Environment.running_tests?
136
138
  TEMP_DIR
137
139
  elsif ENV["LOCALAPPDATA"].nil?
138
140
  File.join(File.expand_path(ENV.fetch("XDG_CACHE_HOME", "~/.cache")), TOOL_NAME)
@@ -147,7 +149,7 @@ module ShopifyCli
147
149
  end
148
150
 
149
151
  def self.tool_config_path
150
- if ENV.key?("RUNNING_SHOPIFY_CLI_TESTS")
152
+ if Environment.running_tests?
151
153
  TEMP_DIR
152
154
  elsif ENV["APPDATA"].nil?
153
155
  File.join(File.expand_path(ENV.fetch("XDG_CONFIG_HOME", "~/.config")), TOOL_NAME)
data/shopify-cli.gemspec CHANGED
@@ -39,10 +39,10 @@ Gem::Specification.new do |spec|
39
39
  # `/usr/local/bin/shopify` to that script, in order to "lock" the Ruby used to
40
40
  # a single Ruby (useful for debugging in multi-Ruby environments)
41
41
 
42
- spec.add_development_dependency("bundler", "~> 2.1.4")
42
+ spec.add_development_dependency("bundler", "~> 2.2.2")
43
43
  spec.add_development_dependency("rake", "~> 12.3", ">= 12.3.3")
44
44
  spec.add_development_dependency("minitest", "~> 5.0")
45
45
 
46
- spec.add_dependency("listen", "~> 3.5")
47
- spec.add_dependency("theme-check", "~> 1.2")
46
+ spec.add_dependency("listen", "~> 3.7.0")
47
+ spec.add_dependency("theme-check", "~> 1.4.0")
48
48
  end