paratrooper 0.0.5 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +9 -5
- data/README.md +2 -0
- data/lib/paratrooper/default_formatter.rb +13 -5
- data/lib/paratrooper/deploy.rb +6 -26
- data/lib/paratrooper/heroku_wrapper.rb +40 -0
- data/lib/paratrooper/local_api_key_extractor.rb +33 -0
- data/lib/paratrooper/version.rb +1 -1
- data/paratrooper.gemspec +4 -2
- data/spec/fixtures/netrc +6 -0
- data/spec/paratrooper/default_formatter_spec.rb +24 -0
- data/spec/paratrooper/deploy_spec.rb +8 -7
- data/spec/paratrooper/heroku_wrapper_spec.rb +71 -0
- data/spec/paratrooper/local_api_key_extractor_spec.rb +48 -0
- data/spec/spec_helper.rb +4 -0
- metadata +50 -7
data/Gemfile.lock
CHANGED
@@ -1,22 +1,25 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
paratrooper (0.0
|
5
|
-
heroku-api
|
4
|
+
paratrooper (0.3.0)
|
5
|
+
heroku-api (~> 0.3)
|
6
|
+
netrc (~> 0.7)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: http://rubygems.org/
|
9
10
|
specs:
|
10
11
|
coderay (1.0.8)
|
11
12
|
diff-lcs (1.1.3)
|
12
|
-
excon (0.16.
|
13
|
-
heroku-api (0.3.
|
14
|
-
excon (~> 0.16.
|
13
|
+
excon (0.16.10)
|
14
|
+
heroku-api (0.3.7)
|
15
|
+
excon (~> 0.16.10)
|
15
16
|
method_source (0.8.1)
|
17
|
+
netrc (0.7.7)
|
16
18
|
pry (0.9.10)
|
17
19
|
coderay (~> 1.0.5)
|
18
20
|
method_source (~> 0.8)
|
19
21
|
slop (~> 3.3.1)
|
22
|
+
rake (10.0.3)
|
20
23
|
rspec (2.12.0)
|
21
24
|
rspec-core (~> 2.12.0)
|
22
25
|
rspec-expectations (~> 2.12.0)
|
@@ -33,4 +36,5 @@ PLATFORMS
|
|
33
36
|
DEPENDENCIES
|
34
37
|
paratrooper!
|
35
38
|
pry
|
39
|
+
rake
|
36
40
|
rspec (~> 2.12)
|
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
Library for handling common tasks when deploying to [Heroku](http://heroku.com)
|
4
4
|
|
5
|
+
[![Build Status](https://travis-ci.org/mattpolito/paratrooper.png?branch=master)](https://travis-ci.org/mattpolito/paratrooper)
|
6
|
+
|
5
7
|
## Installation
|
6
8
|
|
7
9
|
Add this line to your application's Gemfile:
|
@@ -1,11 +1,19 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
1
3
|
module Paratrooper
|
2
4
|
class DefaultFormatter
|
5
|
+
attr_reader :output
|
6
|
+
|
7
|
+
def initialize(output = StringIO.new)
|
8
|
+
@output = output
|
9
|
+
end
|
10
|
+
|
3
11
|
def display(message)
|
4
|
-
puts
|
5
|
-
puts "=" * 80
|
6
|
-
puts ">> #{message}"
|
7
|
-
puts "=" * 80
|
8
|
-
puts
|
12
|
+
output.puts
|
13
|
+
output.puts "=" * 80
|
14
|
+
output.puts ">> #{message}"
|
15
|
+
output.puts "=" * 80
|
16
|
+
output.puts
|
9
17
|
end
|
10
18
|
end
|
11
19
|
end
|
data/lib/paratrooper/deploy.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'paratrooper/heroku_wrapper'
|
2
2
|
require 'paratrooper/default_formatter'
|
3
3
|
require 'paratrooper/system_caller'
|
4
4
|
|
@@ -9,19 +9,19 @@ module Paratrooper
|
|
9
9
|
def initialize(app_name, options = {})
|
10
10
|
@app_name = app_name
|
11
11
|
@formatter = options[:formatter] || DefaultFormatter.new
|
12
|
-
@heroku = options[:
|
12
|
+
@heroku = options[:heroku] || HerokuWrapper.new(app_name, options)
|
13
13
|
@tag_name = options[:tag]
|
14
14
|
@system_caller = options[:system_caller] || SystemCaller.new
|
15
15
|
end
|
16
16
|
|
17
17
|
def activate_maintenance_mode
|
18
18
|
notify_screen("Activating Maintenance Mode")
|
19
|
-
app_maintenance_on
|
19
|
+
heroku.app_maintenance_on
|
20
20
|
end
|
21
21
|
|
22
22
|
def deactivate_maintenance_mode
|
23
23
|
notify_screen("Deactivating Maintenance Mode")
|
24
|
-
app_maintenance_off
|
24
|
+
heroku.app_maintenance_off
|
25
25
|
end
|
26
26
|
|
27
27
|
def update_repo_tag
|
@@ -44,7 +44,7 @@ module Paratrooper
|
|
44
44
|
|
45
45
|
def app_restart
|
46
46
|
notify_screen("Restarting application")
|
47
|
-
|
47
|
+
heroku.app_restart
|
48
48
|
end
|
49
49
|
|
50
50
|
def warm_instance(wait_time = 3)
|
@@ -65,28 +65,8 @@ module Paratrooper
|
|
65
65
|
alias_method :deploy, :default_deploy
|
66
66
|
|
67
67
|
private
|
68
|
-
def _app_maintenance(flag)
|
69
|
-
heroku.post_app_maintenance(app_name, flag)
|
70
|
-
end
|
71
|
-
|
72
|
-
def _app_restart
|
73
|
-
heroku.post_ps_restart(app_name)
|
74
|
-
end
|
75
|
-
|
76
|
-
def _app_domain_name
|
77
|
-
heroku.get_domains(app_name).body.last['domain']
|
78
|
-
end
|
79
|
-
|
80
|
-
def app_maintenance_off
|
81
|
-
_app_maintenance('0')
|
82
|
-
end
|
83
|
-
|
84
|
-
def app_maintenance_on
|
85
|
-
_app_maintenance('1')
|
86
|
-
end
|
87
|
-
|
88
68
|
def app_url
|
89
|
-
|
69
|
+
heroku.app_url
|
90
70
|
end
|
91
71
|
|
92
72
|
def git_remote
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'heroku-api'
|
2
|
+
require 'paratrooper/local_api_key_extractor'
|
3
|
+
|
4
|
+
module Paratrooper
|
5
|
+
class HerokuWrapper
|
6
|
+
attr_reader :api_key, :app_name, :heroku_api, :key_extractor
|
7
|
+
|
8
|
+
def initialize(app_name, options = {})
|
9
|
+
@app_name = app_name
|
10
|
+
@key_extractor = options[:key_extractor] || LocalApiKeyExtractor
|
11
|
+
@api_key = options[:api_key] || key_extractor.get_credentials
|
12
|
+
@heroku_api = options[:heroku_api] || Heroku::API.new(api_key: api_key)
|
13
|
+
end
|
14
|
+
|
15
|
+
def app_restart
|
16
|
+
heroku_api.post_ps_restart(app_name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def app_maintenance_off
|
20
|
+
app_maintenance('0')
|
21
|
+
end
|
22
|
+
|
23
|
+
def app_maintenance_on
|
24
|
+
app_maintenance('1')
|
25
|
+
end
|
26
|
+
|
27
|
+
def app_url
|
28
|
+
app_domain_name
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def app_domain_name
|
33
|
+
heroku_api.get_domains(app_name).body.last['domain']
|
34
|
+
end
|
35
|
+
|
36
|
+
def app_maintenance(flag)
|
37
|
+
heroku_api.post_app_maintenance(app_name, flag)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'netrc'
|
2
|
+
|
3
|
+
module Paratrooper
|
4
|
+
class LocalApiKeyExtractor
|
5
|
+
attr_reader :file_path, :netrc_klass
|
6
|
+
|
7
|
+
def self.get_credentials
|
8
|
+
new.read_credentials
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@netrc_klass = options[:netrc_klass] || Netrc
|
13
|
+
@file_path = options[:file_path] || netrc_klass.default_path
|
14
|
+
end
|
15
|
+
|
16
|
+
def read_credentials
|
17
|
+
ENV['HEROKU_API_KEY'] || read_credentials_for('api.heroku.com')
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def netrc
|
22
|
+
@netrc ||= begin
|
23
|
+
File.exists?(file_path) && Netrc.read(file_path)
|
24
|
+
rescue => error
|
25
|
+
raise error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def read_credentials_for(domain)
|
30
|
+
netrc[domain][1]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/paratrooper/version.rb
CHANGED
data/paratrooper.gemspec
CHANGED
@@ -10,14 +10,16 @@ Gem::Specification.new do |gem|
|
|
10
10
|
gem.email = ['matt.polito@gmail.com', 'bthesorceror@gmail.com']
|
11
11
|
gem.description = %q{Library to create task for deployment to Heroku}
|
12
12
|
gem.summary = %q{Library to create task for deployment to Heroku}
|
13
|
-
gem.homepage = "http://github.com/
|
13
|
+
gem.homepage = "http://github.com/mattpolito/paratrooper"
|
14
14
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
16
16
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
|
+
gem.add_development_dependency 'rake'
|
20
21
|
gem.add_development_dependency 'rspec', '~> 2.12'
|
21
22
|
gem.add_development_dependency 'pry'
|
22
|
-
gem.add_dependency 'heroku-api'
|
23
|
+
gem.add_dependency 'heroku-api', '~> 0.3'
|
24
|
+
gem.add_dependency 'netrc', '~> 0.7'
|
23
25
|
end
|
data/spec/fixtures/netrc
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'paratrooper/default_formatter'
|
3
|
+
|
4
|
+
describe Paratrooper::DefaultFormatter do
|
5
|
+
let(:formatter) { described_class.new(output_stub) }
|
6
|
+
let(:output_stub) { StringIO.new }
|
7
|
+
|
8
|
+
describe "#display(message)" do
|
9
|
+
it "outputs _message_ to screen" do
|
10
|
+
expected_output = <<-EXPECTED_OUTPUT.gsub(/^ {8}/, '')
|
11
|
+
|
12
|
+
#{'=' * 80}
|
13
|
+
>> MESSAGE
|
14
|
+
#{'=' * 80}
|
15
|
+
|
16
|
+
EXPECTED_OUTPUT
|
17
|
+
|
18
|
+
formatter.display('MESSAGE')
|
19
|
+
output_stub.seek(0)
|
20
|
+
|
21
|
+
expect(output_stub.read).to eq(expected_output)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -8,7 +8,7 @@ describe Paratrooper::Deploy do
|
|
8
8
|
let(:app_name) { 'app' }
|
9
9
|
let(:default_options) do
|
10
10
|
{
|
11
|
-
|
11
|
+
heroku: heroku,
|
12
12
|
formatter: formatter,
|
13
13
|
system_caller: system_caller
|
14
14
|
}
|
@@ -16,9 +16,10 @@ describe Paratrooper::Deploy do
|
|
16
16
|
let(:options) { Hash.new }
|
17
17
|
let(:heroku) do
|
18
18
|
double(:heroku,
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
app_url: 'application_url',
|
20
|
+
app_restart: true,
|
21
|
+
app_maintenance_on: true,
|
22
|
+
app_maintenance_off: true,
|
22
23
|
)
|
23
24
|
end
|
24
25
|
let(:formatter) { double(:formatter, puts: '') }
|
@@ -69,7 +70,7 @@ describe Paratrooper::Deploy do
|
|
69
70
|
end
|
70
71
|
|
71
72
|
it "makes call to heroku to turn on maintenance mode" do
|
72
|
-
heroku.should_receive(:
|
73
|
+
heroku.should_receive(:app_maintenance_on)
|
73
74
|
deployer.activate_maintenance_mode
|
74
75
|
end
|
75
76
|
end
|
@@ -85,7 +86,7 @@ describe Paratrooper::Deploy do
|
|
85
86
|
end
|
86
87
|
|
87
88
|
it "makes call to heroku to turn on maintenance mode" do
|
88
|
-
heroku.should_receive(:
|
89
|
+
heroku.should_receive(:app_maintenance_off)
|
89
90
|
deployer.deactivate_maintenance_mode
|
90
91
|
end
|
91
92
|
end
|
@@ -172,7 +173,7 @@ describe Paratrooper::Deploy do
|
|
172
173
|
end
|
173
174
|
|
174
175
|
it 'restarts your heroku instance' do
|
175
|
-
heroku.should_receive(:
|
176
|
+
heroku.should_receive(:app_restart)
|
176
177
|
deployer.app_restart
|
177
178
|
end
|
178
179
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'paratrooper/heroku_wrapper'
|
3
|
+
|
4
|
+
describe Paratrooper::HerokuWrapper do
|
5
|
+
let(:wrapper) do
|
6
|
+
described_class.new(app_name, default_options.merge(options))
|
7
|
+
end
|
8
|
+
let(:app_name) { 'app_name' }
|
9
|
+
let(:options) { Hash.new }
|
10
|
+
let(:default_options) do
|
11
|
+
{
|
12
|
+
heroku_api: heroku_api
|
13
|
+
}
|
14
|
+
end
|
15
|
+
let(:heroku_api) { double(:heroku_api) }
|
16
|
+
|
17
|
+
describe '#api_key' do
|
18
|
+
context 'when api_key is provided as an option' do
|
19
|
+
let(:options) do
|
20
|
+
{
|
21
|
+
api_key: 'PROVIDED_API_KEY'
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns provided api key' do
|
26
|
+
expect(wrapper.api_key).to eq('PROVIDED_API_KEY')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when no key is provided' do
|
31
|
+
let(:options) do
|
32
|
+
{
|
33
|
+
key_extractor: double(:key_extractor, get_credentials: 'NETRC_API_KEY')
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns api key from locally stored file' do
|
38
|
+
expect(wrapper.api_key).to eq('NETRC_API_KEY')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#app_restart' do
|
44
|
+
it "calls down to heroku api" do
|
45
|
+
heroku_api.should_receive(:post_ps_restart).with(app_name)
|
46
|
+
wrapper.app_restart
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#app_maintenance_off' do
|
51
|
+
it "calls down to heroku api" do
|
52
|
+
heroku_api.should_receive(:post_app_maintenance).with(app_name, '0')
|
53
|
+
wrapper.app_maintenance_off
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#app_maintenance_on' do
|
58
|
+
it "calls down to heroku api" do
|
59
|
+
heroku_api.should_receive(:post_app_maintenance).with(app_name, '1')
|
60
|
+
wrapper.app_maintenance_on
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#app_domain_name' do
|
65
|
+
let(:response) { double(:response, body: [{'domain' => 'APP_URL'}]) }
|
66
|
+
it "calls down to heroku api" do
|
67
|
+
heroku_api.should_receive(:get_domains).with(app_name).and_return(response)
|
68
|
+
wrapper.app_url
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'paratrooper/local_api_key_extractor'
|
3
|
+
|
4
|
+
describe Paratrooper::LocalApiKeyExtractor do
|
5
|
+
let(:netrc_klass) { double(:netrc_klass, default_path: fixture_file_path) }
|
6
|
+
let(:fixture_file_path) { fixture_path('netrc') }
|
7
|
+
|
8
|
+
describe 'file association' do
|
9
|
+
context 'when file path is provided' do
|
10
|
+
let(:extractor) { described_class.new(file_path: fixture_file_path) }
|
11
|
+
|
12
|
+
it 'uses provided file path' do
|
13
|
+
expect(extractor.file_path).to eq(fixture_file_path)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when file path is not provided' do
|
18
|
+
let(:extractor) { described_class.new(netrc_klass: netrc_klass) }
|
19
|
+
|
20
|
+
it 'uses default path' do
|
21
|
+
expect(extractor.file_path).to eq(netrc_klass.default_path)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#read_credentials' do
|
27
|
+
let(:extractor) { described_class.new(netrc_klass: netrc_klass) }
|
28
|
+
|
29
|
+
context 'when environment variable is set' do
|
30
|
+
before do
|
31
|
+
ENV.stub(:[]).with('HEROKU_API_KEY').and_return('ENV_API_KEY')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns credentials' do
|
35
|
+
expect(extractor.read_credentials).to eq('ENV_API_KEY')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when environment variable is not set' do
|
40
|
+
before do
|
41
|
+
ENV.stub(:[]).with('HEROKU_API_KEY').and_return(nil)
|
42
|
+
end
|
43
|
+
it 'returns credentials from local file' do
|
44
|
+
expect(extractor.read_credentials).to eq('LOCAL_API_KEY')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paratrooper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,8 +10,24 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-02-05 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rake
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0'
|
15
31
|
- !ruby/object:Gem::Dependency
|
16
32
|
name: rspec
|
17
33
|
requirement: !ruby/object:Gem::Requirement
|
@@ -49,17 +65,33 @@ dependencies:
|
|
49
65
|
requirement: !ruby/object:Gem::Requirement
|
50
66
|
none: false
|
51
67
|
requirements:
|
52
|
-
- -
|
68
|
+
- - ~>
|
53
69
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
70
|
+
version: '0.3'
|
55
71
|
type: :runtime
|
56
72
|
prerelease: false
|
57
73
|
version_requirements: !ruby/object:Gem::Requirement
|
58
74
|
none: false
|
59
75
|
requirements:
|
60
|
-
- -
|
76
|
+
- - ~>
|
61
77
|
- !ruby/object:Gem::Version
|
62
|
-
version: '0'
|
78
|
+
version: '0.3'
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: netrc
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ~>
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0.7'
|
87
|
+
type: :runtime
|
88
|
+
prerelease: false
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ~>
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0.7'
|
63
95
|
description: Library to create task for deployment to Heroku
|
64
96
|
email:
|
65
97
|
- matt.polito@gmail.com
|
@@ -77,12 +109,18 @@ files:
|
|
77
109
|
- lib/paratrooper.rb
|
78
110
|
- lib/paratrooper/default_formatter.rb
|
79
111
|
- lib/paratrooper/deploy.rb
|
112
|
+
- lib/paratrooper/heroku_wrapper.rb
|
113
|
+
- lib/paratrooper/local_api_key_extractor.rb
|
80
114
|
- lib/paratrooper/system_caller.rb
|
81
115
|
- lib/paratrooper/version.rb
|
82
116
|
- paratrooper.gemspec
|
117
|
+
- spec/fixtures/netrc
|
118
|
+
- spec/paratrooper/default_formatter_spec.rb
|
83
119
|
- spec/paratrooper/deploy_spec.rb
|
120
|
+
- spec/paratrooper/heroku_wrapper_spec.rb
|
121
|
+
- spec/paratrooper/local_api_key_extractor_spec.rb
|
84
122
|
- spec/spec_helper.rb
|
85
|
-
homepage: http://github.com/
|
123
|
+
homepage: http://github.com/mattpolito/paratrooper
|
86
124
|
licenses: []
|
87
125
|
post_install_message:
|
88
126
|
rdoc_options: []
|
@@ -107,5 +145,10 @@ signing_key:
|
|
107
145
|
specification_version: 3
|
108
146
|
summary: Library to create task for deployment to Heroku
|
109
147
|
test_files:
|
148
|
+
- spec/fixtures/netrc
|
149
|
+
- spec/paratrooper/default_formatter_spec.rb
|
110
150
|
- spec/paratrooper/deploy_spec.rb
|
151
|
+
- spec/paratrooper/heroku_wrapper_spec.rb
|
152
|
+
- spec/paratrooper/local_api_key_extractor_spec.rb
|
111
153
|
- spec/spec_helper.rb
|
154
|
+
has_rdoc:
|