simplygenius-atmos 0.13.0 → 0.13.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/simplygenius/atmos.rb +3 -0
- data/lib/simplygenius/atmos/cli.rb +61 -9
- data/lib/simplygenius/atmos/commands/account.rb +10 -10
- data/lib/simplygenius/atmos/commands/auth_exec.rb +1 -1
- data/lib/simplygenius/atmos/commands/bootstrap.rb +1 -1
- data/lib/simplygenius/atmos/commands/container.rb +44 -18
- data/lib/simplygenius/atmos/commands/generate.rb +2 -2
- data/lib/simplygenius/atmos/commands/otp.rb +1 -1
- data/lib/simplygenius/atmos/commands/secret.rb +1 -1
- data/lib/simplygenius/atmos/commands/tfutil.rb +4 -4
- data/lib/simplygenius/atmos/commands/user.rb +7 -7
- data/lib/simplygenius/atmos/providers/aws/container_manager.rb +35 -5
- data/lib/simplygenius/atmos/providers/aws/provider.rb +1 -1
- data/lib/simplygenius/atmos/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6e7037a18301c9dc8f8908d72b83d2390481145dcd1061d2c2d678e922bf658
|
4
|
+
data.tar.gz: '08858cc4a83f9af8cca448dc64c9a094ece7216c43b872c0c07bc9f8dcd32b0b'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75e6f5eac9061b38e12f162a31e721d74f97d532d576b142b5a4be5b39b952a91ffc013fc2cce175bd6b8fd0ee2fe8da34bbe73790a8686b930c2a6fb8368556
|
7
|
+
data.tar.gz: 9ebfb5234e13d3972c507c1366c1785ddebea03e23bd6dcc33b32c3057876f0dca2ec696c77bbfcd2ef7ba274aed95f56ac73809e142b52178a4c30902a73bb5
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
0.13.1 (05/04/2021)
|
2
|
+
-------------------
|
3
|
+
|
4
|
+
* fix console exception, extend console startup wait loop, and add better console logging and error reporting [2d44553](../../commit/2d44553)
|
5
|
+
* fix logging [3cc07b9](../../commit/3cc07b9)
|
6
|
+
* allow selection of specific items with cli config dump [675ebfe](../../commit/675ebfe)
|
7
|
+
* cli help line formatting [13b36a3](../../commit/13b36a3)
|
8
|
+
* add container pull helper [22518f3](../../commit/22518f3)
|
9
|
+
|
1
10
|
0.13.0 (01/20/2021)
|
2
11
|
-------------------
|
3
12
|
|
data/lib/simplygenius/atmos.rb
CHANGED
@@ -30,22 +30,22 @@ module SimplyGenius
|
|
30
30
|
end
|
31
31
|
|
32
32
|
option ["-d", "--debug"],
|
33
|
-
:flag, "debug output
|
33
|
+
:flag, "debug output",
|
34
34
|
default: false
|
35
35
|
|
36
36
|
option ["-q", "--quiet"],
|
37
|
-
:flag, "suppress output
|
37
|
+
:flag, "suppress output",
|
38
38
|
default: false
|
39
39
|
|
40
40
|
option ["-c", "--[no-]color"],
|
41
|
-
:flag, "colorize output (or not)
|
41
|
+
:flag, "colorize output (or not) (default: $stdout.tty?)"
|
42
42
|
|
43
43
|
option ["-e", "--atmos-env"],
|
44
|
-
'ENV', "The atmos environment
|
44
|
+
'ENV', "The atmos environment",
|
45
45
|
environment_variable: 'ATMOS_ENV', default: 'ops'
|
46
46
|
|
47
47
|
option ["-g", "--atmos-group"],
|
48
|
-
'GROUP', "The atmos working group
|
48
|
+
'GROUP', "The atmos working group for selecting recipe groups",
|
49
49
|
default: 'default'
|
50
50
|
|
51
51
|
option ["-p", "--load-path"],
|
@@ -53,7 +53,7 @@ module SimplyGenius
|
|
53
53
|
multivalued: true
|
54
54
|
|
55
55
|
option ["-o", "--override"],
|
56
|
-
"KEYVALUE", "overrides atmos configuration
|
56
|
+
"KEYVALUE", "overrides atmos configuration in the form 'some.config=value' where value can be expressed in yaml form for complex types e.g. foo=1 foo=abc, foo=[x, y], foo={x: y}",
|
57
57
|
multivalued: true
|
58
58
|
|
59
59
|
option ["-v", "--version"],
|
@@ -64,7 +64,7 @@ module SimplyGenius
|
|
64
64
|
end
|
65
65
|
|
66
66
|
option ["-l", "--[no-]log"],
|
67
|
-
:flag, "log to file in addition to terminal (or not)
|
67
|
+
:flag, "log to file in addition to terminal (or not)",
|
68
68
|
default: true
|
69
69
|
|
70
70
|
|
@@ -110,11 +110,29 @@ module SimplyGenius
|
|
110
110
|
option ["-j", "--json"],
|
111
111
|
:flag, "Dump config as json instead of yaml"
|
112
112
|
|
113
|
+
parameter "PATH",
|
114
|
+
"The dot notation path of a specific config item to get",
|
115
|
+
required: false
|
116
|
+
|
113
117
|
def execute
|
118
|
+
if path
|
119
|
+
result = Atmos.config[path]
|
120
|
+
result = case result
|
121
|
+
when Hash
|
122
|
+
result.to_h
|
123
|
+
when Array
|
124
|
+
result.to_a
|
125
|
+
else
|
126
|
+
result
|
127
|
+
end
|
128
|
+
else
|
129
|
+
result = Atmos.config.to_h
|
130
|
+
end
|
131
|
+
|
114
132
|
if json?
|
115
|
-
output = JSON.pretty_generate(
|
133
|
+
output = JSON.pretty_generate(result)
|
116
134
|
else
|
117
|
-
output = YAML.dump(
|
135
|
+
output = YAML.dump(result).sub(/^\s*---\s*/, '')
|
118
136
|
end
|
119
137
|
logger.info output
|
120
138
|
end
|
@@ -213,3 +231,37 @@ module SimplyGenius
|
|
213
231
|
|
214
232
|
end
|
215
233
|
end
|
234
|
+
|
235
|
+
# Hack to make clamp usage less of a pain to get long lines to fit within a
|
236
|
+
# standard terminal width
|
237
|
+
class Clamp::Help::Builder
|
238
|
+
|
239
|
+
def word_wrap(text, line_width:)
|
240
|
+
text.split("\n").collect do |line|
|
241
|
+
line.length > line_width ? line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip.split("\n") : line
|
242
|
+
end.flatten
|
243
|
+
end
|
244
|
+
|
245
|
+
def string
|
246
|
+
line_width = 79
|
247
|
+
indent_size = 4
|
248
|
+
indent = " " * indent_size
|
249
|
+
StringIO.new.tap do |out|
|
250
|
+
lines.each do |line|
|
251
|
+
case line
|
252
|
+
when Array
|
253
|
+
out << indent
|
254
|
+
out.puts(line[0])
|
255
|
+
formatted_line = line[1].gsub(/\((default|required)/, "\n\\0")
|
256
|
+
word_wrap(formatted_line, line_width: (line_width - indent_size * 2)).each do |l|
|
257
|
+
out << (indent * 2)
|
258
|
+
out.puts(l)
|
259
|
+
end
|
260
|
+
else
|
261
|
+
out.puts(line)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end.string
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
@@ -15,13 +15,13 @@ module SimplyGenius
|
|
15
15
|
subcommand "create", "Create a new account" do
|
16
16
|
|
17
17
|
option ["-s", "--source-env"],
|
18
|
-
"SOURCE_ENV", "Base the new env on a clone of the given one
|
18
|
+
"SOURCE_ENV", "Base the new env on a clone of the given one"
|
19
19
|
|
20
20
|
option ["-e", "--email"],
|
21
|
-
"EMAIL", "override default email used for new account
|
21
|
+
"EMAIL", "override default email used for new account"
|
22
22
|
|
23
23
|
option ["-n", "--name"],
|
24
|
-
"NAME", "override default name used for new account
|
24
|
+
"NAME", "override default name used for new account"
|
25
25
|
|
26
26
|
parameter "ENV",
|
27
27
|
"The name of the new env to create"
|
@@ -62,25 +62,25 @@ module SimplyGenius
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
subcommand "setup_credentials", "Convenience that adds accounts to the local aws
|
65
|
+
subcommand "setup_credentials", "Convenience that adds accounts to the local aws credentials store" do
|
66
66
|
|
67
67
|
option ["-u", "--user"],
|
68
|
-
"USERNAME", "The username in the cloud provider
|
68
|
+
"USERNAME", "The username in the cloud provider", required: true
|
69
69
|
|
70
70
|
option ["-k", "--key"],
|
71
|
-
"KEY", "The access key in the cloud provider
|
71
|
+
"KEY", "The access key in the cloud provider"
|
72
72
|
|
73
73
|
option ["-s", "--secret"],
|
74
|
-
"SECRET", "The access secret in the cloud provider
|
74
|
+
"SECRET", "The access secret in the cloud provider"
|
75
75
|
|
76
76
|
option ["-d", "--default"],
|
77
|
-
:flag, "Sets as default credentials
|
77
|
+
:flag, "Sets as default credentials"
|
78
78
|
|
79
79
|
option ["-f", "--force"],
|
80
|
-
:flag, "Forces overwrites of existing
|
80
|
+
:flag, "Forces overwrites of existing"
|
81
81
|
|
82
82
|
option ["-n", "--nowrite"],
|
83
|
-
:flag, "Trial run without writing results to files
|
83
|
+
:flag, "Trial run without writing results to files"
|
84
84
|
|
85
85
|
def execute
|
86
86
|
|
@@ -15,22 +15,44 @@ module SimplyGenius
|
|
15
15
|
end
|
16
16
|
|
17
17
|
option ["-c", "--cluster"],
|
18
|
-
"CLUSTER", "The cluster name
|
18
|
+
"CLUSTER", "The cluster name",
|
19
19
|
required: true
|
20
20
|
|
21
21
|
option ["-r", "--role"],
|
22
|
-
"ROLE", "The role to assume when deploying
|
22
|
+
"ROLE", "The role to assume when deploying"
|
23
|
+
|
24
|
+
subcommand "pull", "Pulls a container image from repository" do
|
25
|
+
|
26
|
+
option ["-v", "--revision"],
|
27
|
+
"REVISION", "Use as the remote image revision"
|
28
|
+
|
29
|
+
parameter "NAME",
|
30
|
+
"The name of the service (or task) to pull the image for"
|
31
|
+
|
32
|
+
def execute
|
33
|
+
Atmos.config.provider.auth_manager.authenticate(ENV, role: role) do |auth_env|
|
34
|
+
ClimateControl.modify(auth_env) do
|
35
|
+
mgr = Atmos.config.provider.container_manager
|
36
|
+
|
37
|
+
result = mgr.pull(name, revision: revision)
|
38
|
+
|
39
|
+
logger.info "Container pulled:\n #{display result}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
23
45
|
|
24
46
|
subcommand "push", "Only push a container image without activating it" do
|
25
47
|
|
26
48
|
option ["-i", "--image"],
|
27
|
-
"IMAGE", "The local container image to deploy
|
49
|
+
"IMAGE", "The local container image to deploy Defaults to service/task name"
|
28
50
|
|
29
51
|
option ["-v", "--revision"],
|
30
|
-
"REVISION", "Use as the remote image revision
|
52
|
+
"REVISION", "Use as the remote image revision"
|
31
53
|
|
32
54
|
parameter "NAME ...",
|
33
|
-
"The name of the service (or task) to deploy
|
55
|
+
"The name of the service (or task) to deploy. When multiple, the first is the primary, and the rest get deployed with its image"
|
34
56
|
|
35
57
|
def default_image
|
36
58
|
name_list.first
|
@@ -55,22 +77,22 @@ module SimplyGenius
|
|
55
77
|
subcommand "activate", "Activate a container that has already been pushed" do
|
56
78
|
|
57
79
|
option ["-v", "--revision"],
|
58
|
-
"REVISION", "Use the given revision of the pushed image
|
80
|
+
"REVISION", "Use the given revision of the pushed image to activate"
|
59
81
|
|
60
82
|
option ["-w", "--wait"],
|
61
|
-
:flag, "Wait for service to become stable after deploy
|
83
|
+
:flag, "Wait for service to become stable after deploy non-zero exit on fail"
|
62
84
|
|
63
85
|
option ["-l", "--list"],
|
64
|
-
:flag, "List the most recent pushed images
|
86
|
+
:flag, "List the most recent pushed images"
|
65
87
|
|
66
88
|
option ["-t", "--tagcount"],
|
67
|
-
"N", "Only show the last N items when listing
|
89
|
+
"N", "Only show the last N items when listing",
|
68
90
|
default: 10 do |s|
|
69
91
|
Integer(s)
|
70
92
|
end
|
71
93
|
|
72
94
|
parameter "NAME ...",
|
73
|
-
"The name of the service (or task) to activate
|
95
|
+
"The name of the service (or task) to activate. When multiple, the first is the primary, and the rest get activated with its image"
|
74
96
|
|
75
97
|
def execute
|
76
98
|
Atmos.config.provider.auth_manager.authenticate(ENV, role: role) do |auth_env|
|
@@ -125,16 +147,16 @@ module SimplyGenius
|
|
125
147
|
subcommand "deploy", "Push and activate a container" do
|
126
148
|
|
127
149
|
option ["-i", "--image"],
|
128
|
-
"IMAGE", "The local container image to deploy
|
150
|
+
"IMAGE", "The local container image to deploy. Defaults to service/task name"
|
129
151
|
|
130
152
|
option ["-w", "--wait"],
|
131
|
-
:flag, "Wait for service to become stable after deploy
|
153
|
+
:flag, "Wait for service to become stable after deploy non-zero exit on fail"
|
132
154
|
|
133
155
|
option ["-v", "--revision"],
|
134
|
-
"REVISION", "Use as the remote image revision
|
156
|
+
"REVISION", "Use as the remote image revision"
|
135
157
|
|
136
158
|
parameter "NAME ...",
|
137
|
-
"The name of the service (or task) to deploy
|
159
|
+
"The name of the service (or task) to deploy. When multiple, the first is the primary, and the rest get deployed with its image"
|
138
160
|
|
139
161
|
def default_image
|
140
162
|
name_list.first
|
@@ -171,10 +193,10 @@ module SimplyGenius
|
|
171
193
|
subcommand "console", "Spawn a console and attach to it" do
|
172
194
|
|
173
195
|
option ["-p", "--persist"],
|
174
|
-
:flag, "Leave the task running after disconnect
|
196
|
+
:flag, "Leave the task running after disconnect"
|
175
197
|
|
176
198
|
parameter "NAME",
|
177
|
-
"The name of the service (or task) to attach
|
199
|
+
"The name of the service (or task) to attach the console to"
|
178
200
|
|
179
201
|
def execute
|
180
202
|
Atmos.config.provider.auth_manager.authenticate(ENV, role: role) do |auth_env|
|
@@ -191,8 +213,12 @@ module SimplyGenius
|
|
191
213
|
logger.debug "Run task result: #{result}"
|
192
214
|
begin
|
193
215
|
match = result[:log_match]
|
194
|
-
|
195
|
-
|
216
|
+
if match.blank?
|
217
|
+
logger.error("Aborting, the console task failed to produce the expected output: #{log_pattern}")
|
218
|
+
else
|
219
|
+
local_command = local_command.collect {|c| match.names.each {|n| c = c.gsub("<#{n}>", match[n]) }; c }
|
220
|
+
system(*local_command)
|
221
|
+
end
|
196
222
|
ensure
|
197
223
|
if persist?
|
198
224
|
logger.info "Console disconnected, you can reconnect with: #{local_command.join(" ")}"
|
@@ -34,12 +34,12 @@ module SimplyGenius
|
|
34
34
|
option ["-l", "--list"],
|
35
35
|
:flag, "list available templates"
|
36
36
|
option ["-u", "--update"],
|
37
|
-
:flag, "update all installed templates
|
37
|
+
:flag, "update all installed templates"
|
38
38
|
option ["-p", "--sourcepath"],
|
39
39
|
"PATH", "search for templates using given sourcepath",
|
40
40
|
multivalued: true
|
41
41
|
option ["-r", "--[no-]sourcepaths"],
|
42
|
-
:flag, "clear sourcepaths from template search
|
42
|
+
:flag, "clear sourcepaths from template search", default: true
|
43
43
|
option ["-c", "--context"],
|
44
44
|
"CONTEXT", "provide context variables (dot notation)",
|
45
45
|
multivalued: true
|
@@ -13,21 +13,21 @@ module SimplyGenius
|
|
13
13
|
"Useful utilities when calling out from terraform with data.external"
|
14
14
|
end
|
15
15
|
|
16
|
-
subcommand "jsonify", "Manages json on stdin/out to conform
|
16
|
+
subcommand "jsonify", "Manages json on stdin/out to conform to use in terraform data.external" do
|
17
17
|
|
18
18
|
banner "Ensures json output only contains a single level Hash with string values (e.g. when execing curl returns a deep json hash of mixed values)"
|
19
19
|
|
20
20
|
option ["-a", "--atmos_config"],
|
21
|
-
:flag, "Includes the atmos config in the
|
21
|
+
:flag, "Includes the atmos config in the hash from parsing json on stdin"
|
22
22
|
|
23
23
|
option ["-c", "--clipboard"],
|
24
|
-
:flag, "Copies the actual command used
|
24
|
+
:flag, "Copies the actual command used to the clipboard to allow external debugging"
|
25
25
|
|
26
26
|
option ["-j", "--json"],
|
27
27
|
:flag, "The command output is parsed as json"
|
28
28
|
|
29
29
|
option ["-x", "--[no-]exit"],
|
30
|
-
:flag, "Exit with the command's exit code
|
30
|
+
:flag, "Exit with the command's exit code on failure (or not)", default: true
|
31
31
|
|
32
32
|
parameter "COMMAND ...",
|
33
33
|
"The command to call", :attribute_name => :command
|
@@ -14,31 +14,31 @@ module SimplyGenius
|
|
14
14
|
subcommand "create", "Create a new user" do
|
15
15
|
|
16
16
|
option ["-f", "--force"],
|
17
|
-
:flag, "forces deletion/updates for pre-existing
|
17
|
+
:flag, "forces deletion/updates for pre-existing resources",
|
18
18
|
default: false
|
19
19
|
|
20
20
|
option ["-l", "--login"],
|
21
|
-
:flag, "generate a login password
|
21
|
+
:flag, "generate a login password",
|
22
22
|
default: false
|
23
23
|
|
24
24
|
option ["-m", "--mfa"],
|
25
|
-
:flag, "setup a mfa device
|
25
|
+
:flag, "setup a mfa device",
|
26
26
|
default: false
|
27
27
|
|
28
28
|
option ["-k", "--key"],
|
29
|
-
:flag, "create access keys
|
29
|
+
:flag, "create access keys",
|
30
30
|
default: false
|
31
31
|
|
32
32
|
option ["-p", "--public-key"],
|
33
|
-
"PUBLIC_KEY", "add ssh public key
|
33
|
+
"PUBLIC_KEY", "add ssh public key"
|
34
34
|
|
35
35
|
option ["-g", "--group"],
|
36
36
|
"GROUP",
|
37
|
-
"associate the given groups to new user
|
37
|
+
"associate the given groups to new user",
|
38
38
|
multivalued: true
|
39
39
|
|
40
40
|
parameter "USERNAME",
|
41
|
-
"The username of the user to add
|
41
|
+
"The username of the user to add. Should be an email address" do |u|
|
42
42
|
raise ArgumentError.new("Not an email") if u !~ URI::MailTo::EMAIL_REGEXP
|
43
43
|
u
|
44
44
|
end
|
@@ -16,6 +16,33 @@ module SimplyGenius
|
|
16
16
|
@provider = provider
|
17
17
|
end
|
18
18
|
|
19
|
+
def pull(ecr_repo, revision: nil)
|
20
|
+
|
21
|
+
revision ||= 'latest'
|
22
|
+
result = {}
|
23
|
+
|
24
|
+
ecr = ::Aws::ECR::Client.new
|
25
|
+
resp = nil
|
26
|
+
|
27
|
+
resp = ecr.get_authorization_token
|
28
|
+
auth_data = resp.authorization_data.first
|
29
|
+
token = auth_data.authorization_token
|
30
|
+
endpoint = auth_data.proxy_endpoint
|
31
|
+
user, password = Base64.decode64(token).split(':')
|
32
|
+
|
33
|
+
# docker login into the ECR repo for the current account so that we can pull/push to it
|
34
|
+
run("docker", "login", "-u", user, "-p", password, endpoint)#, stdin_data: token)
|
35
|
+
|
36
|
+
image="#{ecr_repo}:#{revision}"
|
37
|
+
ecs_image="#{endpoint.sub(/https?:\/\//, '')}/#{image}"
|
38
|
+
|
39
|
+
logger.info "Pulling image from ECR repo #{ecs_image}"
|
40
|
+
run("docker", "pull", "#{ecs_image}")
|
41
|
+
|
42
|
+
result[:remote_image] = "#{ecs_image}"
|
43
|
+
return result
|
44
|
+
end
|
45
|
+
|
19
46
|
def push(ecs_name, local_image,
|
20
47
|
ecr_repo: ecs_name, revision: nil)
|
21
48
|
|
@@ -65,7 +92,7 @@ module SimplyGenius
|
|
65
92
|
new_defn = latest_defn.to_h
|
66
93
|
[:revision, :status, :task_definition_arn,
|
67
94
|
:requires_attributes, :compatibilities,
|
68
|
-
:registered_at, :registered_by].each do |attr|
|
95
|
+
:registered_at, :registered_by, :deregistered_at].each do |attr|
|
69
96
|
new_defn.delete(attr)
|
70
97
|
end
|
71
98
|
new_defn[:container_definitions].each {|c| c[:image] = remote_image}
|
@@ -229,9 +256,12 @@ module SimplyGenius
|
|
229
256
|
|
230
257
|
waiter_regexp = Regexp.new(waiter_log_pattern)
|
231
258
|
log_stream = "#{log_stream_prefix}/#{name}/#{task_id}"
|
232
|
-
logger.info "Task started,
|
259
|
+
logger.info "Task started, waiting for remote command"
|
260
|
+
logger.debug "Looking for log_pattern='#{waiter_log_pattern}' in group=#{log_group} stream=#{log_stream}"
|
233
261
|
log_token = nil
|
234
|
-
|
262
|
+
count = (Atmos.config['atmos.container.console.retry_count'] || 30).to_i
|
263
|
+
interval = (Atmos.config['atmos.container.console.retry_interval'] || 2).to_i
|
264
|
+
count.times do
|
235
265
|
resp = cwl.get_log_events(log_group_name: log_group, log_stream_name: log_stream, start_from_head: true, next_token: log_token)
|
236
266
|
resp.events.each do |e|
|
237
267
|
logger.debug("Task log #{e.timestamp}: #{e.message}")
|
@@ -240,8 +270,8 @@ module SimplyGenius
|
|
240
270
|
return result # return, not break due to doubly nested iterator
|
241
271
|
end
|
242
272
|
end
|
243
|
-
log_token = resp.next_forward_token
|
244
|
-
sleep
|
273
|
+
log_token = resp.next_forward_token if resp.events.length > 0
|
274
|
+
sleep interval
|
245
275
|
end
|
246
276
|
end
|
247
277
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simplygenius-atmos
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.13.
|
4
|
+
version: 0.13.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Conway
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|