beanstalkify 0.0.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.
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +34 -0
- data/LICENSE +13 -0
- data/README.md +58 -0
- data/Rakefile +1 -0
- data/beanstalkify.gemspec +21 -0
- data/bin/beanstalkify +35 -0
- data/lib/beanstalkify/application.rb +38 -0
- data/lib/beanstalkify/archive.rb +22 -0
- data/lib/beanstalkify/beanstalk.rb +15 -0
- data/lib/beanstalkify/deploy.rb +49 -0
- data/lib/beanstalkify/environment.rb +60 -0
- data/lib/beanstalkify/version.rb +3 -0
- data/test/application_spec.rb +9 -0
- data/test/archive_spec.rb +26 -0
- data/test/deploy_spec.rb +24 -0
- data/test/environment_spec.rb +9 -0
- metadata +101 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
beanstalkify (0.0.1)
|
5
|
+
aws-sdk
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
aws-sdk (1.14.1)
|
11
|
+
json (~> 1.4)
|
12
|
+
nokogiri (< 1.6.0)
|
13
|
+
uuidtools (~> 2.1)
|
14
|
+
diff-lcs (1.2.4)
|
15
|
+
json (1.8.0)
|
16
|
+
nokogiri (1.5.10)
|
17
|
+
rake (10.0.3)
|
18
|
+
rspec (2.14.1)
|
19
|
+
rspec-core (~> 2.14.0)
|
20
|
+
rspec-expectations (~> 2.14.0)
|
21
|
+
rspec-mocks (~> 2.14.0)
|
22
|
+
rspec-core (2.14.4)
|
23
|
+
rspec-expectations (2.14.0)
|
24
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
25
|
+
rspec-mocks (2.14.2)
|
26
|
+
uuidtools (2.1.4)
|
27
|
+
|
28
|
+
PLATFORMS
|
29
|
+
ruby
|
30
|
+
|
31
|
+
DEPENDENCIES
|
32
|
+
beanstalkify!
|
33
|
+
rake
|
34
|
+
rspec
|
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2013 Pranav Raja.
|
2
|
+
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
[AWS Elastic Beanstalk](http://aws.amazon.com/elasticbeanstalk/) automation. A work in progress.
|
3
|
+
|
4
|
+
# Prerequisites
|
5
|
+
|
6
|
+
- Ruby 1.9
|
7
|
+
|
8
|
+
# Installation
|
9
|
+
|
10
|
+
gem install beanstalkify
|
11
|
+
|
12
|
+
Create a file called `credentials.yml`, with the following format:
|
13
|
+
|
14
|
+
access_key_id: A98KJHBLABLABLA
|
15
|
+
secret_access_key: dkuU90kmySuperSecretKey
|
16
|
+
region: us-east-1
|
17
|
+
|
18
|
+
# Running
|
19
|
+
|
20
|
+
beanstalkify -k credentials.yml -a app-version.zip -s "64bit Amazon Linux running Node.js" -e env [-c config.yml]
|
21
|
+
|
22
|
+
Should do the following
|
23
|
+
|
24
|
+
- Connect to aws using the credentials in `credentials.yml`
|
25
|
+
- Publish `app-version.zip` to s3
|
26
|
+
- Ensure that a beanstalk application called 'app' exists, and add a version called 'version', linked to the archive in that s3 bucket
|
27
|
+
- Ensure that the environment `env` exists (with optional settings overrides in `config.yml` - see below), running the specified stack.
|
28
|
+
- Deploy the provided version of the application into `env`
|
29
|
+
- Report progress. When complete report the URL where the app can be hit (note: this will be the URL of the ELB).
|
30
|
+
|
31
|
+
# Settings overrides
|
32
|
+
|
33
|
+
An example `config.yml`:
|
34
|
+
|
35
|
+
```yaml
|
36
|
+
-
|
37
|
+
namespace: 'aws:autoscaling:asg'
|
38
|
+
option_name: Availability Zones
|
39
|
+
value: Any 2
|
40
|
+
-
|
41
|
+
namespace: 'aws:autoscaling:launchconfiguration'
|
42
|
+
option_name: InstanceType
|
43
|
+
value: m1.small
|
44
|
+
-
|
45
|
+
namespace: 'aws:autoscaling:launchconfiguration'
|
46
|
+
option_name: EC2KeyName
|
47
|
+
value: MyAwesomeEC2-dev
|
48
|
+
```
|
49
|
+
|
50
|
+
# Running the somewhat useless tests
|
51
|
+
|
52
|
+
bundle exec rspec test
|
53
|
+
|
54
|
+
# TODO
|
55
|
+
|
56
|
+
- Tests around error handling
|
57
|
+
- Provide some blue-green deployment integrated with health checks, using the `swap_environment_cnames` feature of the AWS SDK.
|
58
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require 'beanstalkify/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'beanstalkify'
|
7
|
+
s.version = Beanstalkify::VERSION
|
8
|
+
s.summary = "Beanstalk automation for dummies"
|
9
|
+
s.description = "Create Amazon Elastic Beanstalk apps and deploy versions from the command line"
|
10
|
+
s.authors = ["Pranav Raja"]
|
11
|
+
s.email = 'rickdangerous1@gmail.com'
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.homepage = 'https://github.com/pranavraja/beanstalkify'
|
17
|
+
s.license = 'MIT'
|
18
|
+
|
19
|
+
s.add_dependency 'aws-sdk'
|
20
|
+
s.add_development_dependency "rspec"
|
21
|
+
end
|
data/bin/beanstalkify
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'yaml'
|
4
|
+
require 'beanstalkify/beanstalk'
|
5
|
+
require 'beanstalkify/application'
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.on("-k", "--keyfile [file]", "Load credentials from yaml file") do |v|
|
10
|
+
options[:credentials] = YAML.load_file(v)
|
11
|
+
end
|
12
|
+
opts.on("-a", "--archive [file]", "Archive to deploy (e.g. AppName-version.zip)") do |v|
|
13
|
+
options[:archive] = v
|
14
|
+
end
|
15
|
+
opts.on("-e", "--environment [env]", "Environment to provision (e.g. AppName-test)") do |v|
|
16
|
+
options[:environment] = v
|
17
|
+
end
|
18
|
+
opts.on("-s", "--stack [stack]", "Stack to provision (e.g. '64bit Amazon Linux running Node.js')") do |v|
|
19
|
+
options[:stack] = v
|
20
|
+
end
|
21
|
+
opts.on("-c", "--config [file]", "Configuration overrides for the environment") do |v|
|
22
|
+
options[:config] = YAML.load_file(v)
|
23
|
+
end
|
24
|
+
end.parse!
|
25
|
+
|
26
|
+
required_params = [:credentials, :archive, :environment, :stack]
|
27
|
+
unless (required_params - options.keys).empty?
|
28
|
+
puts "Example usage: beanstalkify -k credentials.yml -a AppName-version.zip -e AppName-test -s '64bit Amazon Linux running Node.js' -c config.yml"
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
|
32
|
+
Beanstalkify::Beanstalk.configure! options[:credentials]
|
33
|
+
app = Beanstalkify::Application.new(options[:stack], options[:config] || [])
|
34
|
+
app.deploy!(options[:archive], options[:environment])
|
35
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'beanstalkify/environment'
|
2
|
+
require 'beanstalkify/deploy'
|
3
|
+
|
4
|
+
module Beanstalkify
|
5
|
+
class Application
|
6
|
+
attr_accessor :stack, :config
|
7
|
+
|
8
|
+
# config is an array of hashes:
|
9
|
+
# :namespace, :option_name, :value
|
10
|
+
def initialize(stack, config)
|
11
|
+
@stack = stack
|
12
|
+
@config = config.map { |c| Hash[c.map { |k, v| [k.to_sym,v]}] }
|
13
|
+
end
|
14
|
+
|
15
|
+
# Deploy an archive to an environment.
|
16
|
+
# If the environment doesn't exist, it will be created.
|
17
|
+
def deploy!(archive, environment_name)
|
18
|
+
deployment = Deploy.new(archive)
|
19
|
+
env = Environment.new(environment_name)
|
20
|
+
if deployment.deployed?
|
21
|
+
puts "#{deployment.application.version} is already uploaded."
|
22
|
+
else
|
23
|
+
deployment.upload!
|
24
|
+
deployment.wait!
|
25
|
+
end
|
26
|
+
if env.status.empty?
|
27
|
+
puts "Creating stack '#{@stack}' for #{deployment.application.name}-#{deployment.application.version}..."
|
28
|
+
env.create!(deployment.application, @stack, @config)
|
29
|
+
env.wait!("Launching")
|
30
|
+
else
|
31
|
+
puts "Deploying #{deployment.application.version} to #{environment_name}..."
|
32
|
+
env.deploy!(deployment.application, @config)
|
33
|
+
env.wait!("Updating")
|
34
|
+
end
|
35
|
+
puts "Done. Visit http://#{env.url} in your browser."
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
module Beanstalkify
|
3
|
+
class Archive
|
4
|
+
attr_accessor :path
|
5
|
+
|
6
|
+
def initialize(path)
|
7
|
+
@path = path
|
8
|
+
end
|
9
|
+
|
10
|
+
def name
|
11
|
+
filename.split('-')[0]
|
12
|
+
end
|
13
|
+
|
14
|
+
def version
|
15
|
+
File.basename(@path, '.*').split('-')[-1]
|
16
|
+
end
|
17
|
+
|
18
|
+
def filename
|
19
|
+
File.basename(@path)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
|
3
|
+
module Beanstalkify
|
4
|
+
class Beanstalk
|
5
|
+
@@config = {}
|
6
|
+
def self.configure!(config={})
|
7
|
+
# Convert string keys to symbols
|
8
|
+
@@config = Hash[config.map{|(k,v)| [k.to_sym,v]}]
|
9
|
+
end
|
10
|
+
def self.api
|
11
|
+
AWS.config(@@config)
|
12
|
+
AWS::ElasticBeanstalk.new.client
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'beanstalkify/archive'
|
2
|
+
require 'beanstalkify/beanstalk'
|
3
|
+
require 'aws-sdk'
|
4
|
+
|
5
|
+
module Beanstalkify
|
6
|
+
class Deploy
|
7
|
+
attr_accessor :beanstalk, :application
|
8
|
+
|
9
|
+
def initialize(path)
|
10
|
+
@application = Archive.new(path)
|
11
|
+
@beanstalk = Beanstalk.api
|
12
|
+
end
|
13
|
+
|
14
|
+
def bucket
|
15
|
+
@beanstalk.create_storage_location.data[:s3_bucket]
|
16
|
+
end
|
17
|
+
|
18
|
+
def upload!
|
19
|
+
client = AWS::S3.new.client
|
20
|
+
bucket = self.bucket
|
21
|
+
puts "Uploading #{@application.filename} to bucket #{bucket}..."
|
22
|
+
client.put_object({ :bucket_name => bucket, :key => @application.filename, :data => File.open(@application.path) })
|
23
|
+
puts "Creating #{@application.name} - #{@application.version} in beanstalk"
|
24
|
+
@beanstalk.create_application_version({
|
25
|
+
:application_name => @application.name,
|
26
|
+
:version_label => @application.version,
|
27
|
+
:source_bundle => {
|
28
|
+
:s3_bucket => bucket,
|
29
|
+
:s3_key => @application.filename
|
30
|
+
},
|
31
|
+
:auto_create_application => true
|
32
|
+
})
|
33
|
+
end
|
34
|
+
|
35
|
+
def deployed?
|
36
|
+
@beanstalk.describe_application_versions({
|
37
|
+
:application_name => @application.name,
|
38
|
+
:version_labels => [@application.version]
|
39
|
+
}).data[:application_versions].count > 0
|
40
|
+
end
|
41
|
+
|
42
|
+
def wait!
|
43
|
+
while not self.deployed?
|
44
|
+
puts "Waiting for #{@application.version} to be available..."
|
45
|
+
sleep 10
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'beanstalkify/beanstalk'
|
2
|
+
|
3
|
+
module Beanstalkify
|
4
|
+
class Environment
|
5
|
+
attr_accessor :name
|
6
|
+
|
7
|
+
def initialize(name)
|
8
|
+
@name = name
|
9
|
+
@beanstalk = Beanstalk.api
|
10
|
+
end
|
11
|
+
|
12
|
+
# Assuming the provided app has already been uploaded,
|
13
|
+
# update this environment to the app's version
|
14
|
+
# Optionally pass in a bunch of settings to override
|
15
|
+
def deploy!(app, settings=[])
|
16
|
+
@beanstalk.update_environment({
|
17
|
+
:version_label => app.version,
|
18
|
+
:environment_name => self.name,
|
19
|
+
:option_settings => settings
|
20
|
+
})
|
21
|
+
end
|
22
|
+
|
23
|
+
# Assuming the app has already been uploaded,
|
24
|
+
# create a new environment with the app deployed onto the provided stack.
|
25
|
+
def create!(app, stack, settings=[])
|
26
|
+
@beanstalk.create_environment({
|
27
|
+
:application_name => app.name,
|
28
|
+
:version_label => app.version,
|
29
|
+
:environment_name => self.name,
|
30
|
+
:solution_stack_name => stack,
|
31
|
+
:option_settings => settings
|
32
|
+
})
|
33
|
+
end
|
34
|
+
|
35
|
+
def status
|
36
|
+
envs = @beanstalk.describe_environments({
|
37
|
+
:environment_names => [self.name],
|
38
|
+
:include_deleted => false
|
39
|
+
}).data[:environments]
|
40
|
+
e = envs.first
|
41
|
+
e ? e[:status] : ""
|
42
|
+
end
|
43
|
+
|
44
|
+
def url
|
45
|
+
envs = @beanstalk.describe_environments({
|
46
|
+
:environment_names => [self.name]
|
47
|
+
}).data[:environments]
|
48
|
+
e = envs.first
|
49
|
+
e ? e[:endpoint_url] : ""
|
50
|
+
end
|
51
|
+
|
52
|
+
# Wait for the status to change from `old_status` to something else
|
53
|
+
def wait!(old_status)
|
54
|
+
while self.status == old_status
|
55
|
+
puts "#{self.name} is still #{old_status}..."
|
56
|
+
sleep 20
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require './application'
|
2
|
+
require './environment'
|
3
|
+
|
4
|
+
describe Application do
|
5
|
+
it 'should deploy an application' do
|
6
|
+
#application = Application.new('64bit Amazon Linux running Node.js', [])
|
7
|
+
#application.deploy!('/Users/pmoney/tmp/App-64fc96e.zip', 'test-env')
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
require './archive'
|
3
|
+
|
4
|
+
describe Archive do
|
5
|
+
archive = nil
|
6
|
+
before do
|
7
|
+
archive = Archive.new '/path/to/my/archive/appname-version.zip'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should store the path' do
|
11
|
+
archive.path.should eq('/path/to/my/archive/appname-version.zip')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'extracts the application name from the path' do
|
15
|
+
archive.name.should eq('appname')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'extracts the version from the path' do
|
19
|
+
archive.version.should eq('version')
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns the filename of the archive' do
|
23
|
+
archive.filename.should eq('appname-version.zip')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
data/test/deploy_spec.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require './deploy'
|
2
|
+
|
3
|
+
describe Deploy do
|
4
|
+
deploy = nil
|
5
|
+
before do
|
6
|
+
deploy = Deploy.new('/Users/pmoney/temp/foo-1.0.zip')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should get the s3 bucket' do
|
10
|
+
#puts deploy.bucket
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should upload the application' do
|
14
|
+
#puts deploy.upload!
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should create a new environment with the application' do
|
18
|
+
#puts deploy.create!("test3", "64bit Amazon Linux running Node.js").data
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should get the status of an environment' do
|
22
|
+
#puts deploy.status("test3")
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: beanstalkify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Pranav Raja
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: aws-sdk
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Create Amazon Elastic Beanstalk apps and deploy versions from the command
|
47
|
+
line
|
48
|
+
email: rickdangerous1@gmail.com
|
49
|
+
executables:
|
50
|
+
- beanstalkify
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- .gitignore
|
55
|
+
- Gemfile
|
56
|
+
- Gemfile.lock
|
57
|
+
- LICENSE
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- beanstalkify.gemspec
|
61
|
+
- bin/beanstalkify
|
62
|
+
- lib/beanstalkify/application.rb
|
63
|
+
- lib/beanstalkify/archive.rb
|
64
|
+
- lib/beanstalkify/beanstalk.rb
|
65
|
+
- lib/beanstalkify/deploy.rb
|
66
|
+
- lib/beanstalkify/environment.rb
|
67
|
+
- lib/beanstalkify/version.rb
|
68
|
+
- test/application_spec.rb
|
69
|
+
- test/archive_spec.rb
|
70
|
+
- test/deploy_spec.rb
|
71
|
+
- test/environment_spec.rb
|
72
|
+
homepage: https://github.com/pranavraja/beanstalkify
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 1.8.24
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: Beanstalk automation for dummies
|
97
|
+
test_files:
|
98
|
+
- test/application_spec.rb
|
99
|
+
- test/archive_spec.rb
|
100
|
+
- test/deploy_spec.rb
|
101
|
+
- test/environment_spec.rb
|