renv 0.0.1 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e26c29836717d549fdf77aeb14b7532b0dc36f8c
4
- data.tar.gz: 0e2ec7d01003e5582aec6d90d2c1cce9ff508e19
3
+ metadata.gz: 2ce592555a68c352b441bafb892b77a01ff64d93
4
+ data.tar.gz: 424d50fc6061eea8ea4367930c74b503abb07fea
5
5
  SHA512:
6
- metadata.gz: 7b68c0ecca614b4c6e088a78e17d9f3e3343ad00d7b52711cfa83143b97c15eb53161cb2dc6ab16d2fb67215d77f55daf42fe5844acfc5b90079ef134bdf6c7e
7
- data.tar.gz: 9aa845d58d33b6700b4b1180e9d1e8e1b139a31a7b308d4afc1e186d1e989eb3bb6b0cf3c7514b2ea596c9edbb6c20be7160f3e34e58f324fd70b6eb163f4f92
6
+ metadata.gz: e4cf5e5ac2314ef0ebfeb797dc43e2d0c6853e30e63339751efd503751b4caeb93481f6226e5b95fa55dca7a3525bd5ff89452084854eb94b0d178ff9594e5d6
7
+ data.tar.gz: d49b2c4950e42f474dc63fa581d9431ab2ac7f0367cc51a30ae82bd64e57d586be30952afdb36f416aef16885935e6e84fc9f18342715905fc587335b54c637f
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
4
+ script:
5
+ - bundle exec rspec
@@ -0,0 +1,18 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ # Note: The cmd option is now required due to the increasing number of ways
5
+ # rspec may be run, below are examples of the most common uses.
6
+ # * bundler: 'bundle exec rspec'
7
+ # * bundler binstubs: 'bin/rspec'
8
+ # * spring: 'bin/rsspec' (This will use spring if running and you have
9
+ # installed the spring binstubs per the docs)
10
+ # * zeus: 'zeus rspec' (requires the server to be started separetly)
11
+ # * 'just' rspec: 'rspec'
12
+ guard :rspec, cmd: 'bundle exec rspec' do
13
+ watch(%r{^spec/.+_spec\.rb$})
14
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
15
+ watch('spec/spec_helper.rb') { "spec" }
16
+ end
17
+
18
+ # vi: ft=ruby
data/README.md CHANGED
@@ -7,6 +7,8 @@ The name stands for "Remote ENVironment" (thanks, captain obvious).
7
7
  It can be used to provide a replacement to Heroku's superb `config:get` /
8
8
  `config:set` in Capistrano-land.
9
9
 
