shopify-cli 1.1.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CONTRIBUTING.md +1 -1
  3. data/.gitignore +0 -1
  4. data/.rubocop.yml +6 -2
  5. data/.rubocop_todo.yml +20 -0
  6. data/CHANGELOG.md +24 -0
  7. data/Gemfile +1 -2
  8. data/Gemfile.lock +11 -11
  9. data/RELEASING.md +22 -10
  10. data/docs/core/index.md +16 -0
  11. data/lib/project_types/extension/cli.rb +6 -1
  12. data/lib/project_types/extension/commands/register.rb +1 -1
  13. data/lib/project_types/extension/features/argo/admin.rb +20 -0
  14. data/lib/project_types/extension/features/argo/base.rb +129 -0
  15. data/lib/project_types/extension/features/argo/checkout.rb +20 -0
  16. data/lib/project_types/extension/features/argo_config.rb +60 -0
  17. data/lib/project_types/extension/messages/messages.rb +11 -2
  18. data/lib/project_types/extension/models/type.rb +4 -0
  19. data/lib/project_types/extension/models/types/checkout_post_purchase.rb +6 -3
  20. data/lib/project_types/extension/models/types/product_subscription.rb +24 -0
  21. data/lib/project_types/node/commands/create.rb +6 -1
  22. data/lib/project_types/node/commands/serve.rb +5 -5
  23. data/lib/project_types/node/messages/messages.rb +4 -1
  24. data/lib/project_types/rails/commands/create.rb +10 -2
  25. data/lib/project_types/rails/commands/serve.rb +5 -5
  26. data/lib/project_types/rails/messages/messages.rb +5 -1
  27. data/lib/project_types/script/config/extension_points.yml +8 -8
  28. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +2 -2
  29. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +36 -1
  30. data/lib/project_types/script/layers/infrastructure/errors.rb +7 -0
  31. data/lib/project_types/script/messages/messages.rb +12 -37
  32. data/lib/project_types/script/ui/error_handler.rb +13 -5
  33. data/lib/shopify-cli/api.rb +5 -9
  34. data/lib/shopify-cli/commands/config.rb +33 -1
  35. data/lib/shopify-cli/commands/system.rb +9 -0
  36. data/lib/shopify-cli/context.rb +40 -0
  37. data/lib/shopify-cli/core/entry_point.rb +3 -0
  38. data/lib/shopify-cli/git.rb +1 -1
  39. data/lib/shopify-cli/http_request.rb +15 -0
  40. data/lib/shopify-cli/js_system.rb +22 -5
  41. data/lib/shopify-cli/messages/messages.rb +39 -11
  42. data/lib/shopify-cli/project.rb +3 -3
  43. data/lib/shopify-cli/shopifolk.rb +67 -0
  44. data/lib/shopify-cli/tunnel.rb +1 -1
  45. data/lib/shopify-cli/version.rb +1 -1
  46. data/lib/shopify_cli.rb +1 -0
  47. metadata +10 -4
  48. data/lib/project_types/extension/features/argo.rb +0 -48
  49. data/lib/project_types/extension/models/types/subscription_management.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8765adff2578420b0bbaaf7aa30e7e3f6b28b20363671f9e64a419f8b97fe647
4
- data.tar.gz: 17e00973e6c881c58c1e0ade838a98e93a17a39f7d960261a36f9cdc74a87940
3
+ metadata.gz: 5832060f2695566da5c38ce98ccd1c67d522e8bb8306a5b2a16d95f92b3e56f1
4
+ data.tar.gz: e223c587130318b500d5cd12b494c50aef424957aef5da797dafea4b233e9933
5
5
  SHA512:
