invar 0.6.1 → 0.8.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/.rubocop.yml +0 -12
- data/.ruby-version +1 -1
- data/Gemfile +15 -1
- data/RELEASE_NOTES.md +31 -1
- data/invar.gemspec +1 -8
- data/lib/invar/errors.rb +53 -0
- data/lib/invar/private_file.rb +7 -3
- data/lib/invar/rake/tasks.rb +9 -6
- data/lib/invar/reality.rb +3 -55
- data/lib/invar/scope.rb +12 -7
- data/lib/invar/test.rb +97 -9
- data/lib/invar/version.rb +1 -1
- data/lib/invar.rb +9 -9
- metadata +5 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a4826c528fc5940bcc955a1fc762abc2b4800a30eb4ce5b34af0ea313dd990ab
|
4
|
+
data.tar.gz: f463ed247adc47ea89d7b6965cd427d21a98de125271b262541eb0703a792d62
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bbc1f4df04c3f4917a2cfcce611acde0859ccd74b412c0b9faa021770c4f01d246defb0131fc8052d0e2aeb40d904d40a043ecccb7a872f966b4a9264e812a3
|
7
|
+
data.tar.gz: 32a1754130909b04d488adb88b67e5efe193c2173103d9041338652026ef45a55b3e4fbaa49bed2863f8b5d0d70a257ace52b5bbff913236f4c82b4a90af06bf
|
data/.rubocop.yml
CHANGED
@@ -4,17 +4,6 @@ AllCops:
|
|
4
4
|
Exclude:
|
5
5
|
- 'bin/*'
|
6
6
|
|
7
|
-
TargetRubyVersion: 2.7
|
8
|
-
|
9
|
-
Layout/LineLength:
|
10
|
-
Exclude:
|
11
|
-
- 'spec/**/*.rb'
|
12
|
-
|
13
|
-
# setting to 6 to match RubyMine autoformat
|
14
|
-
Layout/FirstArrayElementIndentation:
|
15
|
-
IndentationWidth: 6
|
16
|
-
|
17
|
-
|
18
7
|
# rspec blocks are huge by design
|
19
8
|
Metrics/BlockLength:
|
20
9
|
Exclude:
|
@@ -23,4 +12,3 @@ Metrics/BlockLength:
|
|
23
12
|
Metrics/ModuleLength:
|
24
13
|
Exclude:
|
25
14
|
- 'spec/**/*.rb'
|
26
|
-
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-
|
1
|
+
ruby-3.1.4
|
data/Gemfile
CHANGED
@@ -2,5 +2,19 @@
|
|
2
2
|
|
3
3
|
source 'https://rubygems.org'
|
4
4
|
|
5
|
-
#
|
5
|
+
# Gem's dependencies in invar.gemspec
|
6
6
|
gemspec
|
7
|
+
|
8
|
+
group :development do
|
9
|
+
gem 'bundler', '~> 2.3'
|
10
|
+
gem 'rake', '~> 13.0'
|
11
|
+
gem 'rubocop', '~> 1.56'
|
12
|
+
gem 'rubocop-performance', '~> 1.19'
|
13
|
+
gem 'yard', '~> 0.9'
|
14
|
+
end
|
15
|
+
|
16
|
+
group :test do
|
17
|
+
gem 'fakefs', '~> 2.5'
|
18
|
+
gem 'rspec', '~> 3.12'
|
19
|
+
gem 'simplecov', '~> 0.22'
|
20
|
+
end
|
data/RELEASE_NOTES.md
CHANGED
@@ -19,6 +19,36 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
19
19
|
|
20
20
|
* none
|
21
21
|
|
22
|
+
## [0.8.0] - 2023-09-13
|
23
|
+
|
24
|
+
### Major Changes
|
25
|
+
|
26
|
+
* none
|
27
|
+
|
28
|
+
### Minor Changes
|
29
|
+
|
30
|
+
* Increased minimum Ruby to 3.1
|
31
|
+
|
32
|
+
### Bugfixes
|
33
|
+
|
34
|
+
* none
|
35
|
+
|
36
|
+
## [0.7.0] - 2023-08-06
|
37
|
+
|
38
|
+
### Major Changes
|
39
|
+
|
40
|
+
* none
|
41
|
+
|
42
|
+
### Minor Changes
|
43
|
+
|
44
|
+
* Tweaked file missing error messages
|
45
|
+
* Extracted testing helper features into a separate module
|
46
|
+
* Added support for multiple after_load hooks
|
47
|
+
|
48
|
+
### Bugfixes
|
49
|
+
|
50
|
+
* No longer attempts to set secrets file permissions on every edit
|
51
|
+
|
22
52
|
## [0.6.1] - 2023-05-22
|
23
53
|
|
24
54
|
### Major Changes
|
@@ -31,7 +61,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
31
61
|
|
32
62
|
### Bugfixes
|
33
63
|
|
34
|
-
* Fixed minor logic error in permissions checking, improved testing
|
64
|
+
* Fixed minor logic error in permissions checking, improved testing
|
35
65
|
|
36
66
|
## [0.6.0] - 2023-05-21
|
37
67
|
|
data/invar.gemspec
CHANGED
@@ -27,15 +27,8 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ['lib']
|
29
29
|
|
30
|
-
spec.required_ruby_version = '>=
|
30
|
+
spec.required_ruby_version = '>= 3.1'
|
31
31
|
|
32
32
|
spec.add_dependency 'dry-schema', '>= 1.0'
|
33
33
|
spec.add_dependency 'lockbox', '>= 1.0'
|
34
|
-
|
35
|
-
spec.add_development_dependency 'bundler', '~> 2.3'
|
36
|
-
spec.add_development_dependency 'fakefs', '~> 1.9'
|
37
|
-
spec.add_development_dependency 'rake', '~> 13.0'
|
38
|
-
spec.add_development_dependency 'rspec', '~> 3.12'
|
39
|
-
spec.add_development_dependency 'simplecov', '~> 0.21'
|
40
|
-
spec.add_development_dependency 'yard', '~> 0.9'
|
41
34
|
end
|
data/lib/invar/errors.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
module Invar
|
5
|
+
# Raised when no config file can be found within the search paths.
|
6
|
+
class MissingConfigFileError < RuntimeError
|
7
|
+
end
|
8
|
+
|
9
|
+
# Raised when no secrets file can be found within the search paths.
|
10
|
+
class MissingSecretsFileError < RuntimeError
|
11
|
+
end
|
12
|
+
|
13
|
+
# Raised when an error is encountered during secrets file encryption
|
14
|
+
class SecretsFileEncryptionError < RuntimeError
|
15
|
+
end
|
16
|
+
|
17
|
+
# Raised when an error is encountered during secrets file decryption
|
18
|
+
class SecretsFileDecryptionError < RuntimeError
|
19
|
+
end
|
20
|
+
|
21
|
+
# Raised when a key is defined in both the environment and the configuration file.
|
22
|
+
class EnvConfigCollisionError < RuntimeError
|
23
|
+
# Message hinting at possible solution
|
24
|
+
HINT = 'Either rename your config entry or remove the environment variable.'
|
25
|
+
end
|
26
|
+
|
27
|
+
# Raised when there are config or secrets files found at multiple locations. You can resolve this by deciding on
|
28
|
+
# one correct location and removing the alternate file(s).
|
29
|
+
class AmbiguousSourceError < RuntimeError
|
30
|
+
# Message hinting at possible solution
|
31
|
+
HINT = 'Choose 1 correct one and delete the others.'
|
32
|
+
end
|
33
|
+
|
34
|
+
# Raised when #pretend is called but the testing extension has not been loaded.
|
35
|
+
#
|
36
|
+
# When raised during normal operation, it may mean the application is calling #pretend directly, which is strongly
|
37
|
+
# discouraged. The feature is meant for testing.
|
38
|
+
#
|
39
|
+
# @see Invar#pretend
|
40
|
+
class ImmutableRealityError < NoMethodError
|
41
|
+
HINT = <<~HINT
|
42
|
+
Try adding this to your test suite config file:
|
43
|
+
require 'invar/test'
|
44
|
+
HINT
|
45
|
+
|
46
|
+
PRETEND_MSG = "Method 'Invar::Scope#pretend' is defined in the testing extension. #{ HINT }".freeze
|
47
|
+
HOOK_MSG = "Methods 'Invar.after_load and clear_hooks' are defined in the testing extension. #{ HINT }".freeze
|
48
|
+
end
|
49
|
+
|
50
|
+
# Raised when schema validation fails
|
51
|
+
class SchemaValidationError < RuntimeError
|
52
|
+
end
|
53
|
+
end
|
data/lib/invar/private_file.rb
CHANGED
@@ -7,13 +7,18 @@ require 'delegate'
|
|
7
7
|
|
8
8
|
module Invar
|
9
9
|
# Verifies a file is secure
|
10
|
-
class PrivateFile
|
10
|
+
class PrivateFile
|
11
11
|
extend Forwardable
|
12
12
|
def_delegators :@delegate_sd_obj, :stat, :to_s, :basename, :==, :chmod
|
13
13
|
|
14
|
+
# Mask for limiting to the lowest three octal digits (which store permissions)
|
15
|
+
PERMISSIONS_MASK = 0o777
|
16
|
+
|
14
17
|
ALLOWED_USER_MODES = [0o600, 0o400].freeze
|
15
18
|
ALLOWED_GROUP_MODES = [0o060, 0o040, 0o000].freeze
|
16
19
|
|
20
|
+
DEFAULT_PERMISSIONS = 0o600
|
21
|
+
|
17
22
|
# Allowed permissions modes for lockfile. Readable or read-writable by the user or group only
|
18
23
|
ALLOWED_MODES = ALLOWED_USER_MODES.product(ALLOWED_GROUP_MODES).collect do |u, g|
|
19
24
|
u | g # bitwise OR
|
@@ -45,9 +50,8 @@ module Invar
|
|
45
50
|
#
|
46
51
|
# @raise [FilePermissionsError] if the file has insecure permissions
|
47
52
|
def verify_permissions!
|
48
|
-
permissions_mask = 0o777 # only the lowest three digits are perms, so masking
|
49
53
|
# stat = @delegate_sd_obj.stat
|
50
|
-
file_mode = stat.mode &
|
54
|
+
file_mode = stat.mode & PERMISSIONS_MASK
|
51
55
|
# TODO: use stat.world_readable? etc instead
|
52
56
|
return if ALLOWED_MODES.include? file_mode
|
53
57
|
|
data/lib/invar/rake/tasks.rb
CHANGED
@@ -30,8 +30,8 @@ module Invar
|
|
30
30
|
#
|
31
31
|
# @param (see #define)
|
32
32
|
# @see Tasks#define
|
33
|
-
def self.define(
|
34
|
-
new.define(
|
33
|
+
def self.define(...)
|
34
|
+
new.define(...)
|
35
35
|
end
|
36
36
|
|
37
37
|
# Defines helpful Rake tasks for the given namespace.
|
@@ -199,7 +199,10 @@ module Invar
|
|
199
199
|
|
200
200
|
encryption_key = Lockbox.generate_key
|
201
201
|
|
202
|
-
write_encrypted_file(file_path,
|
202
|
+
write_encrypted_file(file_path,
|
203
|
+
encryption_key: encryption_key,
|
204
|
+
content: SECRETS_TEMPLATE,
|
205
|
+
permissions: PrivateFile::DEFAULT_PERMISSIONS)
|
203
206
|
|
204
207
|
warn "Created file: #{ file_path }"
|
205
208
|
|
@@ -232,7 +235,7 @@ module Invar
|
|
232
235
|
'secrets.yml'
|
233
236
|
end
|
234
237
|
|
235
|
-
def write_encrypted_file(file_path, encryption_key
|
238
|
+
def write_encrypted_file(file_path, encryption_key:, content:, permissions: nil)
|
236
239
|
lockbox = Lockbox.new(key: encryption_key)
|
237
240
|
|
238
241
|
encrypted_data = lockbox.encrypt(content)
|
@@ -240,7 +243,7 @@ module Invar
|
|
240
243
|
config_dir.mkpath
|
241
244
|
# TODO: replace File.opens with photo_path.binwrite(uri.data) once FakeFS can handle it
|
242
245
|
File.open(file_path.to_s, 'wb') { |f| f.write encrypted_data }
|
243
|
-
file_path.chmod
|
246
|
+
file_path.chmod permissions if permissions
|
244
247
|
end
|
245
248
|
|
246
249
|
def edit_encrypted_file(file_path)
|
@@ -257,7 +260,7 @@ module Invar
|
|
257
260
|
tmp_file.read
|
258
261
|
end
|
259
262
|
|
260
|
-
write_encrypted_file(file_path, encryption_key, file_str)
|
263
|
+
write_encrypted_file(file_path, encryption_key: encryption_key, content: file_str)
|
261
264
|
end
|
262
265
|
|
263
266
|
def determine_key(file_path)
|
data/lib/invar/reality.rb
CHANGED
@@ -72,27 +72,22 @@ module Invar
|
|
72
72
|
@configs = Scope.new(load_configs(locator))
|
73
73
|
rescue FileLocator::FileNotFoundError
|
74
74
|
raise MissingConfigFileError,
|
75
|
-
"No config file found. Create config.yml in one of these locations: #{ search_paths }"
|
75
|
+
"No Invar config file found. Create config.yml in one of these locations: #{ search_paths }"
|
76
76
|
end
|
77
77
|
|
78
78
|
begin
|
79
79
|
@secrets = Scope.new(load_secrets(locator, decryption_keyfile || DEFAULT_KEY_FILE_NAME))
|
80
80
|
rescue FileLocator::FileNotFoundError
|
81
|
+
hint = "Create encrypted secrets.yml in one of these locations: #{ search_paths }"
|
81
82
|
raise MissingSecretsFileError,
|
82
|
-
"No secrets file found.
|
83
|
+
"No Invar secrets file found. #{ hint }"
|
83
84
|
end
|
84
85
|
|
85
86
|
freeze
|
86
|
-
# instance_eval(&self.class.__override_block__)
|
87
|
-
self.class.__override_block__&.call(self)
|
88
87
|
|
89
88
|
RealityValidator.new(configs_schema, secrets_schema).validate(@configs, @secrets)
|
90
89
|
end
|
91
90
|
|
92
|
-
class << self
|
93
|
-
attr_accessor :__override_block__
|
94
|
-
end
|
95
|
-
|
96
91
|
# Fetch from one of the two base scopes: :config or :secret.
|
97
92
|
# Plural names are also accepted (ie. :configs and :secrets).
|
98
93
|
#
|
@@ -224,51 +219,4 @@ module Invar
|
|
224
219
|
end
|
225
220
|
end
|
226
221
|
end
|
227
|
-
|
228
|
-
# Raised when no config file can be found within the search paths.
|
229
|
-
class MissingConfigFileError < RuntimeError
|
230
|
-
end
|
231
|
-
|
232
|
-
# Raised when no secrets file can be found within the search paths.
|
233
|
-
class MissingSecretsFileError < RuntimeError
|
234
|
-
end
|
235
|
-
|
236
|
-
# Raised when an error is encountered during secrets file encryption
|
237
|
-
class SecretsFileEncryptionError < RuntimeError
|
238
|
-
end
|
239
|
-
|
240
|
-
# Raised when an error is encountered during secrets file decryption
|
241
|
-
class SecretsFileDecryptionError < RuntimeError
|
242
|
-
end
|
243
|
-
|
244
|
-
# Raised when a key is defined in both the environment and the configuration file.
|
245
|
-
class EnvConfigCollisionError < RuntimeError
|
246
|
-
# Message hinting at possible solution
|
247
|
-
HINT = 'Either rename your config entry or remove the environment variable.'
|
248
|
-
end
|
249
|
-
|
250
|
-
# Raised when there are config or secrets files found at multiple locations. You can resolve this by deciding on
|
251
|
-
# one correct location and removing the alternate file(s).
|
252
|
-
class AmbiguousSourceError < RuntimeError
|
253
|
-
# Message hinting at possible solution
|
254
|
-
HINT = 'Choose 1 correct one and delete the others.'
|
255
|
-
end
|
256
|
-
|
257
|
-
# Raised when #pretend is called but the testing extension has not been loaded.
|
258
|
-
#
|
259
|
-
# When raised during normal operation, it may mean the application is calling #pretend directly, which is strongly
|
260
|
-
# discouraged. The feature is meant for testing.
|
261
|
-
#
|
262
|
-
# @see Invar#pretend
|
263
|
-
class ImmutableRealityError < NoMethodError
|
264
|
-
# Message and hint for a possible solution
|
265
|
-
MSG = <<~MSG
|
266
|
-
Method 'pretend' is defined in the testing extension. Try adding this to your test suite config file:
|
267
|
-
require 'invar/test'
|
268
|
-
MSG
|
269
|
-
end
|
270
|
-
|
271
|
-
# Raised when schema validation fails
|
272
|
-
class SchemaValidationError < RuntimeError
|
273
|
-
end
|
274
222
|
end
|
data/lib/invar/scope.rb
CHANGED
@@ -7,7 +7,6 @@ module Invar
|
|
7
7
|
@data = convert(data)
|
8
8
|
|
9
9
|
@data.freeze
|
10
|
-
@data_override = {}
|
11
10
|
freeze
|
12
11
|
end
|
13
12
|
|
@@ -18,23 +17,25 @@ module Invar
|
|
18
17
|
# @see #override
|
19
18
|
def fetch(key)
|
20
19
|
key = key.downcase.to_sym
|
21
|
-
@
|
20
|
+
@data.fetch key
|
22
21
|
rescue KeyError => e
|
23
|
-
raise KeyError, "#{ e.message }. Known keys are #{
|
22
|
+
raise KeyError, "#{ e.message }. Known keys are #{ known_keys }"
|
24
23
|
end
|
25
24
|
|
26
25
|
alias / fetch
|
27
26
|
alias [] fetch
|
28
27
|
|
29
|
-
def
|
30
|
-
raise ::Invar::ImmutableRealityError, ::Invar::ImmutableRealityError::
|
28
|
+
def method_missing(symbol, *args)
|
29
|
+
raise ::Invar::ImmutableRealityError, ::Invar::ImmutableRealityError::PRETEND_MSG if symbol == :pretend
|
30
|
+
|
31
|
+
super
|
31
32
|
end
|
32
33
|
|
33
34
|
# Returns a hash representation of this scope and subscopes.
|
34
35
|
#
|
35
36
|
# @return [Hash] a hash representation of this scope
|
36
37
|
def to_h
|
37
|
-
@data.
|
38
|
+
@data.to_h.transform_values do |value|
|
38
39
|
case value
|
39
40
|
when Scope
|
40
41
|
value.to_h
|
@@ -50,11 +51,15 @@ module Invar
|
|
50
51
|
|
51
52
|
private
|
52
53
|
|
54
|
+
def known_keys
|
55
|
+
@data.keys.sort.collect { |k| ":#{ k }" }.join(', ')
|
56
|
+
end
|
57
|
+
|
53
58
|
def convert(data)
|
54
59
|
(data || {}).dup.each_with_object({}) do |pair, agg|
|
55
60
|
key, value = pair
|
56
61
|
|
57
|
-
agg[key] = value.is_a?(Hash) ? Scope.new(value) : value
|
62
|
+
agg[key.to_s.downcase.to_sym] = value.is_a?(Hash) ? Scope.new(value) : value
|
58
63
|
end
|
59
64
|
end
|
60
65
|
end
|
data/lib/invar/test.rb
CHANGED
@@ -1,16 +1,104 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'invar'
|
3
|
+
# Specifically not calling require 'invar' in this file to force applications to need to include it themselves,
|
4
|
+
# avoiding the situation where test suites include application dependencies for them and breaking when
|
5
|
+
# the app is run without the test suite
|
4
6
|
|
7
|
+
# :nodoc:
|
5
8
|
module Invar
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
# Namespace module containing mixins for parts of the main gem to enable modifications and data control
|
10
|
+
# in automated testing, while remaining immutable in the main gem and real runtime usage.
|
11
|
+
module TestExtension
|
12
|
+
# Methods to extend the Reality class
|
13
|
+
module RealityMethods
|
14
|
+
class << self
|
15
|
+
attr_accessor :__after_load_hooks__
|
16
|
+
|
17
|
+
RealityMethods.__after_load_hooks__ = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(**)
|
21
|
+
super
|
22
|
+
|
23
|
+
# instance_eval(&self.class.__override_block__)
|
24
|
+
RealityMethods.__after_load_hooks__.each { |hook| hook.call(self) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Adds methods to the main Invar module itself for a global-access hook to be used in application init phase.
|
29
|
+
module LoadHook
|
30
|
+
def clear_hooks
|
31
|
+
RealityMethods.__after_load_hooks__.clear
|
32
|
+
end
|
33
|
+
|
34
|
+
# Block that will be run after loading from config files.
|
35
|
+
#
|
36
|
+
# It is intended to allow test suites to tweak configurations without having to duplicate the entire config file.
|
37
|
+
#
|
38
|
+
# @yieldparam the configs from the Invar
|
39
|
+
# @return [void]
|
40
|
+
def after_load(&block)
|
41
|
+
RealityMethods.__after_load_hooks__.push(block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Methods mixin for the Invar::Scope class
|
46
|
+
module ScopeMethods
|
47
|
+
def initialize(data)
|
48
|
+
@pretend_data = {}
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
# Overrides the given set of key-value pairs. This is intended to only be used in testing environments,
|
53
|
+
# where you may need contextual adjustments to suit the test situation.
|
54
|
+
#
|
55
|
+
# @param [Hash] pairs the hash of pairs to override.
|
56
|
+
def pretend(pairs)
|
57
|
+
@pretend_data.merge! convert(pairs)
|
58
|
+
end
|
59
|
+
|
60
|
+
def fetch(key)
|
61
|
+
@pretend_data.fetch(key.downcase.to_sym) do
|
62
|
+
super
|
63
|
+
end
|
64
|
+
rescue KeyError => e
|
65
|
+
raise KeyError, "#{ e.message }. Pretend keys are: #{ pretend_keys }."
|
66
|
+
end
|
67
|
+
|
68
|
+
# Duplicated to refer to the override version
|
69
|
+
alias / fetch
|
70
|
+
alias [] fetch
|
71
|
+
|
72
|
+
# Returns a hash representation of this scope and subscopes.
|
73
|
+
#
|
74
|
+
# @return [Hash] a hash representation of this scope
|
75
|
+
def to_h
|
76
|
+
super.merge(@pretend_data).to_h
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def pretend_keys
|
82
|
+
keys = @pretend_data.keys
|
83
|
+
|
84
|
+
if keys.empty?
|
85
|
+
'(none)'
|
86
|
+
else
|
87
|
+
keys.sort.collect { |k| ":#{ k }" }.join(', ')
|
88
|
+
end
|
89
|
+
end
|
14
90
|
end
|
15
91
|
end
|
92
|
+
|
93
|
+
# Extension to the base library class that provides additional methods relevant only to automated testing
|
94
|
+
extend TestExtension::LoadHook
|
95
|
+
|
96
|
+
# Extension to the base library class that provides additional methods relevant only to automated testing
|
97
|
+
class Scope
|
98
|
+
prepend TestExtension::ScopeMethods
|
99
|
+
end
|
100
|
+
|
101
|
+
class Reality
|
102
|
+
prepend TestExtension::RealityMethods
|
103
|
+
end
|
16
104
|
end
|
data/lib/invar/version.rb
CHANGED
data/lib/invar.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require_relative 'invar/version'
|
4
|
+
require_relative 'invar/errors'
|
5
|
+
require_relative 'invar/reality'
|
5
6
|
|
6
7
|
# Invar is a Ruby Gem that provides a single source of truth for application configuration, secrets, and environment
|
7
8
|
# variables.
|
@@ -14,13 +15,12 @@ module Invar
|
|
14
15
|
end
|
15
16
|
|
16
17
|
class << self
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
::Invar::Reality.__override_block__ = block
|
18
|
+
def method_missing(meth)
|
19
|
+
if [:after_load, :clear_hooks].include? meth
|
20
|
+
raise ::Invar::ImmutableRealityError, ::Invar::ImmutableRealityError::HOOK_MSG
|
21
|
+
end
|
22
|
+
|
23
|
+
super
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: invar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robin Miller
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-schema
|
@@ -38,90 +38,6 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: bundler
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '2.3'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '2.3'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: fakefs
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '1.9'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '1.9'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rake
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '13.0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '13.0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rspec
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '3.12'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '3.12'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: simplecov
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - "~>"
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0.21'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - "~>"
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0.21'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: yard
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - "~>"
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0.9'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - "~>"
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '0.9'
|
125
41
|
description: |
|
126
42
|
Locates and loads config YAML files based on XDG standard with the encrypted secrets file kept separately.
|
127
43
|
Includes useful rake tasks to make management easier. No code execution in config. Rails-independent. Gluten free.
|
@@ -143,6 +59,7 @@ files:
|
|
143
59
|
- Rakefile
|
144
60
|
- invar.gemspec
|
145
61
|
- lib/invar.rb
|
62
|
+
- lib/invar/errors.rb
|
146
63
|
- lib/invar/file_locator.rb
|
147
64
|
- lib/invar/private_file.rb
|
148
65
|
- lib/invar/rake/tasks.rb
|
@@ -163,14 +80,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
163
80
|
requirements:
|
164
81
|
- - ">="
|
165
82
|
- !ruby/object:Gem::Version
|
166
|
-
version: '
|
83
|
+
version: '3.1'
|
167
84
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
85
|
requirements:
|
169
86
|
- - ">="
|
170
87
|
- !ruby/object:Gem::Version
|
171
88
|
version: '0'
|
172
89
|
requirements: []
|
173
|
-
rubygems_version: 3.
|
90
|
+
rubygems_version: 3.4.18
|
174
91
|
signing_key:
|
175
92
|
specification_version: 4
|
176
93
|
summary: Single source of truth for environmental configuration.
|