paratrooper 0.0.5 → 0.4.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.
- 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
|
+
[](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:
|