shopify-cli 2.8.0 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/Gemfile.lock +1 -1
  4. data/RELEASING.md +4 -3
  5. data/ext/javy/javy.rb +1 -1
  6. data/lib/project_types/extension/commands/push.rb +2 -2
  7. data/lib/project_types/extension/messages/messages.rb +1 -1
  8. data/lib/project_types/extension/models/development_server.rb +2 -4
  9. data/lib/project_types/rails/gem.rb +1 -2
  10. data/lib/project_types/script/cli.rb +5 -0
  11. data/lib/project_types/script/commands/connect.rb +1 -1
  12. data/lib/project_types/script/commands/create.rb +8 -2
  13. data/lib/project_types/script/commands/push.rb +35 -12
  14. data/lib/project_types/script/layers/application/connect_app.rb +11 -5
  15. data/lib/project_types/script/layers/application/extension_points.rb +50 -26
  16. data/lib/project_types/script/layers/application/push_script.rb +5 -2
  17. data/lib/project_types/script/layers/domain/extension_point.rb +14 -0
  18. data/lib/project_types/script/layers/infrastructure/errors.rb +2 -0
  19. data/lib/project_types/script/loaders/project.rb +44 -0
  20. data/lib/project_types/script/loaders/specification_handler.rb +22 -0
  21. data/lib/project_types/script/messages/messages.rb +15 -1
  22. data/lib/project_types/script/ui/error_handler.rb +5 -0
  23. data/lib/project_types/theme/commands/pull.rb +39 -16
  24. data/lib/project_types/theme/commands/push.rb +56 -26
  25. data/lib/project_types/theme/commands/serve.rb +5 -0
  26. data/lib/project_types/theme/messages/messages.rb +29 -18
  27. data/lib/shopify_cli/commands/login.rb +10 -4
  28. data/lib/shopify_cli/constants.rb +1 -0
  29. data/lib/shopify_cli/context.rb +66 -12
  30. data/lib/shopify_cli/environment.rb +15 -4
  31. data/lib/shopify_cli/identity_auth.rb +1 -0
  32. data/lib/shopify_cli/messages/messages.rb +3 -1
  33. data/lib/shopify_cli/resources/env_file.rb +5 -1
  34. data/lib/shopify_cli/theme/dev_server/hot-reload.js +19 -1
  35. data/lib/shopify_cli/theme/dev_server/hot_reload.rb +18 -2
  36. data/lib/shopify_cli/theme/dev_server/proxy.rb +1 -0
  37. data/lib/shopify_cli/theme/dev_server/reload_mode.rb +34 -0
  38. data/lib/shopify_cli/theme/dev_server.rb +6 -21
  39. data/lib/shopify_cli/theme/theme.rb +26 -4
  40. data/lib/shopify_cli/version.rb +1 -1
  41. data/lib/shopify_cli.rb +4 -0
  42. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 44313f65cde9217bac879066a57be593752c7d791d272d1ada078bc4a876f24c
4
- data.tar.gz: bcb6ac1b939ee13ccec83eb74814ceddb1cb2d11661f516327ca2f0d294795a3
3
+ metadata.gz: 3126bd5c9f4667732d248380f29b84fcac3bab1e3c944748b18dd3b0a639301d
4
+ data.tar.gz: 8c6ffbcf72d7360e227178f970c63a6041ee6c7f61b0ea22a9d6747f163f5b6b
5
5
  SHA512:
