stack_master 0.14.0 → 0.15.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.
- checksums.yaml +4 -4
- data/README.md +31 -0
- data/features/apply.feature +11 -11
- data/features/apply_with_s3.feature +1 -1
- data/features/delete.feature +1 -1
- data/features/events.feature +1 -1
- data/features/region_aliases.feature +1 -1
- data/lib/stack_master/config.rb +3 -0
- data/lib/stack_master/stack.rb +1 -1
- data/lib/stack_master/stack_definition.rb +8 -7
- data/lib/stack_master/template_compiler.rb +2 -2
- data/lib/stack_master/template_compilers/cfndsl.rb +2 -2
- data/lib/stack_master/template_compilers/json.rb +2 -2
- data/lib/stack_master/template_compilers/sparkle_formation.rb +8 -3
- data/lib/stack_master/template_compilers/yaml.rb +1 -1
- data/lib/stack_master/validator.rb +1 -1
- data/lib/stack_master/version.rb +1 -1
- data/spec/stack_master/stack_spec.rb +1 -1
- data/spec/stack_master/template_compiler_spec.rb +8 -2
- data/spec/stack_master/template_compilers/sparkle_formation_spec.rb +17 -2
- data/stack_master.gemspec +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44ae5dfa519051496de9c2707df2441f8a0a9115
|
4
|
+
data.tar.gz: 8f2065b8c59a2a2399f0398a0dc6a8541d864287
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50f3472de66c642581c80398f5430c9fcb596f5b973582834a65bfbca589265be7e2951a584e2459f42f2aa9fcdf1fd2c9fd9bfd07dca1397e8007d67641c6f4
|
7
|
+
data.tar.gz: 2a2e5221add3e4aa4c3910de36f73d26eb551d63b3272526e5329124d386feccc8566bcbe593a4e49833e8996c7835ab1d577b4e72d70326176fbc5242f45c1e
|
data/README.md
CHANGED
@@ -390,6 +390,37 @@ container_definitions array!(
|
|
390
390
|
)
|
391
391
|
```
|
392
392
|
|
393
|
+
## Compiler Options & Alternate Template Directories
|
394
|
+
|
395
|
+
StackMaster allows you to separate your stack definitions and parameters from your templates by way of a `template_dir` key in your stack_master.yml.
|
396
|
+
You can also pass compiler-specific options to the template compiler to further customize SparkleFormation or CfnDsl's behavior. Combining the 2 lets you move your SFN templates away from your stack definitions. For example, if your project is laid out as:
|
397
|
+
|
398
|
+
```
|
399
|
+
project-root
|
400
|
+
|-- envs
|
401
|
+
|-- env-1
|
402
|
+
|-- stack_master.yml
|
403
|
+
|-- env-2
|
404
|
+
|-- stack_master.yml
|
405
|
+
|-- sparkle
|
406
|
+
|-- templates
|
407
|
+
|-- my-stack.rb
|
408
|
+
```
|
409
|
+
|
410
|
+
Your env-1/stack_master.yml files can reference common templates by setting:
|
411
|
+
|
412
|
+
```
|
413
|
+
template_dir: ../../sparkle/templates
|
414
|
+
stack_defaults:
|
415
|
+
compiler_options:
|
416
|
+
sparkle_path: ../../sparkle
|
417
|
+
|
418
|
+
stacks:
|
419
|
+
us-east-1:
|
420
|
+
my-stack:
|
421
|
+
template: my-stack.rb
|
422
|
+
```
|
423
|
+
|
393
424
|
## Commands
|
394
425
|
|
395
426
|
```bash
|
data/features/apply.feature
CHANGED
@@ -78,7 +78,7 @@ Feature: Apply command
|
|
78
78
|
| + "Vpc": { |
|
79
79
|
| Parameters diff: |
|
80
80
|
| KeyName: my-key |
|
81
|
-
And the output should match /2020-10-29 00:00:00
|
81
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
82
82
|
Then the exit status should be 0
|
83
83
|
|
84
84
|
Scenario: Run apply and don't create the stack
|
@@ -90,7 +90,7 @@ Feature: Apply command
|
|
90
90
|
| Parameters diff: |
|
91
91
|
| KeyName: my-key |
|
92
92
|
| aborted |
|
93
|
-
And the output should not match /2020-10-29 00:00:00
|
93
|
+
And the output should not match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
94
94
|
Then the exit status should be 0
|
95
95
|
|
96
96
|
Scenario: Run apply with region only and create 2 stacks
|
@@ -120,11 +120,11 @@ Feature: Apply command
|
|
120
120
|
| + "Vpc": { |
|
121
121
|
| Parameters diff: |
|
122
122
|
| KeyName: my-key |
|
123
|
-
And the output should match /2020-10-29 00:00:00
|
124
|
-
And the output should match /2020-10-29 00:00:00
|
123
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
124
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
|
125
125
|
Then the exit status should be 0
|
126
|
-
And the output should match /2020-10-29 00:00:00
|
127
|
-
And the output should match /2020-10-29 00:00:00
|
126
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
127
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
|
128
128
|
Then the exit status should be 0
|
129
129
|
|
130
130
|
Scenario: Create stack with --changed
|
@@ -154,11 +154,11 @@ Feature: Apply command
|
|
154
154
|
| + "Vpc": { |
|
155
155
|
| Parameters diff: |
|
156
156
|
| KeyName: my-key |
|
157
|
-
And the output should match /2020-10-29 00:00:00
|
158
|
-
And the output should match /2020-10-29 00:00:00
|
157
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
158
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
|
159
159
|
Then the exit status should be 0
|
160
|
-
And the output should match /2020-10-29 00:00:00
|
161
|
-
And the output should match /2020-10-29 00:00:00
|
160
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
161
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
|
162
162
|
Then the exit status should be 0
|
163
163
|
|
164
164
|
Scenario: Update a stack
|
@@ -324,7 +324,7 @@ Feature: Apply command
|
|
324
324
|
| + "TestSg": { |
|
325
325
|
| Parameters diff: |
|
326
326
|
| VpcId: vpc-xxxxxx |
|
327
|
-
And the output should match /2020-10-29 00:00:00
|
327
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-web AWS::CloudFormation::Stack CREATE_COMPLETE/
|
328
328
|
Then the exit status should be 0
|
329
329
|
|
330
330
|
Scenario: Create a stack with a notification ARN and a stack update policy
|
@@ -68,7 +68,7 @@ Feature: Apply command
|
|
68
68
|
| + "Vpc": { |
|
69
69
|
| Parameters diff: |
|
70
70
|
| KeyName: my-key |
|
71
|
-
And the output should match /2020-10-29 00:00:00
|
71
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
72
72
|
And an S3 file in bucket "my-bucket" with key "cfn_templates/my-app/myapp_vpc.json" exists with content:
|
73
73
|
"""
|
74
74
|
{
|
data/features/delete.feature
CHANGED
@@ -8,7 +8,7 @@ Feature: Delete command
|
|
8
8
|
| stack_id | event_id | stack_name | logical_resource_id | resource_status | resource_type | timestamp |
|
9
9
|
| 1 | 1 | myapp-vpc | myapp-vpc | DELETE_COMPLETE | AWS::CloudFormation::Stack | 2020-10-29 00:00:00 |
|
10
10
|
When I run `stack_master delete us-east-1 myapp-vpc --trace`
|
11
|
-
And the output should match /2020-10-29 00:00:00
|
11
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack DELETE_COMPLETE/
|
12
12
|
Then the exit status should be 0
|
13
13
|
|
14
14
|
Scenario: Run a delete command on a stack that does not exists
|
data/features/events.feature
CHANGED
@@ -30,4 +30,4 @@ Feature: Events command
|
|
30
30
|
| 1 | 1 | myapp-vpc | TestSg | CREATE_COMPLETE | AWS::EC2::SecurityGroup | 2020-10-29 00:00:00 |
|
31
31
|
| 1 | 1 | myapp-vpc | myapp-vpc | CREATE_COMPLETE | AWS::CloudFormation::Stack | 2020-10-29 00:00:00 |
|
32
32
|
When I run `stack_master events us-east-1 myapp-vpc --trace`
|
33
|
-
And the output should match /2020-10-29 00:00:00
|
33
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
@@ -58,5 +58,5 @@ Feature: Region aliases
|
|
58
58
|
| + "Vpc": { |
|
59
59
|
| Parameters diff: |
|
60
60
|
| KeyName: my-key |
|
61
|
-
And the output should match /2020-10-29 00:00:00
|
61
|
+
And the output should match /2020-10-29 00:00:00 (\+|\-)[0-9]{4} myapp-vpc AWS::CloudFormation::Stack CREATE_COMPLETE/
|
62
62
|
Then the exit status should be 0
|
data/lib/stack_master/config.rb
CHANGED
@@ -12,6 +12,7 @@ module StackMaster
|
|
12
12
|
|
13
13
|
attr_accessor :stacks,
|
14
14
|
:base_dir,
|
15
|
+
:template_dir,
|
15
16
|
:stack_defaults,
|
16
17
|
:region_defaults,
|
17
18
|
:region_aliases,
|
@@ -33,6 +34,7 @@ module StackMaster
|
|
33
34
|
def initialize(config, base_dir)
|
34
35
|
@config = config
|
35
36
|
@base_dir = base_dir
|
37
|
+
@template_dir = config.fetch('template_dir', nil)
|
36
38
|
@stack_defaults = config.fetch('stack_defaults', {})
|
37
39
|
@region_aliases = Utils.underscore_keys_to_hyphen(config.fetch('region_aliases', {}))
|
38
40
|
@region_to_aliases = @region_aliases.inject({}) do |hash, (key, value)|
|
@@ -108,6 +110,7 @@ module StackMaster
|
|
108
110
|
'region' => region,
|
109
111
|
'stack_name' => stack_name,
|
110
112
|
'base_dir' => @base_dir,
|
113
|
+
'template_dir' => @template_dir,
|
111
114
|
'additional_parameter_lookup_dirs' => @region_to_aliases[region])
|
112
115
|
@stacks << StackDefinition.new(stack_attributes)
|
113
116
|
end
|
data/lib/stack_master/stack.rb
CHANGED
@@ -63,7 +63,7 @@ module StackMaster
|
|
63
63
|
|
64
64
|
def self.generate(stack_definition, config)
|
65
65
|
parameter_hash = ParameterLoader.load(stack_definition.parameter_files)
|
66
|
-
template_body = TemplateCompiler.compile(config, stack_definition.template_file_path)
|
66
|
+
template_body = TemplateCompiler.compile(config, stack_definition.template_file_path, stack_definition.compiler_options)
|
67
67
|
template_format = TemplateUtils.identify_template_format(template_body)
|
68
68
|
parameters = ParameterResolver.resolve(config, stack_definition, parameter_hash)
|
69
69
|
stack_policy_body = if stack_definition.stack_policy_file_path
|
@@ -7,20 +7,24 @@ module StackMaster
|
|
7
7
|
:role_arn,
|
8
8
|
:notification_arns,
|
9
9
|
:base_dir,
|
10
|
+
:template_dir,
|
10
11
|
:secret_file,
|
11
12
|
:stack_policy_file,
|
12
13
|
:additional_parameter_lookup_dirs,
|
13
14
|
:s3,
|
14
|
-
:files
|
15
|
+
:files,
|
16
|
+
:compiler_options
|
15
17
|
|
16
18
|
include Utils::Initializable
|
17
19
|
|
18
20
|
def initialize(attributes = {})
|
19
21
|
@additional_parameter_lookup_dirs = []
|
22
|
+
@compiler_options = {}
|
20
23
|
@notification_arns = []
|
21
24
|
@s3 = {}
|
22
25
|
@files = []
|
23
26
|
super
|
27
|
+
@template_dir ||= File.join(@base_dir, 'templates')
|
24
28
|
end
|
25
29
|
|
26
30
|
def ==(other)
|
@@ -35,15 +39,12 @@ module StackMaster
|
|
35
39
|
@secret_file == other.secret_file &&
|
36
40
|
@stack_policy_file == other.stack_policy_file &&
|
37
41
|
@additional_parameter_lookup_dirs == other.additional_parameter_lookup_dirs &&
|
38
|
-
@s3 == other.s3
|
39
|
-
|
40
|
-
|
41
|
-
def template_dir
|
42
|
-
File.join(base_dir, 'templates')
|
42
|
+
@s3 == other.s3 &&
|
43
|
+
@compiler_options == other.compiler_options
|
43
44
|
end
|
44
45
|
|
45
46
|
def template_file_path
|
46
|
-
File.join(template_dir, template)
|
47
|
+
File.expand_path(File.join(template_dir, template))
|
47
48
|
end
|
48
49
|
|
49
50
|
def files_dir
|
@@ -2,10 +2,10 @@ module StackMaster
|
|
2
2
|
class TemplateCompiler
|
3
3
|
TemplateCompilationFailed = Class.new(RuntimeError)
|
4
4
|
|
5
|
-
def self.compile(config, template_file_path)
|
5
|
+
def self.compile(config, template_file_path, compiler_options = {})
|
6
6
|
compiler = template_compiler_for_file(template_file_path, config)
|
7
7
|
compiler.require_dependencies
|
8
|
-
compiler.compile(template_file_path)
|
8
|
+
compiler.compile(template_file_path, compiler_options)
|
9
9
|
rescue
|
10
10
|
raise TemplateCompilationFailed.new("Failed to compile #{template_file_path}.")
|
11
11
|
end
|
@@ -4,10 +4,10 @@ module StackMaster::TemplateCompilers
|
|
4
4
|
require 'cfndsl'
|
5
5
|
end
|
6
6
|
|
7
|
-
def self.compile(template_file_path)
|
7
|
+
def self.compile(template_file_path, compiler_options = {})
|
8
8
|
::CfnDsl.eval_file_with_extras(template_file_path).to_json
|
9
9
|
end
|
10
10
|
|
11
11
|
StackMaster::TemplateCompiler.register(:cfndsl, self)
|
12
12
|
end
|
13
|
-
end
|
13
|
+
end
|
@@ -7,7 +7,7 @@ module StackMaster::TemplateCompilers
|
|
7
7
|
require 'json'
|
8
8
|
end
|
9
9
|
|
10
|
-
def self.compile(template_file_path)
|
10
|
+
def self.compile(template_file_path, compiler_options = {})
|
11
11
|
template_body = File.read(template_file_path)
|
12
12
|
if template_body.size > MAX_TEMPLATE_SIZE
|
13
13
|
# Parse the json and rewrite compressed
|
@@ -19,4 +19,4 @@ module StackMaster::TemplateCompilers
|
|
19
19
|
|
20
20
|
StackMaster::TemplateCompiler.register(:json, self)
|
21
21
|
end
|
22
|
-
end
|
22
|
+
end
|
@@ -5,11 +5,16 @@ module StackMaster::TemplateCompilers
|
|
5
5
|
require 'stack_master/sparkle_formation/template_file'
|
6
6
|
end
|
7
7
|
|
8
|
-
def self.compile(template_file_path)
|
9
|
-
|
8
|
+
def self.compile(template_file_path, compiler_options = {})
|
9
|
+
if compiler_options["sparkle_path"]
|
10
|
+
::SparkleFormation.sparkle_path = File.expand_path(compiler_options["sparkle_path"])
|
11
|
+
else
|
12
|
+
::SparkleFormation.sparkle_path = File.dirname(template_file_path)
|
13
|
+
end
|
14
|
+
|
10
15
|
JSON.pretty_generate(::SparkleFormation.compile(template_file_path))
|
11
16
|
end
|
12
17
|
|
13
18
|
StackMaster::TemplateCompiler.register(:sparkle_formation, self)
|
14
19
|
end
|
15
|
-
end
|
20
|
+
end
|
@@ -11,7 +11,7 @@ module StackMaster
|
|
11
11
|
|
12
12
|
def perform
|
13
13
|
StackMaster.stdout.print "#{@stack_definition.stack_name}: "
|
14
|
-
template_body = TemplateCompiler.compile(@config, @stack_definition.template_file_path)
|
14
|
+
template_body = TemplateCompiler.compile(@config, @stack_definition.template_file_path, @stack_definition.compiler_options)
|
15
15
|
cf.validate_template(template_body: TemplateUtils.maybe_compressed_template_body(template_body))
|
16
16
|
StackMaster.stdout.puts "valid"
|
17
17
|
true
|
data/lib/stack_master/version.rb
CHANGED
@@ -87,7 +87,7 @@ RSpec.describe StackMaster::Stack do
|
|
87
87
|
before do
|
88
88
|
allow(StackMaster::ParameterLoader).to receive(:load).and_return(parameter_hash)
|
89
89
|
allow(StackMaster::ParameterResolver).to receive(:resolve).and_return(resolved_parameters)
|
90
|
-
allow(StackMaster::TemplateCompiler).to receive(:compile).with(config, stack_definition.template_file_path).and_return(template_body)
|
90
|
+
allow(StackMaster::TemplateCompiler).to receive(:compile).with(config, stack_definition.template_file_path, stack_definition.compiler_options).and_return(template_body)
|
91
91
|
allow(File).to receive(:read).with(stack_definition.stack_policy_file_path).and_return(stack_policy_body)
|
92
92
|
end
|
93
93
|
|
@@ -5,7 +5,7 @@ RSpec.describe StackMaster::TemplateCompiler do
|
|
5
5
|
|
6
6
|
class TestTemplateCompiler
|
7
7
|
def self.require_dependencies; end
|
8
|
-
def self.compile(template_file_path); end
|
8
|
+
def self.compile(template_file_path, compile_options); end
|
9
9
|
end
|
10
10
|
|
11
11
|
context 'when a template compiler is registered for the given file type' do
|
@@ -14,10 +14,16 @@ RSpec.describe StackMaster::TemplateCompiler do
|
|
14
14
|
}
|
15
15
|
|
16
16
|
it 'compiles the template using the relevant template compiler' do
|
17
|
-
expect(TestTemplateCompiler).to receive(:compile).with(template_file_path)
|
17
|
+
expect(TestTemplateCompiler).to receive(:compile).with(template_file_path, anything)
|
18
18
|
StackMaster::TemplateCompiler.compile(config, template_file_path)
|
19
19
|
end
|
20
20
|
|
21
|
+
it 'passes compile_options to the template compiler' do
|
22
|
+
opts = {foo: 1, bar: true, baz: "meh"}
|
23
|
+
expect(TestTemplateCompiler).to receive(:compile).with(template_file_path, opts)
|
24
|
+
StackMaster::TemplateCompiler.compile(config, template_file_path, opts)
|
25
|
+
end
|
26
|
+
|
21
27
|
context 'when template compilation fails' do
|
22
28
|
before { allow(TestTemplateCompiler).to receive(:compile).and_raise(RuntimeError) }
|
23
29
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
RSpec.describe StackMaster::TemplateCompilers::SparkleFormation do
|
2
2
|
describe '.compile' do
|
3
3
|
def compile
|
4
|
-
described_class.compile(template_file_path)
|
4
|
+
described_class.compile(template_file_path, compiler_options)
|
5
5
|
end
|
6
6
|
|
7
7
|
before do
|
@@ -9,6 +9,7 @@ RSpec.describe StackMaster::TemplateCompilers::SparkleFormation do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
let(:template_file_path) { '/base_dir/templates/template.rb' }
|
12
|
+
let(:compiler_options) { {} }
|
12
13
|
|
13
14
|
it 'compiles with sparkleformation' do
|
14
15
|
expect(compile).to eq("{\n}")
|
@@ -18,5 +19,19 @@ RSpec.describe StackMaster::TemplateCompilers::SparkleFormation do
|
|
18
19
|
compile
|
19
20
|
expect(SparkleFormation.sparkle_path).to eq File.dirname(template_file_path)
|
20
21
|
end
|
22
|
+
|
23
|
+
context 'with a custom sparkle_path' do
|
24
|
+
let(:compiler_options) { { "sparkle_path" => '../foo' } }
|
25
|
+
|
26
|
+
it 'does not use the default path' do
|
27
|
+
compile
|
28
|
+
expect(SparkleFormation.sparkle_path).to_not eq File.dirname(template_file_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'expands the given path' do
|
32
|
+
compile
|
33
|
+
expect(SparkleFormation.sparkle_path).to match %r{^/.+/foo}
|
34
|
+
end
|
35
|
+
end
|
21
36
|
end
|
22
|
-
end
|
37
|
+
end
|
data/stack_master.gemspec
CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_dependency "erubis"
|
34
34
|
spec.add_dependency "colorize"
|
35
35
|
spec.add_dependency "activesupport", "~> 4.2"
|
36
|
-
spec.add_dependency "sparkle_formation"
|
36
|
+
spec.add_dependency "sparkle_formation"
|
37
37
|
spec.add_dependency "table_print"
|
38
38
|
spec.add_dependency "dotgpg"
|
39
39
|
spec.add_dependency "deep_merge"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stack_master
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Hodgkiss
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-04-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -211,16 +211,16 @@ dependencies:
|
|
211
211
|
name: sparkle_formation
|
212
212
|
requirement: !ruby/object:Gem::Requirement
|
213
213
|
requirements:
|
214
|
-
- - "
|
214
|
+
- - ">="
|
215
215
|
- !ruby/object:Gem::Version
|
216
|
-
version: '
|
216
|
+
version: '0'
|
217
217
|
type: :runtime
|
218
218
|
prerelease: false
|
219
219
|
version_requirements: !ruby/object:Gem::Requirement
|
220
220
|
requirements:
|
221
|
-
- - "
|
221
|
+
- - ">="
|
222
222
|
- !ruby/object:Gem::Version
|
223
|
-
version: '
|
223
|
+
version: '0'
|
224
224
|
- !ruby/object:Gem::Dependency
|
225
225
|
name: table_print
|
226
226
|
requirement: !ruby/object:Gem::Requirement
|
@@ -450,7 +450,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
450
450
|
version: '0'
|
451
451
|
requirements: []
|
452
452
|
rubyforge_project:
|
453
|
-
rubygems_version: 2.6.
|
453
|
+
rubygems_version: 2.6.11
|
454
454
|
signing_key:
|
455
455
|
specification_version: 4
|
456
456
|
summary: StackMaster is a sure-footed way of creating, updating and keeping track
|