chamber 2.13.1 → 2.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +101 -26
- data/lib/chamber.rb +72 -10
- data/lib/chamber/adapters/cloud/circle_ci.rb +16 -13
- data/lib/chamber/adapters/cloud/heroku.rb +40 -13
- data/lib/chamber/binary/circle_ci.rb +25 -12
- data/lib/chamber/binary/heroku.rb +31 -12
- data/lib/chamber/binary/runner.rb +37 -27
- data/lib/chamber/binary/travis.rb +5 -3
- data/lib/chamber/commands/base.rb +10 -16
- data/lib/chamber/commands/cloud/base.rb +3 -3
- data/lib/chamber/commands/cloud/pull.rb +2 -2
- data/lib/chamber/commands/cloud/push.rb +7 -7
- data/lib/chamber/commands/comparable.rb +2 -2
- data/lib/chamber/commands/compare.rb +6 -9
- data/lib/chamber/commands/initialize.rb +26 -22
- data/lib/chamber/commands/securable.rb +9 -9
- data/lib/chamber/commands/secure.rb +2 -2
- data/lib/chamber/commands/show.rb +8 -8
- data/lib/chamber/commands/sign.rb +2 -2
- data/lib/chamber/commands/verify.rb +2 -2
- data/lib/chamber/configuration.rb +6 -3
- data/lib/chamber/context_resolver.rb +8 -7
- data/lib/chamber/encryption_methods/ssl.rb +12 -12
- data/lib/chamber/file.rb +16 -14
- data/lib/chamber/file_set.rb +18 -8
- data/lib/chamber/files/signature.rb +16 -14
- data/lib/chamber/filters/decryption_filter.rb +12 -10
- data/lib/chamber/filters/encryption_filter.rb +8 -8
- data/lib/chamber/filters/environment_filter.rb +12 -14
- data/lib/chamber/filters/failed_decryption_filter.rb +6 -6
- data/lib/chamber/filters/insecure_filter.rb +3 -3
- data/lib/chamber/filters/namespace_filter.rb +5 -5
- data/lib/chamber/filters/secure_filter.rb +5 -5
- data/lib/chamber/filters/translate_secure_keys_filter.rb +5 -5
- data/lib/chamber/instance.rb +37 -21
- data/lib/chamber/key_pair.rb +7 -7
- data/lib/chamber/keys/base.rb +13 -13
- data/lib/chamber/keys/decryption.rb +3 -3
- data/lib/chamber/keys/encryption.rb +3 -3
- data/lib/chamber/namespace_set.rb +2 -4
- data/lib/chamber/settings.rb +45 -43
- data/lib/chamber/types/secured.rb +8 -10
- data/lib/chamber/version.rb +1 -1
- data/templates/settings.yml +2 -0
- metadata +24 -26
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bf2d68260ae1fa27b7a2befdc5ff274c34477ff3bf584027d39747fbcd5a489
|
4
|
+
data.tar.gz: 63f97b11849eb6e800b5f4e4f0ae49ad57d1e92cd942f114d417dc8c980a40a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a8f5f026bee9a0380410ee6ed8c4e563f0c465b56a0d111d10f8ef35eb986f4e3cfeb7acfaa283cfcc7380135026d63f4edbfd3649ea4bfc543b91410f1b155
|
7
|
+
data.tar.gz: 9d012efb86e89a1a78cd39f0bd54200d0508394b46a7b66b2144b645bcd86f17d25f1f2ad3d2df8c3cab355f1669903b17d8dc8de024d520b854022a6e32d892
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/README.md
CHANGED
@@ -1,5 +1,33 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
Chamber
|
2
|
+
================================================================================
|
3
|
+
|
4
|
+
<div align="center">
|
5
|
+
<a href="https://rubygems.org/gems/chamber" alt="RubyGems Version">
|
6
|
+
<img src="https://img.shields.io/gem/v/chamber.svg?style=flat-square&label=current-version" alt="RubyGems Version" />
|
7
|
+
</a>
|
8
|
+
|
9
|
+
<a href="https://rubygems.org/gems/chamber" alt="RubyGems Rank Overall">
|
10
|
+
<img src="https://img.shields.io/gem/rt/chamber.svg?style=flat-square&label=total-rank" alt="RubyGems Rank Overall" />
|
11
|
+
</a>
|
12
|
+
|
13
|
+
<a href="https://rubygems.org/gems/chamber" alt="RubyGems Rank Daily">
|
14
|
+
<img src="https://img.shields.io/gem/rd/chamber.svg?style=flat-square&label=daily-rank" alt="RubyGems Rank Daily" />
|
15
|
+
</a>
|
16
|
+
|
17
|
+
<a href="https://rubygems.org/gems/chamber" alt="RubyGems Downloads">
|
18
|
+
<img src="https://img.shields.io/gem/dt/chamber.svg?style=flat-square&label=total-downloads" alt="RubyGems Downloads" />
|
19
|
+
</a>
|
20
|
+
|
21
|
+
<a href="https://github.com/thekompanee/chamber/actions?query=workflow%3ABuild" alt="Build Status">
|
22
|
+
<img src="https://img.shields.io/github/workflow/status/thekompanee/chamber/Build?label=CI&style=flat-square&logo=github" alt="Build Status" />
|
23
|
+
</a>
|
24
|
+
|
25
|
+
<a href="#" alt="Maintainability">
|
26
|
+
<img src="https://img.shields.io/codeclimate/maintainability/thekompanee/chamber?style=flat-square&label=grade" alt="Maintainability" />
|
27
|
+
</a>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<br>
|
3
31
|
|
4
32
|
Chamber is the auto-encrypting, extremely organizable, Heroku-loving,
|
5
33
|
CLI-having, non-extra-repo-needing, non-Rails-specific-ing, CI-serving
|
@@ -9,17 +37,73 @@ We looked at all of the options out there and thought something was still
|
|
9
37
|
missing, so we wrote Chamber. We made it with lots of ❤ and we hope you like it
|
10
38
|
as much as we do.
|
11
39
|
|
12
|
-
|
40
|
+
What Sets Chamber Apart
|
41
|
+
--------------------------------------------------------------------------------
|
13
42
|
|
14
43
|
For an idea of how Chamber compares to other popular libraries, check out our
|
15
44
|
[Gem Comparison][comparison].
|
16
45
|
|
17
|
-
|
46
|
+
Basic Usage
|
47
|
+
--------------------------------------------------------------------------------
|
48
|
+
|
49
|
+
Before starting this guide, make sure you [install chamber][installation].
|
50
|
+
|
51
|
+
Once your app is initialized, you should have a `settings.yml` file somewhere.
|
52
|
+
A lot of times it's the root of your project and sometimes it's in a framework
|
53
|
+
specific location.
|
54
|
+
|
55
|
+
Inside of here you can define any settings you'd like like so:
|
56
|
+
|
57
|
+
```yaml
|
58
|
+
# settings.yml
|
59
|
+
|
60
|
+
smtp_username: 'my_username'
|
61
|
+
smtp_password: 'my_password'
|
62
|
+
```
|
63
|
+
|
64
|
+
From there you can access your settings by using the special `Chamber.env`
|
65
|
+
constant.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
Chamber.env.smtp_password
|
69
|
+
# => 'my_password'
|
70
|
+
```
|
71
|
+
|
72
|
+
If you want to encrypt a setting, prefix the setting name with `_secure_` like
|
73
|
+
so:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
# settings.yml
|
77
|
+
|
78
|
+
smtp_username: 'my_username'
|
79
|
+
_secure_smtp_password: 'my_password'
|
80
|
+
```
|
81
|
+
|
82
|
+
And then run `chamber secure`. Your settings file will have an encrypted value:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
# settings.yml
|
86
|
+
|
87
|
+
smtp_username: 'my_username'
|
88
|
+
_secure_smtp_password: JL5hAVux4tERpv49QPWxy9H0VC2Rnk7V8/e8+1XOwPcXcoH/a7Lh253UY/v9m8nI/Onb+ZG9nZ082J4M/BmLa+f7jwMEwufIqbUhUah9eKIW8xcxlppBYpl7JVGf2HJF5TfCN44gMQNgGNzboCQXKqRyeGFm4u772Sg9V2gEx/q7qJ6F4jg7v/cltCFLmJfXA2SHA5Dai4p9L4IvMVVJGm34k5j7KOegNqpVWs2RY99cagjPuzc9VM2XSUsXgqcUJdmH8YtPW8Kqkyg0oYlRh6VQWABlWXwTZz74QjTTjqtqfoELIoFTMBDh+cCvuUTAE5m06LhlqauVrB4UnBsd5g==
|
89
|
+
```
|
90
|
+
|
91
|
+
which you still access the same way because Chamber handles the decryption for
|
92
|
+
you:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
Chamber.env.smtp_password
|
96
|
+
# => 'my_password'
|
97
|
+
```
|
98
|
+
|
99
|
+
Full Reference
|
100
|
+
--------------------------------------------------------------------------------
|
18
101
|
|
19
|
-
|
102
|
+
There's so much to Chamber, we couldn't put it all in the README. For the full
|
20
103
|
Chamber guide, visit the [wiki][wiki].
|
21
104
|
|
22
|
-
|
105
|
+
Credits
|
106
|
+
--------------------------------------------------------------------------------
|
23
107
|
|
24
108
|
Chamber was written by [Jeff Felchner][jeff-profile] and
|
25
109
|
[Mark McEahern][mark-profile]
|
@@ -30,27 +114,18 @@ Chamber is maintained and funded by [The Kompanee, Ltd.][kompanee-site]
|
|
30
114
|
|
31
115
|
The names and logos for The Kompanee are trademarks of The Kompanee, Ltd.
|
32
116
|
|
33
|
-
|
117
|
+
License
|
118
|
+
--------------------------------------------------------------------------------
|
34
119
|
|
35
|
-
Chamber is Copyright © 2014-
|
120
|
+
Chamber is Copyright © 2014-2021 Jeff Felchner and Mark McEahern. It is free
|
36
121
|
software, and may be redistributed under the terms specified in the
|
37
122
|
[LICENSE][license] file.
|
38
123
|
|
39
|
-
[
|
40
|
-
[
|
41
|
-
[
|
42
|
-
[
|
43
|
-
[
|
44
|
-
[
|
45
|
-
[
|
46
|
-
[
|
47
|
-
[inch]: https://inch-ci.org/github/thekompanee/chamber
|
48
|
-
[jeff-profile]: https://github.com/jfelchner
|
49
|
-
[kompanee-logo]: https://kompanee-public-assets.s3.amazonaws.com/readmes/kompanee-horizontal-black.png
|
50
|
-
[kompanee-site]: http://www.thekompanee.com
|
51
|
-
[license]: https://github.com/thekompanee/chamber/blob/master/LICENSE.txt
|
52
|
-
[mark-profile]: https://github.com/m5rk
|
53
|
-
[namespace-keys]: https://github.com/thekompanee/chamber/wiki/Namespaced-Key-Pairs
|
54
|
-
[plain-ruby]: https://github.com/thekompanee/chamber/wiki/Installation#in-a-ruby-project-or-ruby-gem
|
55
|
-
[travis]: https://github.com/thekompanee/chamber/wiki/TravisCI
|
56
|
-
[wiki]: https://github.com/thekompanee/chamber/wiki
|
124
|
+
[comparison]: https://github.com/thekompanee/chamber/wiki/Gem-Comparison
|
125
|
+
[jeff-profile]: https://github.com/jfelchner
|
126
|
+
[kompanee-logo]: https://kompanee-public-assets.s3.amazonaws.com/readmes/kompanee-horizontal-black.png
|
127
|
+
[kompanee-site]: http://www.thekompanee.com
|
128
|
+
[license]: https://github.com/thekompanee/chamber/blob/master/LICENSE.txt
|
129
|
+
[mark-profile]: https://github.com/m5rk
|
130
|
+
[wiki]: https://github.com/thekompanee/chamber/wiki
|
131
|
+
[installation]: https://github.com/thekompanee/chamber/wiki/Installation
|
data/lib/chamber.rb
CHANGED
@@ -7,12 +7,8 @@ require 'chamber/rails'
|
|
7
7
|
module Chamber
|
8
8
|
attr_writer :instance
|
9
9
|
|
10
|
-
def load(
|
11
|
-
self.instance = Instance.new(
|
12
|
-
end
|
13
|
-
|
14
|
-
def to_s(options = {})
|
15
|
-
instance.to_s(options)
|
10
|
+
def load(**args)
|
11
|
+
self.instance = Instance.new(**args)
|
16
12
|
end
|
17
13
|
|
18
14
|
def env
|
@@ -20,7 +16,61 @@ module Chamber
|
|
20
16
|
end
|
21
17
|
|
22
18
|
def instance
|
23
|
-
@instance ||= Instance.new
|
19
|
+
@instance ||= Instance.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def [](key)
|
23
|
+
instance.[](key)
|
24
|
+
end
|
25
|
+
|
26
|
+
def configuration
|
27
|
+
instance.configuration
|
28
|
+
end
|
29
|
+
|
30
|
+
def decrypt(value, **args)
|
31
|
+
instance.decrypt(value, **args)
|
32
|
+
end
|
33
|
+
|
34
|
+
def encrypt(value, **args)
|
35
|
+
instance.encrypt(value, **args)
|
36
|
+
end
|
37
|
+
|
38
|
+
def files
|
39
|
+
instance.files
|
40
|
+
end
|
41
|
+
|
42
|
+
def filenames
|
43
|
+
instance.filenames
|
44
|
+
end
|
45
|
+
|
46
|
+
def namespaces
|
47
|
+
instance.namespaces
|
48
|
+
end
|
49
|
+
|
50
|
+
def secure
|
51
|
+
instance.secure
|
52
|
+
end
|
53
|
+
|
54
|
+
def sign
|
55
|
+
instance.sign
|
56
|
+
end
|
57
|
+
|
58
|
+
def verify
|
59
|
+
instance.verify
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_environment
|
63
|
+
instance.to_environment
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_hash
|
67
|
+
instance.to_hash
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_s(**args)
|
71
|
+
return '' unless @instance
|
72
|
+
|
73
|
+
instance.to_s(**args)
|
24
74
|
end
|
25
75
|
|
26
76
|
def method_missing(name, *args)
|
@@ -33,11 +83,23 @@ module Chamber
|
|
33
83
|
instance.respond_to?(name, include_private)
|
34
84
|
end
|
35
85
|
|
36
|
-
module_function :
|
37
|
-
:
|
86
|
+
module_function :[],
|
87
|
+
:configuration,
|
88
|
+
:decrypt,
|
89
|
+
:encrypt,
|
38
90
|
:env,
|
91
|
+
:filenames,
|
92
|
+
:files,
|
39
93
|
:instance,
|
40
94
|
:instance=,
|
95
|
+
:load,
|
41
96
|
:method_missing,
|
42
|
-
:
|
97
|
+
:namespaces,
|
98
|
+
:respond_to_missing?,
|
99
|
+
:secure,
|
100
|
+
:sign,
|
101
|
+
:to_environment,
|
102
|
+
:to_hash,
|
103
|
+
:to_s,
|
104
|
+
:verify
|
43
105
|
end
|
@@ -17,11 +17,11 @@ class CircleCi
|
|
17
17
|
:username,
|
18
18
|
:vcs_type
|
19
19
|
|
20
|
-
def initialize(
|
21
|
-
self.api_token =
|
22
|
-
self.project =
|
23
|
-
self.username =
|
24
|
-
self.vcs_type =
|
20
|
+
def initialize(api_token:, project:, username:, vcs_type:)
|
21
|
+
self.api_token = api_token
|
22
|
+
self.project = project
|
23
|
+
self.username = username
|
24
|
+
self.vcs_type = vcs_type
|
25
25
|
end
|
26
26
|
|
27
27
|
def add_environment_variable(name, value)
|
@@ -39,18 +39,21 @@ class CircleCi
|
|
39
39
|
response['name']
|
40
40
|
end
|
41
41
|
|
42
|
+
# rubocop:disable Layout/MultilineAssignmentLayout
|
42
43
|
def environment_variables
|
43
|
-
@environment_variables ||=
|
44
|
-
|
44
|
+
@environment_variables ||= \
|
45
|
+
begin
|
46
|
+
request = ::Net::HTTP::Get.new(request_uri(resource: 'envvar'))
|
45
47
|
|
46
|
-
|
47
|
-
|
48
|
+
request.basic_auth api_token, ''
|
49
|
+
request['Content-Type'] = 'application/json'
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
::JSON
|
52
|
+
.parse(response(request).body)
|
53
|
+
.each_with_object({}) { |e, m| m[e['name']] = e['value'] }
|
54
|
+
end
|
53
55
|
end
|
56
|
+
# rubocop:enable Layout/MultilineAssignmentLayout
|
54
57
|
|
55
58
|
def remove_environment_variable(name)
|
56
59
|
request = ::Net::HTTP::Delete.new(request_uri(resource: "envvar/#{name}"))
|
@@ -8,38 +8,65 @@ module Chamber
|
|
8
8
|
module Adapters
|
9
9
|
module Cloud
|
10
10
|
class Heroku
|
11
|
-
|
11
|
+
API_HOST = 'api.heroku.com'
|
12
|
+
API_PORT = 443
|
13
|
+
API_BASE_URI = ''
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
+
attr_accessor :api_token,
|
16
|
+
:app
|
17
|
+
|
18
|
+
def initialize(api_token:, app:)
|
19
|
+
self.api_token = api_token
|
20
|
+
self.app = app
|
15
21
|
end
|
16
22
|
|
17
|
-
def add_environment_variable(name, value)
|
18
|
-
value
|
23
|
+
def add_environment_variable(name, value) # rubocop:disable Metrics/AbcSize
|
24
|
+
value = value.gsub(/\n/, '\n') if value
|
25
|
+
request = ::Net::HTTP::Patch.new(config_vars_uri)
|
26
|
+
|
27
|
+
request['Authorization'] = "Bearer #{api_token}"
|
28
|
+
request['Accept'] = 'application/vnd.heroku+json; version=3'
|
29
|
+
request['Content-Type'] = 'application/json'
|
30
|
+
request.body = ::JSON.dump(Hash[name, value])
|
19
31
|
|
20
|
-
response =
|
32
|
+
response = ::JSON.parse(response(request).body)
|
21
33
|
|
22
|
-
fail NameError,
|
34
|
+
fail NameError, response['message'] if response['message']
|
23
35
|
|
24
36
|
response
|
25
37
|
end
|
26
38
|
|
27
39
|
def environment_variables
|
28
|
-
|
40
|
+
request = ::Net::HTTP::Get.new(config_vars_uri)
|
41
|
+
|
42
|
+
request['Authorization'] = "Bearer #{api_token}"
|
43
|
+
request['Accept'] = 'application/vnd.heroku+json; version=3'
|
44
|
+
|
45
|
+
response = ::JSON.parse(response(request).body)
|
46
|
+
|
47
|
+
fail NameError, response['message'] if response['message']
|
48
|
+
|
49
|
+
response
|
29
50
|
end
|
30
51
|
|
31
52
|
def remove_environment_variable(name)
|
32
|
-
|
53
|
+
add_environment_variable(name, nil)
|
33
54
|
end
|
34
55
|
|
35
56
|
private
|
36
57
|
|
37
|
-
def
|
38
|
-
|
58
|
+
def config_vars_uri
|
59
|
+
"#{API_BASE_URI}/apps/#{app}/config-vars"
|
60
|
+
end
|
61
|
+
|
62
|
+
def response(request)
|
63
|
+
connection.request(request)
|
39
64
|
end
|
40
65
|
|
41
|
-
def
|
42
|
-
|
66
|
+
def connection
|
67
|
+
@connection ||= ::Net::HTTP.new(API_HOST, API_PORT).tap do |conn|
|
68
|
+
conn.use_ssl = true
|
69
|
+
end
|
43
70
|
end
|
44
71
|
end
|
45
72
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'thor'
|
4
|
+
require 'chamber/core_ext/hash'
|
4
5
|
require 'chamber/commands/cloud/clear'
|
5
6
|
require 'chamber/commands/cloud/push'
|
6
7
|
require 'chamber/commands/cloud/pull'
|
@@ -36,8 +37,9 @@ class CircleCi < Thor
|
|
36
37
|
desc: 'The type of VCS your project is using.',
|
37
38
|
enum: %w{github bitbucket}
|
38
39
|
|
39
|
-
desc 'clear',
|
40
|
-
|
40
|
+
desc 'clear',
|
41
|
+
'Removes all CircleCi environment variables which match settings that Chamber ' \
|
42
|
+
'knows about'
|
41
43
|
|
42
44
|
method_option :dry_run,
|
43
45
|
type: :boolean,
|
@@ -46,11 +48,14 @@ class CircleCi < Thor
|
|
46
48
|
'would change if cleared'
|
47
49
|
|
48
50
|
def clear
|
49
|
-
Commands::Cloud::Clear.call(options
|
51
|
+
Commands::Cloud::Clear.call(**options
|
52
|
+
.transform_keys(&:to_sym)
|
53
|
+
.merge(shell: self, adapter: 'circle_ci'))
|
50
54
|
end
|
51
55
|
|
52
|
-
desc 'push',
|
53
|
-
|
56
|
+
desc 'push',
|
57
|
+
'Sends settings to CircleCi so that they may be used in the application ' \
|
58
|
+
'once it is deployed'
|
54
59
|
|
55
60
|
method_option :dry_run,
|
56
61
|
type: :boolean,
|
@@ -75,11 +80,14 @@ class CircleCi < Thor
|
|
75
80
|
'will be pushed'
|
76
81
|
|
77
82
|
def push
|
78
|
-
Commands::Cloud::Push.call(options
|
83
|
+
Commands::Cloud::Push.call(**options
|
84
|
+
.transform_keys(&:to_sym)
|
85
|
+
.merge(shell: self, adapter: 'circle_ci'))
|
79
86
|
end
|
80
87
|
|
81
|
-
desc 'pull',
|
82
|
-
|
88
|
+
desc 'pull',
|
89
|
+
'Retrieves the environment variables for the application and stores them in a ' \
|
90
|
+
'temporary file'
|
83
91
|
|
84
92
|
method_option :into,
|
85
93
|
type: :string,
|
@@ -87,11 +95,14 @@ class CircleCi < Thor
|
|
87
95
|
'stored. This file WILL BE OVERRIDDEN.'
|
88
96
|
|
89
97
|
def pull
|
90
|
-
Commands::Cloud::Pull.call(options
|
98
|
+
Commands::Cloud::Pull.call(**options
|
99
|
+
.transform_keys(&:to_sym)
|
100
|
+
.merge(shell: self, adapter: 'circle_ci'))
|
91
101
|
end
|
92
102
|
|
93
|
-
desc 'compare',
|
94
|
-
|
103
|
+
desc 'compare',
|
104
|
+
'Displays the difference between what is currently stored in the ' \
|
105
|
+
'CircleCi application\'s config and what Chamber knows about locally'
|
95
106
|
|
96
107
|
method_option :only_sensitive,
|
97
108
|
type: :boolean,
|
@@ -102,7 +113,9 @@ class CircleCi < Thor
|
|
102
113
|
'which are marked as "_secure"'
|
103
114
|
|
104
115
|
def compare
|
105
|
-
Commands::Cloud::Compare.call(options
|
116
|
+
Commands::Cloud::Compare.call(**options
|
117
|
+
.transform_keys(&:to_sym)
|
118
|
+
.merge(shell: self, adapter: 'circle_ci'))
|
106
119
|
end
|
107
120
|
end
|
108
121
|
end
|