6
- metadata.gz: '08b07fe290962b6ba6416214165dde7d9c78d01c7eade8662917ec530af18af1a773b08957c58be5b6c10c733bd4be8e2c40a24c2241153d575a158d3988bb84'
7
- data.tar.gz: 171f11dd5a4e740cb91345ed51e10485f9499e328bc6dec0ab3027c415b35fd312b616c451137639c224c07862d8651836074ef5bbb85563229ca93d85aa944a
6
+ metadata.gz: b85a1e420f5d8b80a46f93ca4d16ebc1198fd31899bc7fbb8c9e0fbfa485c5f38fe9eca820782b0c4743b53e10266ce73bb0010fa90cd5b08fff199bb6a99585
7
+ data.tar.gz: 0dfd783ede5fcad7b04d648ec0f4d7084bea778d1fe7c73c0d2a86e683181cce73e8706a53462b7e285c04095dcebcc0c7cc489587f35ceb34716be4ec71efa2
@@ -4,7 +4,7 @@ Shopify App CLI is an open source project. We want to make it as easy and transp
4
4
 
5
5
  ## Code of conduct
6
6
 
7
- We expect all participants to read our [code of conduct](https://github.com/Shopify/shopify-app-cli/.github/CODE_OF_CONDUCT.md) to understand which actions are and aren’t tolerated.
7
+ We expect all participants to read our [code of conduct](https://github.com/Shopify/shopify-app-cli/blob/master/.github/CODE_OF_CONDUCT.md) to understand which actions are and aren’t tolerated.
8
8
 
9
9
  ## Open development
10
10
 
data/.gitignore CHANGED
@@ -1,4 +1,3 @@
1
- .rubocop-*
2
1
  .tmp/*
3
2
  .bundle/*
4
3
  .DS_Store
@@ -1,5 +1,8 @@
1
- inherit_from:
2
- - https://shopify.github.io/ruby-style-guide/rubocop-cli.yml
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ inherit_gem:
4
+ rubocop-shopify:
5
+ - rubocop-cli.yml
3
6
 
4
7
  AllCops:
5
8
  Exclude:
@@ -45,3 +48,4 @@ Style/MethodCallWithArgsParentheses:
45
48
  - assert_equal
46
49
  - assert
47
50
  - refute
51
+ - assert_requested # from Webmock
@@ -0,0 +1,20 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2020-10-17 00:53:36 UTC using RuboCop version 0.93.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 66
10
+ # Cop supports --auto-correct.
11
+ # Configuration parameters: IgnoreMacros, IgnoredMethods, IgnoredPatterns, IncludedMacros, AllowParenthesesInMultilineCall, AllowParenthesesInChaining, AllowParenthesesInCamelCaseMethod, EnforcedStyle.
12
+ # SupportedStyles: require_parentheses, omit_parentheses
13
+ Style/MethodCallWithArgsParentheses:
14
+ Enabled: false
15
+
16
+ # Offense count: 1
17
+ # Cop supports --auto-correct.
18
+ Style/RedundantBegin:
19
+ Exclude:
20
+ - 'test/test_helper.rb'
@@ -1,3 +1,27 @@
1
+ Unreleased
2
+ ------
3
+
4
+ Version 1.4.0
5
+ ------
6
+ * Updates to tests, dependencies and internal tooling
7
+ * #924: Improve debugging messages on Partner API errors
8
+
9
+ Version 1.3.1
10
+ ------
11
+ * Allow any characters in ngrok account names
12
+
13
+ Version 1.3.0
14
+ ------
15
+ * Support for new `shopify config analytics` command to enable/disable anonymous usage reporting
16
+
17
+ Version 1.2.0
18
+ ------
19
+ * Improvements and new functionality to various internal components
20
+
21
+ Version 1.1.2
22
+ ------
23
+ * Fix various minor bugs (check dir before creating Rails project, catch stderr from failed git command)
24
+
1
25
  Version 1.1.1
2
26
  ------
3
27
  * Fix a bug where usernames with spaces caused issues on Windows
data/Gemfile CHANGED
@@ -8,11 +8,10 @@ group :development, :test do
8
8
  gem 'rake'
9
9
  gem 'pry-byebug'
10
10
  gem 'byebug'
11
- gem 'rubocop'
11
+ gem 'rubocop-shopify', require: false
12
12
  end
13
13
 
14
14
  group :test do
15
- gem 'session'
16
15
  gem 'mocha', require: false
17
16
  gem 'minitest', '>= 5.0.0', require: false
18
17
  gem 'minitest-reporters', require: false
@@ -23,7 +23,7 @@ GEM
23
23
  mocha (1.7.0)
24
24
  metaclass (~> 0.0.1)
25
25
  parallel (1.19.2)
26
- parser (2.7.1.4)
26
+ parser (2.7.2.0)
27
27
  ast (~> 2.4.1)
28
28
  pry (0.12.2)
29
29
  coderay (~> 1.1.0)
@@ -34,22 +34,23 @@ GEM
34
34
  public_suffix (3.0.3)
35
35
  rainbow (3.0.0)
36
36
  rake (13.0.1)
37
- regexp_parser (1.7.1)
37
+ regexp_parser (1.8.2)
38
38
  rexml (3.2.4)
39
- rubocop (0.89.1)
39
+ rubocop (0.93.1)
40
40
  parallel (~> 1.10)
41
- parser (>= 2.7.1.1)
41
+ parser (>= 2.7.1.5)
42
42
  rainbow (>= 2.2.2, < 4.0)
43
- regexp_parser (>= 1.7)
43
+ regexp_parser (>= 1.8)
44
44
  rexml
45
- rubocop-ast (>= 0.3.0, < 1.0)
45
+ rubocop-ast (>= 0.6.0)
46
46
  ruby-progressbar (~> 1.7)
47
47
  unicode-display_width (>= 1.4.0, < 2.0)
48
- rubocop-ast (0.3.0)
49
- parser (>= 2.7.1.4)
48
+ rubocop-ast (0.8.0)
49
+ parser (>= 2.7.1.5)
50
+ rubocop-shopify (1.0.6)
51
+ rubocop (>= 0.92, < 0.94)
50
52
  ruby-progressbar (1.10.1)
51
53
  safe_yaml (1.0.4)
52
- session (3.2.0)
53
54
  timecop (0.9.1)
54
55
  unicode-display_width (1.7.0)
55
56
  webmock (2.3.2)
@@ -68,8 +69,7 @@ DEPENDENCIES
68
69
  mocha
69
70
  pry-byebug
70
71
  rake
71
- rubocop
72
- session
72
+ rubocop-shopify
73
73
  timecop
74
74
  webmock
75
75
 
@@ -2,42 +2,54 @@
2
2
 
3
3
  1. Check the Semantic Versioning page for info on how to version the new release: http://semver.org
4
4
 
5
- 2. Create a branch named `release_X_Y_Z` (replacing `X_Y_Z` with the intended release version)
5
+ 1. Make sure you're on the most recent `master`
6
+ ```
7
+ $ git checkout master
8
+ $ git pull
9
+ ```
10
+
11
+ 1. Create a branch named `release_X_Y_Z` (replacing `X_Y_Z` with the intended release version)
6
12
  ```
7
13
  $ git checkout -b release_X_Y_Z
8
14
  ```
9
15
 
10
- 3. Update the version of Shopify CLI in `lib/shopify-cli/version.rb`
16
+ 1. Update the version of Shopify CLI in `lib/shopify-cli/version.rb`
11
17
 
12
- 4. Add an entry for the new release to `CHANGELOG.md`
18
+ 1. Add an entry for the new release to `CHANGELOG.md`
13
19
 
14
- 5. Commit the changes with a commit message like "Packaging for release X.Y.Z"
20
+ 1. Commit the changes with a commit message like "Packaging for release X.Y.Z"
15
21
  ```
16
22
  $ git commit -am "Packaging for release vX.Y.Z"
17
23
  ```
18
24
 
19
- 6. Push out the changes
25
+ 1. Push out the changes
20
26
  ```
21
27
  $ git push -u origin release_X_Y_Z
22
28
  ```
23
29
 
24
- 7. 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
30
+ 1. 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
25
31
 
26
- 8. Deploy using Shipit
32
+ 1. Deploy using Shipit
33
+
34
+ 1. Update your `master` branch to the latest version
35
+ ```
36
+ $ git checkout master
37
+ $ git pull
38
+ ```
27
39
 
28
- 9. On local machine and _AFTER_ gem has been published to https://rubygems.org, run
40
+ 1. On local machine and _AFTER_ gem has been published to https://rubygems.org, run
29
41
  ```
30
42
  $ rake package
31
43
  ```
32
44
  This will generate the `.deb`, `.rpm` and brew formula files, which will be located in `packaging/builds/X.Y.Z/`.
33
45
 
34
- 10. Clone the `Shopify/homebrew-shopify` repository (if not already cloned), and then
46
+ 1. Clone the `Shopify/homebrew-shopify` repository (if not already cloned), and then
35
47
  * create a branch named `release_X_Y_Z_of_shopify-cli`
36
48
  * update the brew formula in `shopify-cli.rb` with the generated formula in `packaging/builds/X.Y.Z/` in the `Shopify/shopify-app-cli` repo (from step 9)
37
49
  * commit the change and create a PR on the [Shopify Homebrew repository](https://github.com/Shopify/homebrew-shopify)
38
50
  * when PR is approved, merge into main branch
39
51
 
40
- 11. Go to [releases](https://github.com/Shopify/shopify-app-cli/releases) page of `Shopify/shopify-app-cli` repo and create a new release:
52
+ 1. Go to [releases](https://github.com/Shopify/shopify-app-cli/releases) page of `Shopify/shopify-app-cli` repo and create a new release:
41
53
  * use the tag created in step 8 by Shipit (should be "vX.Y.Z")
42
54
  * release title = "Version X.Y.Z"
43
55
  * description should be
@@ -68,3 +68,19 @@ Log out of the currently authenticated partner organization and store. The `logo
68
68
  $ shopify logout
69
69
  ```
70
70
 
71
+ ## `config`
72
+
73
+ Configure Shopify App CLI options. Currently there are two available options.
74
+
75
+ ### `analytics`
76
+
77
+ Configure anonymous usage reporting by enabling or disabling analytics
78
+ ```console
79
+ $ shopify config analytics [ --status | --enable | --disable ]
80
+ ```
81
+
82
+ ### `feature`
83
+ Configure active [feature sets](https://github.com/Shopify/shopify-app-cli/wiki/Feature-Sets) in the CLI. This command is used for development and debugging work on the CLI tool itself. Only alter it if you know what you're doing. Check the [Shopify App CLI development guide](https://github.com/Shopify/shopify-app-cli/wiki) for more information.
84
+ ```console
85
+ $ shopify config feature [ feature_name ] [ --status | --enable | --disable ]
86
+ ```
@@ -48,11 +48,16 @@ module Extension
48
48
  end
49
49
 
50
50
  module Features
51
- autoload :Argo, Project.project_filepath('features/argo')
52
51
  autoload :ArgoSetup, Project.project_filepath('features/argo_setup')
53
52
  autoload :ArgoSetupStep, Project.project_filepath('features/argo_setup_step')
54
53
  autoload :ArgoSetupSteps, Project.project_filepath('features/argo_setup_steps')
55
54
  autoload :ArgoDependencies, Project.project_filepath('features/argo_dependencies')
55
+ autoload :ArgoConfig, Project.project_filepath('features/argo_config')
56
+ module Argo
57
+ autoload :Base, Project.project_filepath('features/argo/base')
58
+ autoload :Admin, Project.project_filepath('features/argo/admin')
59
+ autoload :Checkout, Project.project_filepath('features/argo/checkout')
60
+ end
56
61
  end
57
62
 
58
63
  module Models
@@ -52,7 +52,7 @@ module Extension
52
52
  Tasks::CreateExtension.call(
53
53
  context: @ctx,
54
54
  api_key: app.api_key,
55
- type: extension_type.identifier,
55
+ type: extension_type.graphql_identifier,
56
56
  title: project.title,
57
57
  config: {},
58
58
  extension_context: extension_type.extension_context(@ctx)
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ module Extension
3
+ module Features
4
+ module Argo
5
+ class Admin < Base
6
+ GIT_TEMPLATE = 'https://github.com/Shopify/argo-admin-template.git'
7
+ RENDERER_PACKAGE = '@shopify/argo-admin'
8
+ private_constant :GIT_TEMPLATE, :RENDERER_PACKAGE
9
+
10
+ def git_template
11
+ GIT_TEMPLATE
12
+ end
13
+
14
+ def renderer_package_name
15
+ RENDERER_PACKAGE
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+ require 'base64'
3
+ require 'shopify_cli'
4
+ require 'semantic/semantic'
5
+
6
+ module Extension
7
+ module Features
8
+ module Argo
9
+ class Base
10
+ include SmartProperties
11
+
12
+ SCRIPT_PATH = %w(build main.js).freeze
13
+
14
+ NPM_LIST_COMMAND = %w(list).freeze
15
+ YARN_LIST_COMMAND = %w(list --pattern).freeze
16
+ NPM_LIST_PARAMETERS = %w(--prod).freeze
17
+ YARN_LIST_PARAMETERS = %w(--production).freeze
18
+ private_constant :NPM_LIST_COMMAND, :YARN_LIST_COMMAND, :NPM_LIST_PARAMETERS, :YARN_LIST_PARAMETERS
19
+
20
+ YARN_INSTALL_COMMAND = %w(install).freeze
21
+ YARN_INSTALL_PARAMETERS = %w(--silent).freeze
22
+ YARN_RUN_COMMAND = %w(run).freeze
23
+ YARN_RUN_SCRIPT_NAME = %w(build).freeze
24
+ private_constant :YARN_INSTALL_COMMAND, :YARN_INSTALL_PARAMETERS, :YARN_RUN_COMMAND, :YARN_RUN_SCRIPT_NAME
25
+
26
+ def create(directory_name, identifier, context)
27
+ Features::ArgoSetup.new(git_template: git_template).call(directory_name, identifier, context)
28
+ end
29
+
30
+ def config(context)
31
+ js_system = ShopifyCli::JsSystem.new(ctx: context)
32
+ if js_system.package_manager == 'yarn'
33
+ run_yarn_install(context, js_system)
34
+ run_yarn_run_script(context, js_system)
35
+ end
36
+ filepath = File.join(context.root, SCRIPT_PATH)
37
+ context.abort(context.message('features.argo.missing_file_error')) unless File.exist?(filepath)
38
+ begin
39
+ {
40
+ renderer_version: extract_argo_renderer_version(context),
41
+ serialized_script: Base64.strict_encode64(File.read(filepath).chomp),
42
+ }
43
+ rescue StandardError
44
+ context.abort(context.message('features.argo.script_prepare_error'))
45
+ end
46
+ end
47
+
48
+ def git_template
49
+ raise NotImplementedError, "'#{__method__}' must be implemented for #{self.class}"
50
+ end
51
+
52
+ def renderer_package_name
53
+ # The renderer_package_name is used as a regex pattern to
54
+ # find a match in the output of yarn or npm list command.
55
+ # Use the full package name as it appears in the template without targeting a version.
56
+ # Examples: "@shopify/some-renderer-package", "argo-renderer-package"
57
+
58
+ raise NotImplementedError, "'#{__method__}' must be implemented for #{self.class}"
59
+ end
60
+
61
+ private
62
+
63
+ def extract_argo_renderer_version(context)
64
+ result = run_list_command(context)
65
+ found_version = find_version_number(context, result)
66
+ context.abort(
67
+ context.message('features.argo.dependencies.argo_renderer_package_invalid_version_error')
68
+ ) if found_version.nil?
69
+ ::Semantic::Version.new(found_version).to_s
70
+ rescue ArgumentError
71
+ context.abort(
72
+ context.message('features.argo.dependencies.argo_renderer_package_invalid_version_error')
73
+ )
74
+ end
75
+
76
+ def find_version_number(context, result)
77
+ packages = result.to_json.split('\n')
78
+ found_package = packages.find do |package|
79
+ package.match(/#{renderer_package_name}@/)
80
+ end
81
+ if found_package.nil?
82
+ error = "'#{renderer_package_name}' not found."
83
+ context.abort(
84
+ context.message('features.argo.dependencies.argo_missing_renderer_package_error', error)
85
+ )
86
+ end
87
+ found_package.split('@')[2]&.strip
88
+ end
89
+
90
+ def run_list_command(context)
91
+ js_system = ShopifyCli::JsSystem.new(ctx: context)
92
+ result, error, status = js_system.call(
93
+ yarn: YARN_LIST_COMMAND + [renderer_package_name] + YARN_LIST_PARAMETERS,
94
+ npm: NPM_LIST_COMMAND + [renderer_package_name] + NPM_LIST_PARAMETERS,
95
+ capture_response: true
96
+ )
97
+ context.abort(
98
+ context.message('features.argo.dependencies.argo_missing_renderer_package_error', error)
99
+ ) unless status.success?
100
+ result
101
+ end
102
+
103
+ def run_yarn_install(context, js_system)
104
+ _result, error, status = js_system.call(
105
+ yarn: YARN_INSTALL_COMMAND + YARN_INSTALL_PARAMETERS,
106
+ npm: [],
107
+ capture_response: true
108
+ )
109
+
110
+ context.abort(
111
+ context.message('features.argo.dependencies.yarn_install_error', error)
112
+ ) unless status.success?
113
+ end
114
+
115
+ def run_yarn_run_script(context, js_system)
116
+ _result, error, status = js_system.call(
117
+ yarn: YARN_RUN_COMMAND + YARN_RUN_SCRIPT_NAME,
118
+ npm: [],
119
+ capture_response: true
120
+ )
121
+
122
+ context.abort(
123
+ context.message('features.argo.dependencies.yarn_run_script_error', error)
124
+ ) unless status.success?
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ module Extension
3
+ module Features
4
+ module Argo
5
+ class Checkout < Base
6
+ GIT_TEMPLATE = 'https://github.com/Shopify/argo-checkout-template.git'
7
+ RENDERER_PACKAGE = '@shopify/argo-checkout'
8
+ private_constant :GIT_TEMPLATE, :RENDERER_PACKAGE
9
+
10
+ def git_template
11
+ GIT_TEMPLATE
12
+ end
13
+
14
+ def renderer_package_name
15
+ RENDERER_PACKAGE
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Features
5
+ class ArgoConfig
6
+ CONFIG_FILE_NAME = 'extension.config.yml'
7
+
8
+ class << self
9
+ def parse_yaml(context, permitted_keys = [])
10
+ file_name = File.join(context.root, CONFIG_FILE_NAME)
11
+
12
+ return {} unless File.size?(file_name)
13
+
14
+ require 'yaml' # takes 20ms, so deferred as late as possible.
15
+ begin
16
+ config = YAML.load_file(file_name)
17
+
18
+ # `YAML.load_file` returns nil if the file is not empty
19
+ # but does not contain any parsable yml data, e.g. only comments
20
+ # We consider this valid
21
+ return {} if config.nil?
22
+
23
+ unless config.is_a?(Hash)
24
+ raise ShopifyCli::Abort, ShopifyCli::Context.message('core.yaml.error.not_hash', CONFIG_FILE_NAME)
25
+ end
26
+
27
+ config.transform_keys!(&:to_sym)
28
+ assert_valid_config(config, permitted_keys) unless permitted_keys.empty?
29
+
30
+ config
31
+ rescue Psych::SyntaxError => e
32
+ raise(
33
+ ShopifyCli::Abort,
34
+ ShopifyCli::Context.message('core.yaml.error.invalid', CONFIG_FILE_NAME, e.message)
35
+ )
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def assert_valid_config(config, permitted_keys)
42
+ unpermitted_keys = config.keys.select do |k|
43
+ !permitted_keys.include?(k)
44
+ end
45
+
46
+ unless unpermitted_keys.empty?
47
+ raise(
48
+ ShopifyCli::Abort,
49
+ ShopifyCli::Context.message(
50
+ 'features.argo.config.unpermitted_keys',
51
+ CONFIG_FILE_NAME,
52
+ unpermitted_keys.map { |k| "\n- #{k}" }.join
53
+ )
54
+ )
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end