10
+ ![Version](https://badge.fury.io/rb/renv.svg)
11
+ ![Build status](https://travis-ci.org/HouseTrip/renv.svg?branch=master)
10
12
 
11
13
  ## Installation
12
14
 
@@ -37,16 +37,21 @@ module Renv
37
37
  private
38
38
 
39
39
  def _engine
40
+ connection = Connection.new(
41
+ app: options[:app],
42
+ bucket: options[:bucket]
43
+ )
40
44
  Engine.new(
41
- app: options[:app],
42
- name: options[:name],
43
- bucket: options[:bucket])
45
+ name: options[:name],
46
+ connection: connection)
44
47
  end
45
48
 
49
+ # Transforms an array of KEY=VALUE pairs into a { KEY => VALUE } hash.
50
+ # The key is the part at the left of the first equals sign.
46
51
  def _parse_pairs(pairs)
47
52
  Hash.new.tap do |h|
48
53
  pairs.each do |p|
49
- if p !~ /^([^=]+)=(.*)$/
54
+ if p !~ /^([^=]+)=(.*)$/ # left/right of the first equals sign
50
55
  $stderr.puts "Not a valid key-value: '#{p}'"
51
56
  exit 1
52
57
  end
@@ -0,0 +1,53 @@
1
+ require 'fog'
2
+ require 'delegate'
3
+ require 'renv'
4
+
5
+ module Renv
6
+ class Connection < SimpleDelegator
7
+
8
+ def initialize(app: nil, bucket: bucket)
9
+ @_app = app
10
+ @_bucket = bucket
11
+
12
+ connection = Fog::Storage.new(
13
+ provider: 'AWS',
14
+ aws_access_key_id: ENV.fetch("RENV_AWS_KEY_#{_app}"),
15
+ aws_secret_access_key: ENV.fetch("RENV_AWS_SECRET_#{_app}"),
16
+ region: ENV.fetch("RENV_AWS_REGION_#{_app}", 'eu-west-1')
17
+ )
18
+
19
+ if connection.nil?
20
+ $stderr.puts "Failed to connect to AWS, please check your key and secret."
21
+ exit 1
22
+ end
23
+
24
+ bucket = connection.directories.get(_bucket).tap do |b|
25
+ if b.nil?
26
+ $stderr.puts "Bucket '#{_bucket}' does not seem to exist"
27
+ exit 1
28
+ end
29
+ end
30
+
31
+ super bucket
32
+
33
+ rescue Excon::Errors::Forbidden
34
+ $stderr.puts "Credentials rejected by AWS, please check your settings."
35
+ exit 1
36
+ end
37
+
38
+
39
+ def app_name ; _app ; end
40
+
41
+ private
42
+
43
+ def _app
44
+ @_app ||= ENV.fetch('RENV_APP')
45
+ end
46
+
47
+ def _bucket
48
+ @_bucket ||= ENV.fetch("RENV_BUCKET_#{_app}")
49
+ end
50
+
51
+ end
52
+ end
53
+
@@ -5,7 +5,7 @@ module Renv
5
5
  class Data
6
6
  extend Forwardable
7
7
 
8
- def initialize(payload)
8
+ def initialize(payload = '')
9
9
  @data = _parse(payload)
10
10
  end
11
11
 
@@ -22,7 +22,8 @@ module Renv
22
22
  end
23
23
 
24
24
  def load(payload)
25
- @data = _parse(payload).merge(@data)
25
+ @data = @data.merge(_parse(payload))
26
+ self
26
27
  end
27
28
 
28
29
  private
@@ -1,19 +1,22 @@
1
1
  require 'renv'
2
2
  require 'fog'
3
3
  require 'renv/data'
4
+ require 'renv/connection'
4
5
 
5
6
  module Renv
6
7
  class Engine
7
- def initialize(app: nil, name: nil, bucket: nil)
8
- @_app = app
9
- @_name = name
10
- @_bucket = bucket
8
+ def initialize(connection:, name: nil, data: nil)
9
+ @_name = name
10
+ @_connection = connection
11
+ @_data = data || Data.new
12
+ @_loaded = false
11
13
  end
12
14
 
13
15
  def get(key)
14
16
  _data[key]
15
17
  end
16
18
 
19
+ # Sets one or more key-value pairs
17
20
  def set(hash)
18
21
  hash.each_pair do |key, value|
19
22
  _data[key] = value
@@ -21,6 +24,7 @@ module Renv
21
24
  _save
22
25
  end
23
26
 
27
+ # Deletes one or more keys-value pairs
24
28
  def del(keys)
25
29
  keys.each { |key| _data.delete(key) }
26
30
  _save
@@ -38,16 +42,16 @@ module Renv
38
42
  private
39
43
 
40
44
  def _data
41
- @_data ||= begin
42
- s3file = _directory.files.get(_path_current)
43
- payload = s3file ? s3file.body : ''
44
- Data.new(payload)
45
- end
45
+ return @_data if @_loaded
46
+ s3file = @_connection.files.get(_path_current)
47
+ payload = s3file ? s3file.body : ''
48
+ @_loaded = true
49
+ @_data.load(payload)
46
50
  end
47
51
 
48
52
  def _save
49
53
  [_path_new, _path_current].each do |path|
50
- _directory.files.create(key: path, body: _data.dump, public: false)
54
+ @_connection.files.create(key: path, body: _data.dump, public: false)
51
55
  end
52
56
  end
53
57
 
@@ -55,38 +59,17 @@ module Renv
55
59
  @_path_current ||= "#{_name}/current"
56
60
  end
57
61
 
62
+ # "Backup" path, which is a timestamp in ISO format (2014-08-07T11:24:25)
58
63
  def _path_new
59
64
  @_path_new ||= "#{_name}/#{Time.now.strftime('%FT%T')}"
60
65
  end
61
66
 
62
- def _directory
63
- @_directory ||= _connection.directories.get(_bucket).tap do |dir|
64
- if dir.nil?
65
- $stderr.puts "Bucket '#{_bucket}' does not seem to exist"
66
- exit 1
67
- end
68
- end
69
- end
70
-
71
- def _connection
72
- @_connection ||= Fog::Storage.new(
73
- provider: 'AWS',
74
- aws_access_key_id: ENV.fetch("RENV_AWS_KEY_#{_app}"),
75
- aws_secret_access_key: ENV.fetch("RENV_AWS_SECRET_#{_app}"),
76
- region: ENV.fetch("RENV_AWS_REGION_#{_app}", 'eu-west-1')
77
- )
78
- end
79
-
80
- def _bucket
81
- @_bucket ||= ENV.fetch("RENV_BUCKET_#{_app}")
82
- end
83
-
84
67
  def _name
85
- @_name ||= _app
68
+ @_name ||= @_connection.app_name
86
69
  end
87
70
 
88
71
  def _app
89
- @_app ||= ENV.fetch('RENV_APP')
72
+ @_connection.app
90
73
  end
91
74
 
92
75
  end
@@ -1,3 +1,3 @@
1
1
  module Renv
2
- VERSION = "0.0.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -20,6 +20,8 @@ Gem::Specification.new do |spec|
20
20
  spec.add_development_dependency 'bundler', '~> 1.6'
21
21
  spec.add_development_dependency 'rake'
22
22
  spec.add_development_dependency 'pry'
23
+ spec.add_development_dependency 'guard-rspec'
24
+ spec.add_development_dependency 'timecop'
23
25
 
24
26
  spec.add_runtime_dependency 'fog'
25
27
  spec.add_runtime_dependency 'thor'
@@ -0,0 +1,91 @@
1
+ require 'renv/data'
2
+
3
+ describe Renv::Data do
4
+ let(:payload) { '' }
5
+ subject { described_class.new(payload) }
6
+
7
+ context 'with a simple payload' do
8
+ let(:payload) { "FOO=bar\nBAR=baz" }
9
+
10
+ describe '#[]' do
11
+ it 'returns nil for unknown keys' do
12
+ expect(subject['DO_YOU_EVEN']).to be_nil
13
+ end
14
+
15
+ it 'returns key values' do
16
+ expect(subject['FOO']).to eq('bar')
17
+ end
18
+ end
19
+
20
+ describe '#[]=' do
21
+ it 'aborts on bad keys' do
22
+ expect { subject['hello, world!'] = 'foo' }.to raise_error(SystemExit)
23
+ end
24
+
25
+ it 'sets key values' do
26
+ subject['DO_YOU'] = 'even'
27
+ expect(subject['DO_YOU']).to eq('even')
28
+ end
29
+ end
30
+
31
+ describe '#dump' do
32
+ it 'serializes the hash' do
33
+ subject['BAZ'] = 'qux'
34
+ expect(subject.dump).to eq("FOO=bar\nBAR=baz\nBAZ=qux\n")
35
+ end
36
+ end
37
+
38
+ describe '#load' do
39
+ it 'adds extra keys' do
40
+ subject.load('QUX=even')
41
+ expect(subject['QUX']).to eq('even')
42
+ end
43
+
44
+ it 'does not remove existing keys' do
45
+ subject.load('QUX=even')
46
+ expect(subject['FOO']).to eq('bar')
47
+ end
48
+
49
+ it 'replaces same keys' do
50
+ subject.load('FOO=qux')
51
+ expect(subject['FOO']).to eq('qux')
52
+ end
53
+ end
54
+ end
55
+
56
+ describe '#initialize' do
57
+ it 'does not require a payload' do
58
+ expect { described_class.new }.not_to raise_error
59
+ end
60
+
61
+ it 'accepts comments' do
62
+ payload.replace "# comment1\nFOO=bar\n# comment 2"
63
+ expect(subject['FOO']).to eq('bar')
64
+ end
65
+
66
+ it 'accepts blank lines' do
67
+ payload.replace "\n\nFOO=bar\n\n\n# comment 2\n\n"
68
+ expect(subject['FOO']).to eq('bar')
69
+ end
70
+
71
+ it 'accepts multiple equal signs' do
72
+ payload.replace "FOO=bar=baz"
73
+ expect(subject['FOO']).to eq('bar=baz')
74
+ end
75
+
76
+ it 'accepts spaces in values' do
77
+ payload.replace "FOO=bar baz"
78
+ expect(subject['FOO']).to eq('bar baz')
79
+ end
80
+
81
+ it 'rejects misformatted pairs' do
82
+ payload.replace "FOO: bar baz"
83
+ expect { subject }.to raise_error(SystemExit)
84
+ end
85
+
86
+ it 'only loads the last of identical keys' do
87
+ payload.replace "FOO=bar\nFOO=qux"
88
+ expect(subject['FOO']).to eq('qux')
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,141 @@
1
+ require 'renv/engine'
2
+ require 'timecop'
3
+ require 'fog'
4
+
5
+ describe Renv::Engine do
6
+ let(:tempdir) { Pathname.new('tmp').join("%08x" % rand(1<<31)) }
7
+ let(:name) { 'staging' }
8
+ let(:app_name) { 'testapp' }
9
+ let(:data) { Renv::Data.new }
10
+
11
+ let(:connection) do
12
+ c = Fog::Storage.new(provider: 'Local', local_root: tempdir.to_s)
13
+ c.directories.create(key: 'testbucket')
14
+ end
15
+
16
+ let(:options) {{ name: name, connection: connection, data: data }}
17
+
18
+ let(:default_data) { "KEY1=value1\nKEY2=value2" }
19
+
20
+ subject { described_class.new(**options) }
21
+
22
+ def data_for(entry, value = nil)
23
+ path = tempdir.join("testbucket/#{name}/#{entry}")
24
+ if value
25
+ path.parent.mkpath
26
+ path.write(value)
27
+ elsif path.exist?
28
+ path.read
29
+ else
30
+ nil
31
+ end
32
+ end
33
+
34
+ around do |example|
35
+ tempdir.mkpath
36
+ example.run
37
+ tempdir.rmtree
38
+ end
39
+
40
+ before do
41
+ allow(connection).to receive(:app_name).and_return(app_name)
42
+ # TODO: proper separation would use the injected Data dependency
43
+ # and do the following instead of parsing files:
44
+ # allow(data).to receive(:dump).and_return('dump')
45
+ end
46
+
47
+ before do
48
+ data_for(:current, default_data) if default_data
49
+ end
50
+
51
+ shared_examples 'writer' do
52
+ it 'creates a backup' do
53
+ timestamp = '2014-07-30T01:23:45'
54
+ Timecop.freeze(timestamp) { perform }
55
+ expect(data_for(timestamp)).not_to be_nil
56
+ end
57
+ end
58
+
59
+ shared_examples 'preserving existing keypairs' do
60
+ it 'leaves existing keypairs intact' do
61
+ data_for(:current, "#{default_data}\nPRESERVED=value\n")
62
+ perform
63
+ expect(data_for(:current)).to match(/^PRESERVED=value$/)
64
+ end
65
+ end
66
+
67
+ shared_examples 'initial conditions' do
68
+ let(:default_data) { nil }
69
+
70
+ it 'has no initial data' do
71
+ expect(data_for(:current)).to be_nil
72
+ end
73
+
74
+ it 'works with an empty bucket' do
75
+ expect { perform }.not_to raise_error
76
+ end
77
+ end
78
+
79
+ describe 'set' do
80
+ let(:perform) { subject.set('FOO' => 'bar', 'BAZ' => 'qux') }
81
+ it 'writes keys to file' do
82
+ perform
83
+ expect(data_for(:current)).to match(/^FOO=bar$/)
84
+ expect(data_for(:current)).to match(/^BAZ=qux$/)
85
+ end
86
+
87
+ it_behaves_like 'writer'
88
+ it_behaves_like 'preserving existing keypairs'
89
+ it_behaves_like 'initial conditions'
90
+ end
91
+
92
+ describe 'del' do
93
+ let(:perform) { subject.del(['KEY1']) }
94
+
95
+ it 'deletes key from store' do
96
+ perform
97
+ expect(data_for(:current)).not_to match(/^KEY1=/)
98
+ end
99
+
100
+ it_behaves_like 'writer'
101
+ it_behaves_like 'preserving existing keypairs'
102
+ it_behaves_like 'initial conditions'
103
+ end
104
+
105
+ describe 'load' do
106
+ let(:perform) { subject.load("FOO=bar\nBAZ=qux") }
107
+
108
+ it 'deletes key from store' do
109
+ perform
110
+ expect(data_for(:current)).to match(/^FOO=bar$/)
111
+ expect(data_for(:current)).to match(/^BAZ=qux$/)
112
+ end
113
+
114
+ it_behaves_like 'writer'
115
+ it_behaves_like 'preserving existing keypairs'
116
+ it_behaves_like 'initial conditions'
117
+ end
118
+
119
+ describe 'get' do
120
+ let(:perform) { subject.get('KEY1') }
121
+
122
+ it 'returns the value' do
123
+ expect(perform).to eq('value1')
124
+ end
125
+
126
+ it_behaves_like 'preserving existing keypairs'
127
+ it_behaves_like 'initial conditions'
128
+ end
129
+
130
+ describe 'dump' do
131
+ let(:perform) { subject.dump }
132
+
133
+ it 'returns the value' do
134
+ expect(perform).to match(/^KEY1=value1$/)
135
+ expect(perform).to match(/^KEY2=value2$/)
136
+ end
137
+
138
+ it_behaves_like 'preserving existing keypairs'
139
+ it_behaves_like 'initial conditions'
140
+ end
141
+ end
@@ -0,0 +1,78 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
4
+ # file to always be loaded, without a need to explicitly require it in any files.
5
+ #
6
+ # Given that it is always loaded, you are encouraged to keep this file as
7
+ # light-weight as possible. Requiring heavyweight dependencies from this file
8
+ # will add to the boot time of your test suite on EVERY test run, even for an
9
+ # individual file that may not need all of that loaded. Instead, make a
10
+ # separate helper file that requires this one and then use it only in the specs
11
+ # that actually need it.
12
+ #
13
+ # The `.rspec` file also contains a few flags that are not defaults but that
14
+ # users commonly want.
15
+ #
16
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
17
+ RSpec.configure do |config|
18
+ # The settings below are suggested to provide a good initial experience
19
+ # with RSpec, but feel free to customize to your heart's content.
20
+ =begin
21
+ # These two settings work together to allow you to limit a spec run
22
+ # to individual examples or groups you care about by tagging them with
23
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
24
+ # get run.
25
+ config.filter_run :focus
26
+ config.run_all_when_everything_filtered = true
27
+
28
+ # Many RSpec users commonly either run the entire suite or an individual
29
+ # file, and it's useful to allow more verbose output when running an
30
+ # individual spec file.
31
+ if config.files_to_run.one?
32
+ # Use the documentation formatter for detailed output,
33
+ # unless a formatter has already been configured
34
+ # (e.g. via a command-line flag).
35
+ config.default_formatter = 'doc'
36
+ end
37
+
38
+ # Print the 10 slowest examples and example groups at the
39
+ # end of the spec run, to help surface which specs are running
40
+ # particularly slow.
41
+ config.profile_examples = 10
42
+
43
+ # Run specs in random order to surface order dependencies. If you find an
44
+ # order dependency and want to debug it, you can fix the order by providing
45
+ # the seed, which is printed after each run.
46
+ # --seed 1234
47
+ config.order = :random
48
+
49
+ # Seed global randomization in this process using the `--seed` CLI option.
50
+ # Setting this allows you to use `--seed` to deterministically reproduce
51
+ # test failures related to randomization by passing the same `--seed` value
52
+ # as the one that triggered the failure.
53
+ Kernel.srand config.seed
54
+
55
+ # rspec-expectations config goes here. You can use an alternate
56
+ # assertion/expectation library such as wrong or the stdlib/minitest
57
+ # assertions if you prefer.
58
+ config.expect_with :rspec do |expectations|
59
+ # Enable only the newer, non-monkey-patching expect syntax.
60
+ # For more details, see:
61
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
62
+ expectations.syntax = :expect
63
+ end
64
+
65
+ # rspec-mocks config goes here. You can use an alternate test double
66
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
67
+ config.mock_with :rspec do |mocks|
68
+ # Enable only the newer, non-monkey-patching expect syntax.
69
+ # For more details, see:
70
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
71
+ mocks.syntax = :expect
72
+
73
+ # Prevents you from mocking or stubbing a method that does not exist on
74
+ # a real object. This is generally recommended.
75
+ mocks.verify_partial_doubles = true
76
+ end
77
+ =end
78
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: renv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julien Letessier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-24 00:00:00.000000000 Z
11
+ date: 2014-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard-rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: timecop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: fog
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -89,17 +117,24 @@ extensions: []
89
117
  extra_rdoc_files: []
90
118
  files:
91
119
  - ".gitignore"
120
+ - ".rspec"
121
+ - ".travis.yml"
92
122
  - Gemfile
123
+ - Guardfile
93
124
  - LICENSE.txt
94
125
  - README.md
95
126
  - Rakefile
96
127
  - bin/renv
97
128
  - lib/renv.rb
98
129
  - lib/renv/cli.rb
130
+ - lib/renv/connection.rb
99
131
  - lib/renv/data.rb
100
132
  - lib/renv/engine.rb
101
133
  - lib/renv/version.rb
102
134
  - renv.gemspec
135
+ - spec/renv/data_spec.rb
136
+ - spec/renv/engine_spec.rb
137
+ - spec/spec_helper.rb
103
138
  homepage: ''
104
139
  licenses:
105
140
  - MIT
@@ -124,4 +159,7 @@ rubygems_version: 2.2.2
124
159
  signing_key:
125
160
  specification_version: 4
126
161
  summary: Manages out-of-repository .env file
127
- test_files: []
162
+ test_files:
163
+ - spec/renv/data_spec.rb
164
+ - spec/renv/engine_spec.rb
165
+ - spec/spec_helper.rb