6
- metadata.gz: 77f0ea5bef5ce778e87c9414c4ec1712795ef144e603bf22f88975d5f86dab2f4d43052522f18302be1ac836b3b2b98cb2f66ea9d413d93214da365895d3a2b5
7
- data.tar.gz: 7cc5de0ba35117ae63a6cbb9e6d761695a75166cb15a996fd6545ba981e1809f60e9e42ad2d13e59a837310b11328b693744eb9547e90a0a8f537fd6640ba206
6
+ metadata.gz: 2a21a55b5b258fa6c5037fff6652c43ba09a207e7f2b313b52a950b7a1d221e41d7edf719ce66c089200c1f2fba577e412fb985420c872ee83a4d40ef0cd05be
7
+ data.tar.gz: 338348f5e2220ef8b307e619981cc16985f012ecafc09c2d2eb232c2639ca65a11df12249f0d64fea5839b9015e1e31f0617eae84b82b4e530df587969b5fcc8
data/CHANGELOG.md CHANGED
@@ -2,6 +2,24 @@ 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
+ ## 2.9.0
6
+
7
+ ### Fixed
8
+ * [#1922](https://github.com/Shopify/shopify-cli/pull/1922): Respect RUBY_BINDIR from Homebrew for installing gem
9
+ * [#1906](https://github.com/Shopify/shopify-cli/pull/1906): Fix Ngrok incompatibility with some Apple ARM environments
10
+ * [#1873](https://github.com/Shopify/shopify-cli/pull/1873): Fix partners ability to login to external shops.
11
+ * [#1909](https://github.com/Shopify/shopify-cli/pull/1909): Fix `theme serve` on Safari
12
+
13
+ ### Added
14
+ * [#1900](https://github.com/Shopify/shopify-cli/pull/1900): Add `-d`/`--development` flag to Shopify theme pull command
15
+ * [#1896](https://github.com/Shopify/shopify-cli/pull/1896): Release Typescript options for payment_methods and shipping_methods scripts
16
+ * [#1891](https://github.com/Shopify/shopify-cli/pull/1891): Allow for additional arguments in `shopify push script` on CI.
17
+ * [#1877](https://github.com/Shopify/shopify-cli/pull/1877): Add theme (`-t`/`--theme=NAME_OR_ID`) parameter to `theme push`/`theme pull` commands
18
+ * [#1871](https://github.com/Shopify/shopify-cli/pull/1871): Add a new `--live-reload` parameter to the `theme serve` command
19
+
20
+ ### Changed
21
+ - [#1929](https://github.com/Shopify/shopify-cli/pull/1929): Rename `--registration-id` to `--extension-id` in `shopify extension push`.
22
+
5
23
  ## Version 2.8.0
6
24
  ### Fixed
7
25
  * [#1879](https://github.com/Shopify/shopify-cli/pull/1879): Disambiguate -s as store option
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shopify-cli (2.8.0)
4
+ shopify-cli (2.9.0)
5
5
  bugsnag (~> 6.22)
6
6
  listen (~> 3.7.0)
7
7
  theme-check (~> 1.9.0)
data/RELEASING.md CHANGED
@@ -23,21 +23,22 @@
23
23
  ```
24
24
 
25
25
  9. Open a PR for the branch, get necessary approvals from code owners and merge into main branch. Note that the PR title will be the release note in Shipit, so make sure it mentions the release
26
- 10. Deploy using Shipit
26
+ 10. Deploy to RubyGems using [Shipit](https://shipit.shopify.io/shopify/shopify-cli/rubygems)
27
27
  11. Update your `main` branch to the latest version
28
28
  ```
29
29
  $ git checkout main
30
30
  $ git pull
31
31
  ```
32
32
 
33
- 12. On local machine and _AFTER_ gem has been published to https://rubygems.org, run
33
+ 12. On local machine and _AFTER_ gem has been published to https://rubygems.org/gems/shopify-cli, run
34
34
  ```
35
35
  $ rake package
36
36
  ```
37
37
  This will generate the `.deb`, `.rpm` and brew formula files, which will be located in `packaging/builds/X.Y.Z/`.
38
38
 
39
39
  13. Clone the `Shopify/homebrew-shopify` repository (if not already cloned), and then
40
- * create a branch named `release_X_Y_Z_of_shopify-cli`
40
+ * update your `master` branch to the latest version: `git checkout master && git pull`
41
+ * create a new branch: `git checkout -b release_X_Y_Z_of_shopify-cli`
41
42
  * update the brew formula in `shopify-cli.rb` with the generated formula in `packaging/builds/X.Y.Z/` in the `Shopify/shopify-cli` repo (from the `rake package` step above)
42
43
  * commit the change and create a PR on the [Shopify Homebrew repository](https://github.com/Shopify/homebrew-shopify)
43
44
  * when PR is approved, merge into main branch
data/ext/javy/javy.rb CHANGED
@@ -5,7 +5,7 @@ require "digest/sha2"
5
5
 
6
6
  module Javy
7
7
  ROOT = __dir__
8
- BIN_FOLDER = File.join(ROOT, "bin")
8
+ BIN_FOLDER = File.join(ShopifyCLI.cache_dir, "javy", "bin")
9
9
  HASH_FOLDER = File.join(ROOT, "hashes")
10
10
  VERSION = File.read(File.join(ROOT, "version")).strip
11
11
  TARGET = File.join(BIN_FOLDER, "javy-#{VERSION}")
@@ -9,7 +9,7 @@ module Extension
9
9
  options do |parser, flags|
10
10
  parser.on("--api-key=API_KEY") { |api_key| flags[:api_key] = api_key.gsub('"', "") }
11
11
  parser.on("--api-secret=API_SECRET") { |api_secret| flags[:api_secret] = api_secret.gsub('"', "") }
12
- parser.on("--registration-id=REGISTRATION_ID") do |registration_id|
12
+ parser.on("--extension-id=EXTENSION_ID") do |registration_id|
13
13
  flags[:registration_id] = registration_id.gsub('"', "")
14
14
  end
15
15
  end
@@ -35,7 +35,7 @@ module Extension
35
35
  end
36
36
 
37
37
  def register_if_necessary(project:, args:, name:)
38
- if @ctx.tty? && !project.registered?
38
+ if ShopifyCLI::Environment.interactive? && !project.registered?
39
39
  Command::Register.new(@ctx).call(args, name)
40
40
  end
41
41
  end
@@ -91,7 +91,7 @@ module Extension
91
91
  Usage: {{command:%s extension push}}
92
92
  Options:
93
93
  {{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).
94
- {{command:--registration-id=REGISTRATION_ID}} The id of the extension's registration.
94
+ {{command:--extension-id=EXTENSION_ID}} The id of the extension's registration.
95
95
  HELP
96
96
  frame_title: "Pushing your extension to Shopify",
97
97
  waiting_text: "Pushing code to Shopify…",
@@ -40,7 +40,7 @@ module Extension
40
40
 
41
41
  def serve(context, server_config)
42
42
  CLI::Kit::System.popen3(executable, "serve", "-") do |input, out, err, status|
43
- context.puts("Sending configuration data …")
43
+ context.debug("Sending configuration data to extension development server …")
44
44
  input << server_config.to_yaml
45
45
  input.close
46
46
 
@@ -57,17 +57,15 @@ module Extension
57
57
  private
58
58
 
59
59
  def forward_output_to_user(out, err, ctx)
60
- ctx.puts("Starting monitoring threads …")
60
+ ctx.debug("Starting message processing threads to relay output produced by the extension development server …")
61
61
 
62
62
  Thread.new do
63
- ctx.puts("Ready to process standard output")
64
63
  while (line = out.gets)
65
64
  ctx.puts(line)
66
65
  end
67
66
  end
68
67
 
69
68
  Thread.new do
70
- ctx.puts("Ready to process standard error")
71
69
  while (error = err.gets)
72
70
  ctx.puts(error)
73
71
  end
@@ -79,8 +79,7 @@ module Rails
79
79
  def install!
80
80
  spin = CLI::UI::SpinGroup.new
81
81
  spin.add(ctx.message("rails.gem.installing", name)) do |spinner|
82
- args = %w(gem install)
83
- args.push(name)
82
+ args = ["#{ENV["RUBY_BINDIR"]}gem", "install", name]
84
83
  unless version.nil?
85
84
  if ctx.windows? && version.include?("~")
86
85
  args.push("-v", "\"#{version}\"")
@@ -92,5 +92,10 @@ module Script
92
92
 
93
93
  autoload :Errors, Project.project_filepath("errors")
94
94
 
95
+ module Loaders
96
+ autoload :Project, Script::Project.project_filepath("loaders/project")
97
+ autoload :SpecificationHandler, Script::Project.project_filepath("loaders/specification_handler")
98
+ end
99
+
95
100
  class ScriptProjectError < StandardError; end
96
101
  end
@@ -6,7 +6,7 @@ module Script
6
6
  prerequisite_task ensure_project_type: :script
7
7
 
8
8
  def call(_args, _)
9
- Layers::Application::ConnectApp.call(ctx: @ctx, force: true, strict: true)
9
+ Layers::Application::ConnectApp.call(ctx: @ctx, force: true)
10
10
  rescue StandardError => e
11
11
  UI::ErrorHandler.pretty_print_and_raise(e, failed_op: @ctx.message("script.connect.error.operation_failed"))
12
12
  end
@@ -33,8 +33,14 @@ module Script
33
33
  end
34
34
 
35
35
  def self.help
36
- allowed_values = Script::Layers::Application::ExtensionPoints.available_types.map { |type| "{{cyan:#{type}}}" }
37
- ShopifyCLI::Context.message("script.create.help", ShopifyCLI::TOOL_NAME, allowed_values.join(", "))
36
+ allowed_apis = Layers::Application::ExtensionPoints.available_types.map { |type| "{{cyan:#{type}}}" }
37
+ allowed_languages = Layers::Application::ExtensionPoints.all_languages.map { |lang| "{{cyan:#{lang}}}" }
38
+ ShopifyCLI::Context.message(
39
+ "script.create.help",
40
+ ShopifyCLI::TOOL_NAME,
41
+ allowed_apis.join(", "),
42
+ allowed_languages.join(", ")
43
+ )
38
44
  end
39
45
  end
40
46
  end
@@ -7,25 +7,48 @@ module Script
7
7
 
8
8
  options do |parser, flags|
9
9
  parser.on("--force") { |t| flags[:force] = t }
10
+ parser.on("--api-key=API_KEY") { |api_key| flags[:api_key] = api_key.gsub('"', "") }
11
+ parser.on("--api-secret=API_SECRET") { |api_secret| flags[:api_secret] = api_secret.gsub('"', "") }
12
+ parser.on("--uuid=UUID") do |uuid|
13
+ flags[:uuid] = uuid.gsub('""', "")
14
+ end
10
15
  end
11
16
 
12
17
  def call(_args, _name)
13
- fresh_env = Layers::Application::ConnectApp.call(ctx: @ctx)
14
-
15
- force = options.flags.key?(:force) || !!fresh_env
18
+ connect_to_app
19
+ project = load_project
20
+ push(project: project)
21
+ rescue StandardError => e
22
+ UI::ErrorHandler.pretty_print_and_raise(e,
23
+ failed_op: @ctx.message("script.push.error.operation_failed_no_api_key"))
24
+ end
16
25
 
17
- api_key = Layers::Infrastructure::ScriptProjectRepository.new(ctx: @ctx).get.api_key
18
- return @ctx.puts(self.class.help) unless api_key
26
+ def push(project:)
27
+ force = options.flags.key?(:force)
28
+ api_key = project.env[:api_key]
29
+ uuid = project.env[:extra]["UUID"]
19
30
 
20
- Layers::Application::PushScript.call(ctx: @ctx, force: force)
21
- @ctx.puts(@ctx.message("script.push.script_pushed", api_key: api_key))
22
- rescue StandardError => e
23
- msg = if api_key
24
- @ctx.message("script.push.error.operation_failed_with_api_key", api_key: api_key)
31
+ if ShopifyCLI::Environment.interactive? || (uuid && !uuid.empty?)
32
+ Layers::Application::PushScript.call(ctx: @ctx, force: force, project: project)
33
+ @ctx.puts(@ctx.message("script.push.script_pushed", api_key: api_key))
25
34
  else
26
- @ctx.message("script.push.error.operation_failed_no_api_key")
35
+ raise ShopifyCLI::Abort, @ctx.message("script.push.error.operation_failed_no_uuid")
36
+ end
37
+ end
38
+
39
+ def load_project
40
+ Script::Loaders::Project.load(
41
+ directory: Dir.pwd,
42
+ api_key: options.flags[:api_key],
43
+ api_secret: options.flags[:api_secret],
44
+ uuid: options.flags[:uuid]
45
+ )
46
+ end
47
+
48
+ def connect_to_app
49
+ if ShopifyCLI::Environment.interactive?
50
+ Layers::Application::ConnectApp.call(ctx: @ctx)
27
51
  end
28
- UI::ErrorHandler.pretty_print_and_raise(e, failed_op: msg)
29
52
  end
30
53
 
31
54
  def self.help
@@ -7,7 +7,7 @@ module Script
7
7
  module Application
8
8
  class ConnectApp
9
9
  class << self
10
- def call(ctx:, force: false, strict: false)
10
+ def call(ctx:, force: false)
11
11
  script_project_repo = Layers::Infrastructure::ScriptProjectRepository.new(ctx: ctx)
12
12
  script_project = script_project_repo.get
13
13
 
@@ -40,10 +40,6 @@ module Script
40
40
 
41
41
  uuid = Forms::AskScriptUuid.ask(ctx, scripts, nil)&.uuid
42
42
 
43
- if strict && uuid.nil?
44
- ctx.abort(ctx.message("script.connect.missing_script"))
45
- end
46
-
47
43
  script_project_repo.create_env(
48
44
  api_key: app["apiKey"],
49
45
  secret: app["apiSecretKeys"].first["secret"],
@@ -52,6 +48,16 @@ module Script
52
48
  ctx.done(ctx.message("script.connect.connected", app["title"]))
53
49
 
54
50
  true
51
+ rescue SmartProperties::InitializationError, SmartProperties::InvalidValueError => error
52
+ handle_error(error, context: ctx)
53
+ end
54
+
55
+ def handle_error(error, context:)
56
+ properties_hash = { api_key: "SHOPIFY_API_KEY", secret: "SHOPIFY_API_SECRET" }
57
+ missing_env_variables = error.properties.map { |p| properties_hash[p.name] }.compact.join(", ")
58
+ raise ShopifyCLI::Abort,
59
+ context.message("script.connect.error.missing_env_file_variables", missing_env_variables,
60
+ ShopifyCLI::TOOL_NAME)
55
61
  end
56
62
 
57
63
  private
@@ -4,37 +4,61 @@ module Script
4
4
  module Layers
5
5
  module Application
6
6
  class ExtensionPoints
7
- def self.get(type:)
8
- Infrastructure::ExtensionPointRepository.new.get_extension_point(type)
9
- end
7
+ class << self
8
+ def get(type:)
9
+ extension_point_repository.get_extension_point(type)
10
+ end
10
11
 
11
- def self.types
12
- Infrastructure::ExtensionPointRepository.new.extension_point_types
13
- end
12
+ def types
13
+ extension_point_repository.extension_point_types
14
+ end
14
15
 
15
- def self.available_types
16
- Infrastructure::ExtensionPointRepository.new.extension_points.select do |ep|
17
- next false if ep.deprecated?
18
- !ep.beta? || ShopifyCLI::Feature.enabled?(:scripts_beta_extension_points)
19
- end.map(&:type)
20
- end
16
+ def available_types
17
+ available_extension_points.map(&:type)
18
+ end
21
19
 
22
- def self.deprecated_types
23
- Infrastructure::ExtensionPointRepository.new
24
- .extension_points
25
- .select(&:deprecated?)
26
- .map(&:type)
27
- end
20
+ def deprecated_types
21
+ extension_point_repository
22
+ .extension_points
23
+ .select(&:deprecated?)
24
+ .map(&:type)
25
+ end
28
26
 
29
- def self.languages(type:)
30
- get(type: type).libraries.all.map do |library|
31
- next nil if library.beta? && !ShopifyCLI::Feature.enabled?(:scripts_beta_languages)
32
- library.language
33
- end.compact
34
- end
27
+ def all_languages
28
+ available_extension_points
29
+ .map { |ep| ep.library_languages(include_betas: include_beta_languages?) }
30
+ .flatten
31
+ .uniq
32
+ end
33
+
34
+ def languages(type:)
35
+ get(type: type).library_languages(include_betas: include_beta_languages?)
36
+ end
37
+
38
+ def supported_language?(type:, language:)
39
+ languages(type: type).include?(language.downcase)
40
+ end
41
+
42
+ private
43
+
44
+ def available_extension_points
45
+ extension_point_repository.extension_points.select do |ep|
46
+ next false if ep.deprecated?
47
+ ep.stable? || include_beta_extension_points?
48
+ end
49
+ end
50
+
51
+ def extension_point_repository
52
+ Infrastructure::ExtensionPointRepository.new
53
+ end
54
+
55
+ def include_beta_languages?
56
+ ShopifyCLI::Feature.enabled?(:scripts_beta_languages)
57
+ end
35
58
 
36
- def self.supported_language?(type:, language:)
37
- languages(type: type).include?(language.downcase)
59
+ def include_beta_extension_points?
60
+ ShopifyCLI::Feature.enabled?(:scripts_beta_extension_points)
61
+ end
38
62
  end
39
63
  end
40
64
  end
@@ -5,9 +5,10 @@ module Script
5
5
  module Application
6
6
  class PushScript
7
7
  class << self
8
- def call(ctx:, force:)
8
+ def call(ctx:, force:, project:)
9
9
  script_project_repo = Infrastructure::ScriptProjectRepository.new(ctx: ctx)
10
10
  script_project = script_project_repo.get
11
+ script_project.env = project.env
11
12
  task_runner = Infrastructure::Languages::TaskRunner
12
13
  .for(ctx, script_project.language, script_project.script_name)
13
14
 
@@ -47,7 +48,9 @@ module Script
47
48
  module_upload_url: module_upload_url,
48
49
  library: package.library,
49
50
  )
50
- script_project_repo.update_env(uuid: uuid)
51
+ if ShopifyCLI::Environment.interactive?
52
+ script_project_repo.update_env(uuid: uuid)
53
+ end
51
54
  spinner.update_title(p_ctx.message("script.application.pushed"))
52
55
  end
53
56
  end
@@ -18,6 +18,10 @@ module Script
18
18
  @beta
19
19
  end
20
20
 
21
+ def stable?
22
+ !beta?
23
+ end
24
+
21
25
  def deprecated?
22
26
  @deprecated
23
27
  end
@@ -26,6 +30,12 @@ module Script
26
30
  @type.gsub("_", "-")
27
31
  end
28
32
 
33
+ def library_languages(include_betas: false)
34
+ @libraries.all.map do |library|
35
+ include_betas || library.stable? ? library.language : nil
36
+ end.compact
37
+ end
38
+
29
39
  class ExtensionPointLibraries
30
40
  def initialize(config)
31
41
  @config = config
@@ -57,6 +67,10 @@ module Script
57
67
  @beta
58
68
  end
59
69
 
70
+ def stable?
71
+ !beta?
72
+ end
73
+
60
74
  def versioned?
61
75
  @version
62
76
  end
@@ -39,6 +39,8 @@ module Script
39
39
  end
40
40
  end
41
41
 
42
+ class ScriptEnvAppNotConnectedError < ScriptProjectError; end
43
+
42
44
  class InvalidScriptConfigYmlDefinitionError < ScriptProjectError; end
43
45
 
44
46
  class InvalidScriptJsonDefinitionError < ScriptProjectError; end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Loaders
5
+ module Project
6
+ def self.load(directory:, api_key:, uuid:, api_secret:, context: ShopifyCLI::Context.new)
7
+ env_overrides = {
8
+ "SHOPIFY_API_KEY" => api_key,
9
+ "SHOPIFY_API_SECRET" => api_secret,
10
+ "UUID" => uuid,
11
+ }.compact
12
+ env_file_present = env_file_exists?(directory)
13
+ env = if env_file_present
14
+ ShopifyCLI::Resources::EnvFile.read(directory, overrides: env_overrides)
15
+ else
16
+ ShopifyCLI::Resources::EnvFile.from_hash(env_overrides)
17
+ end
18
+
19
+ project = ShopifyCLI::Project.at(directory)
20
+ project.env = env
21
+ project
22
+ rescue SmartProperties::InitializationError, SmartProperties::InvalidValueError => error
23
+ handle_error(error, context: context, env_file_present: env_file_present)
24
+ end
25
+
26
+ def self.handle_error(error, context:, env_file_present:)
27
+ if env_file_present
28
+ properties_hash = { api_key: "SHOPIFY_API_KEY", secret: "SHOPIFY_API_SECRET" }
29
+ missing_env_variables = error.properties.map { |p| properties_hash[p.name] }.compact.join(", ")
30
+ raise ShopifyCLI::Abort,
31
+ context.message("script.error.missing_env_file_variables", missing_env_variables, ShopifyCLI::TOOL_NAME)
32
+ else
33
+ properties_hash = { api_key: "--api-key", secret: "--api-secret" }
34
+ missing_options = error.properties.map { |p| properties_hash[p.name] }.compact.join(", ")
35
+ raise ShopifyCLI::Abort, context.message("script.error.missing_push_options", missing_options)
36
+ end
37
+ end
38
+
39
+ def self.env_file_exists?(directory)
40
+ File.exist?(ShopifyCLI::Resources::EnvFile.path(directory))
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Loaders
5
+ module SpecificationHandler
6
+ def self.load(project:, context:)
7
+ identifier = project.specification_identifier
8
+ Models::LazySpecificationHandler.new(identifier) do
9
+ specifications = Models::Specifications.new(
10
+ fetch_specifications: Tasks::FetchSpecifications.new(api_key: project.app.api_key, context: context)
11
+ )
12
+
13
+ unless specifications.valid?(identifier)
14
+ context.abort(context.message("errors.unknown_type", project.specification_identifier))
15
+ end
16
+
17
+ specifications[identifier]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -62,6 +62,9 @@ module Script
62
62
  no_script_config_yml_file_cause: "The script.config.yml file is missing.",
63
63
  no_script_config_yml_file_help: "Create this file and try again.",
64
64
 
65
+ app_not_connected_cause: "Script is not connected to an app.",
66
+ app_not_connected_help: "Run shopify connect or enter fields for api-key and api-secret.",
67
+
65
68
  configuration_syntax_error_cause: "The script.json is not formatted properly.",
66
69
  configuration_syntax_error_help: "Fix the errors and try again.",
67
70
 
@@ -145,6 +148,11 @@ module Script
145
148
  language_library_for_api_not_found_cause: "Script can’t be pushed because the %{language} library for API %{api} is missing.",
146
149
  language_library_for_api_not_found_help: "Make sure extension_point.yml contains the correct API library.",
147
150
  no_scripts_found_in_app: "The selected apps have no scripts. Please, create them first on the partners' dashboard.",
151
+ missing_env_file_variables: "The following variables are missing in the .env file: %s."\
152
+ " It might happen when the script hasn't been previously connected to an app."\
153
+ " To connect the script to an app, run {{command:%s script connect}}",
154
+ missing_push_options: "The following options are required: %s."\
155
+ " You can obtain them from the .env file generated after connecting the script to an app.",
148
156
  },
149
157
 
150
158
  create: {
@@ -154,6 +162,7 @@ module Script
154
162
  Options:
155
163
  {{command:--name=NAME}} Script project name. Use any string.
156
164
  {{command:--api=TYPE}} Script API name. Allowed values: %2$s.
165
+ {{command:--language=LANGUAGE}} Programming language. Allowed values: %3$s.
157
166
  HELP
158
167
 
159
168
  error: {
@@ -171,9 +180,13 @@ module Script
171
180
  Usage: {{command:%s script push}}
172
181
  Options:
173
182
  {{command:[--force]}} Replaces the existing script on the app with this version.
183
+ {{command:[--api-key=API_KEY]}} The API key used to register an app with the script. This can be found on the app page on Partners Dashboard. Overrides the value in the .env file, if present.
184
+ {{command:[--api-secret=API_SECRET]}} The API secret of the app the script is registered with. Overrides the value in the .env file, if present.
185
+ {{command:[--uuid=UUID]}} The uuid of the script. Overrides the value in the .env file, if present.
174
186
  HELP
175
187
 
176
188
  error: {
189
+ operation_failed_no_uuid: "UUID is required to push in a CI environment.",
177
190
  operation_failed_with_api_key: "Couldn't push script to app (API key: %{api_key}).",
178
191
  operation_failed_no_api_key: "Couldn't push script to app.",
179
192
  },
@@ -182,13 +195,14 @@ module Script
182
195
  },
183
196
  connect: {
184
197
  connected: "Connected! Your project is now connected to {{green:%s}}",
185
- missing_script: "No script has been selected.",
186
198
  help: <<~HELP,
187
199
  {{command:%s script connect}}: Connects an existing script to an app.
188
200
  Usage: {{command:%s script connect}}
189
201
  HELP
190
202
  error: {
191
203
  operation_failed: "Couldn't connect script to app.",
204
+ missing_env_file_variables: "The following variables are missing in the .env file: %s."\
205
+ " To connect the script to an app, either enter the value into the .env file or delete the .env file, then run {{command:%s script connect}}",
192
206
  },
193
207
  },
194
208
  javy: {
@@ -143,6 +143,11 @@ module Script
143
143
  cause_of_error: ShopifyCLI::Context.message("script.error.configuration_syntax_error_cause"),
144
144
  help_suggestion: ShopifyCLI::Context.message("script.error.configuration_syntax_error_help"),
145
145
  }
146
+ when Layers::Infrastructure::Errors::ScriptEnvAppNotConnectedError
147
+ {
148
+ cause_of_error: ShopifyCLI::Context.message("script.error.app_not_connected_cause"),
149
+ help_suggestion: ShopifyCLI::Context.message("script.error.app_not_connected_help"),
150
+ }
146
151
  when Layers::Infrastructure::Errors::ScriptConfigMissingKeysError
147
152
  {
148
153
  cause_of_error: ShopifyCLI::Context.message(