runger_config 4.0.0 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/bin/release +27 -0
  4. data/lib/generators/runger/app_config/app_config_generator.rb +6 -10
  5. data/lib/generators/runger/config/config_generator.rb +44 -41
  6. data/lib/generators/runger/install/install_generator.rb +35 -37
  7. data/lib/runger/auto_cast.rb +3 -3
  8. data/lib/runger/config.rb +114 -94
  9. data/lib/runger/dynamic_config.rb +21 -23
  10. data/lib/runger/ejson_parser.rb +24 -24
  11. data/lib/runger/env.rb +50 -52
  12. data/lib/runger/ext/deep_dup.rb +33 -36
  13. data/lib/runger/ext/deep_freeze.rb +28 -32
  14. data/lib/runger/ext/flatten_names.rb +23 -27
  15. data/lib/runger/ext/hash.rb +26 -29
  16. data/lib/runger/ext/string_constantize.rb +12 -15
  17. data/lib/runger/loaders/base.rb +11 -15
  18. data/lib/runger/loaders/doppler.rb +38 -42
  19. data/lib/runger/loaders/ejson.rb +65 -63
  20. data/lib/runger/loaders/env.rb +6 -10
  21. data/lib/runger/loaders/yaml.rb +69 -66
  22. data/lib/runger/loaders.rb +69 -71
  23. data/lib/runger/option_parser_builder.rb +16 -18
  24. data/lib/runger/optparse_config.rb +11 -10
  25. data/lib/runger/rails/autoload.rb +24 -26
  26. data/lib/runger/rails/config.rb +13 -17
  27. data/lib/runger/rails/loaders/credentials.rb +53 -57
  28. data/lib/runger/rails/loaders/secrets.rb +21 -25
  29. data/lib/runger/rails/loaders/yaml.rb +1 -6
  30. data/lib/runger/rails/loaders.rb +3 -3
  31. data/lib/runger/rails/settings.rb +49 -49
  32. data/lib/runger/rails.rb +9 -11
  33. data/lib/runger/railtie.rb +3 -2
  34. data/lib/runger/rbs.rb +29 -29
  35. data/lib/runger/settings.rb +82 -84
  36. data/lib/runger/testing/helpers.rb +26 -28
  37. data/lib/runger/testing.rb +2 -2
  38. data/lib/runger/tracing.rb +143 -136
  39. data/lib/runger/type_casting.rb +16 -11
  40. data/lib/runger/utils/which.rb +10 -12
  41. data/lib/runger/version.rb +1 -1
  42. data/lib/runger.rb +1 -1
  43. data/lib/runger_config.rb +34 -27
  44. metadata +20 -19
@@ -1,83 +1,86 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pathname"
4
- require "runger/ext/hash"
3
+ require 'pathname'
4
+ require 'runger/ext/hash'
5
5
 
6
6
  using Runger::Ext::Hash
7
7
 
8
- module Runger
9
- module Loaders
10
- class YAML < Base
11
- def call(config_path:, **_options)
12
- rel_config_path = relative_config_path(config_path).to_s
13
- base_config = trace!(:yml, path: rel_config_path) do
14
- config = load_base_yml(config_path)
15
- environmental?(config) ? config_with_env(config) : config
16
- end
17
-
18
- return base_config unless use_local?
19
-
20
- local_path = local_config_path(config_path)
21
- local_config = trace!(:yml, path: relative_config_path(local_path).to_s) { load_local_yml(local_path) }
22
- Utils.deep_merge!(base_config, local_config)
8
+ class Runger::Loaders::YAML < Runger::Loaders::Base
9
+ def call(config_path:, **_options)
10
+ rel_config_path = relative_config_path(config_path).to_s
11
+ base_config =
12
+ trace!(:yml, path: rel_config_path) do
13
+ config = load_base_yml(config_path)
14
+ environmental?(config) ? config_with_env(config) : config
23
15
  end
24
16
 
25
- private
26
-
27
- def environmental?(parsed_yml)
28
- # strange, but still possible
29
- return true if Settings.default_environmental_key? && parsed_yml.key?(Settings.default_environmental_key)
30
- # possible
31
- return true if !Settings.future.unwrap_known_environments && Settings.current_environment
32
- # for other environments
33
- return true if Settings.known_environments&.any? { parsed_yml.key?(_1) }
34
- # preferred
35
- parsed_yml.key?(Settings.current_environment)
36
- end
17
+ return base_config unless use_local?
37
18
 
38
- def config_with_env(config)
39
- env_config = config[Settings.current_environment] || {}
40
- return env_config unless Settings.default_environmental_key?
19
+ local_path = local_config_path(config_path)
20
+ local_config =
21
+ trace!(:yml, path: relative_config_path(local_path).to_s) {
22
+ load_local_yml(local_path)
23
+ }
24
+ ::Runger::Utils.deep_merge!(base_config, local_config)
25
+ end
41
26
 
42
- default_config = config[Settings.default_environmental_key] || {}
43
- Utils.deep_merge!(default_config, env_config)
44
- end
27
+ private
45
28
 
46
- def parse_yml(path)
47
- return {} unless File.file?(path)
48
- require "yaml" unless defined?(::YAML)
49
-
50
- # By default, YAML load will return `false` when the yaml document is
51
- # empty. When this occurs, we return an empty hash instead, to match
52
- # the interface when no config file is present.
53
- begin
54
- if defined?(ERB)
55
- ::YAML.load(ERB.new(File.read(path)).result, aliases: true) || {}
56
- else
57
- ::YAML.load_file(path, aliases: true) || {}
58
- end
59
- rescue ArgumentError
60
- if defined?(ERB)
61
- ::YAML.load(ERB.new(File.read(path)).result) || {}
62
- else
63
- ::YAML.load_file(path) || {}
64
- end
65
- end
66
- end
29
+ def environmental?(parsed_yml)
30
+ # strange, but still possible
31
+ return true if ::Runger::Settings.default_environmental_key? && parsed_yml.key?(::Runger::Settings.default_environmental_key)
32
+ # possible
33
+ return true if !::Runger::Settings.future.unwrap_known_environments && ::Runger::Settings.current_environment
34
+ # for other environments
35
+ return true if ::Runger::Settings.known_environments&.any? { parsed_yml.key?(_1) }
67
36
 
68
- alias_method :load_base_yml, :parse_yml
69
- alias_method :load_local_yml, :parse_yml
37
+ # preferred
38
+ parsed_yml.key?(::Runger::Settings.current_environment)
39
+ end
70
40
 
71
- def local_config_path(path)
72
- path.sub(".yml", ".local.yml")
73
- end
41
+ def config_with_env(config)
42
+ env_config = config[::Runger::Settings.current_environment] || {}
43
+ return env_config unless ::Runger::Settings.default_environmental_key?
44
+
45
+ default_config = config[::Runger::Settings.default_environmental_key] || {}
46
+ ::Runger::Utils.deep_merge!(default_config, env_config)
47
+ end
48
+
49
+ def parse_yml(path)
50
+ return {} unless File.file?(path)
74
51
 
75
- def relative_config_path(path)
76
- Pathname.new(path).then do |path|
77
- return path if path.relative?
78
- path.relative_path_from(Settings.app_root)
79
- end
52
+ require 'yaml' unless defined?(::YAML)
53
+
54
+ # By default, YAML load will return `false` when the yaml document is
55
+ # empty. When this occurs, we return an empty hash instead, to match
56
+ # the interface when no config file is present.
57
+ begin
58
+ if defined?(ERB)
59
+ ::YAML.load(ERB.new(File.read(path)).result, aliases: true) || {}
60
+ else
61
+ ::YAML.load_file(path, aliases: true) || {}
62
+ end
63
+ rescue ArgumentError
64
+ if defined?(ERB)
65
+ ::YAML.load(ERB.new(File.read(path)).result) || {}
66
+ else
67
+ ::YAML.load_file(path) || {}
80
68
  end
81
69
  end
82
70
  end
71
+
72
+ alias load_base_yml parse_yml
73
+ alias load_local_yml parse_yml
74
+
75
+ def local_config_path(path)
76
+ path.sub('.yml', '.local.yml')
77
+ end
78
+
79
+ def relative_config_path(path)
80
+ Pathname.new(path).then do |path|
81
+ return path if path.relative?
82
+
83
+ path.relative_path_from(::Runger::Settings.app_root)
84
+ end
85
+ end
83
86
  end
@@ -1,77 +1,75 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Runger
4
- module Loaders
5
- class Registry
6
- attr_reader :registry
7
-
8
- def initialize
9
- @registry = []
10
- end
11
-
12
- def prepend(id, handler = nil, &block)
13
- handler ||= block
14
- insert_at(0, id, handler)
15
- end
16
-
17
- def append(id, handler = nil, &block)
18
- handler ||= block
19
- insert_at(registry.size, id, handler)
20
- end
21
-
22
- def insert_before(another_id, id, handler = nil, &block)
23
- ind = registry.find_index { |(hid, _)| hid == another_id }
24
- raise ArgumentError, "Loader with ID #{another_id} hasn't been registered" if ind.nil?
25
-
26
- handler ||= block
27
- insert_at(ind, id, handler)
28
- end
29
-
30
- def insert_after(another_id, id, handler = nil, &block)
31
- ind = registry.find_index { |(hid, _)| hid == another_id }
32
- raise ArgumentError, "Loader with ID #{another_id} hasn't been registered" if ind.nil?
33
-
34
- handler ||= block
35
- insert_at(ind + 1, id, handler)
36
- end
37
-
38
- def override(id, handler)
39
- find(id).then do |id_to_handler|
40
- raise ArgumentError, "Loader with ID #{id} hasn't been registered" if id_to_handler.nil?
41
- id_to_handler[1] = handler
42
- end
43
- end
44
-
45
- def delete(id)
46
- find(id).then do |id_to_handler|
47
- raise ArgumentError, "Loader with ID #{id} hasn't been registered" if id_to_handler.nil?
48
- registry.delete id_to_handler
49
- end
50
- end
51
-
52
- def each(&block)
53
- registry.each(&block)
54
- end
55
-
56
- def freeze = registry.freeze
57
-
58
- private
59
-
60
- def insert_at(index, id, handler)
61
- raise ArgumentError, "Loader with ID #{id} has been already registered" unless find(id).nil?
62
-
63
- registry.insert(index, [id, handler])
64
- end
65
-
66
- def find(id)
67
- registry.find { |(hid, _)| hid == id }
68
- end
3
+ class Runger::Loaders::Registry
4
+ attr_reader :registry
5
+
6
+ def initialize
7
+ @registry = []
8
+ end
9
+
10
+ def prepend(id, handler = nil, &block)
11
+ handler ||= block
12
+ insert_at(0, id, handler)
13
+ end
14
+
15
+ def append(id, handler = nil, &block)
16
+ handler ||= block
17
+ insert_at(registry.size, id, handler)
18
+ end
19
+
20
+ def insert_before(another_id, id, handler = nil, &block)
21
+ ind = registry.find_index { |(hid, _)| hid == another_id }
22
+ raise(ArgumentError, "Loader with ID #{another_id} hasn't been registered") if ind.nil?
23
+
24
+ handler ||= block
25
+ insert_at(ind, id, handler)
26
+ end
27
+
28
+ def insert_after(another_id, id, handler = nil, &block)
29
+ ind = registry.find_index { |(hid, _)| hid == another_id }
30
+ raise(ArgumentError, "Loader with ID #{another_id} hasn't been registered") if ind.nil?
31
+
32
+ handler ||= block
33
+ insert_at(ind + 1, id, handler)
34
+ end
35
+
36
+ def override(id, handler)
37
+ find(id).then do |id_to_handler|
38
+ raise(ArgumentError, "Loader with ID #{id} hasn't been registered") if id_to_handler.nil?
39
+
40
+ id_to_handler[1] = handler
69
41
  end
70
42
  end
43
+
44
+ def delete(id)
45
+ find(id).then do |id_to_handler|
46
+ raise(ArgumentError, "Loader with ID #{id} hasn't been registered") if id_to_handler.nil?
47
+
48
+ registry.delete(id_to_handler)
49
+ end
50
+ end
51
+
52
+ def each(&block)
53
+ registry.each(&block)
54
+ end
55
+
56
+ def freeze = registry.freeze
57
+
58
+ private
59
+
60
+ def insert_at(index, id, handler)
61
+ raise(ArgumentError, "Loader with ID #{id} has been already registered") unless find(id).nil?
62
+
63
+ registry.insert(index, [id, handler])
64
+ end
65
+
66
+ def find(id)
67
+ registry.find { |(hid, _)| hid == id }
68
+ end
71
69
  end
72
70
 
73
- require "runger/loaders/base"
74
- require "runger/loaders/yaml"
75
- require "runger/loaders/env"
76
- require "runger/loaders/doppler"
77
- require "runger/loaders/ejson"
71
+ require 'runger/loaders/base'
72
+ require 'runger/loaders/doppler'
73
+ require 'runger/loaders/ejson'
74
+ require 'runger/loaders/env'
75
+ require 'runger/loaders/yaml'
@@ -1,29 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "optparse"
3
+ require 'optparse'
4
4
 
5
- module Runger # :nodoc:
6
- # Initializes the OptionParser instance using the given configuration
7
- class OptionParserBuilder
8
- class << self
9
- def call(options)
10
- OptionParser.new do |opts|
11
- options.each do |key, descriptor|
12
- opts.on(*option_parser_on_args(key, **descriptor)) do |val|
13
- yield [key, val]
14
- end
5
+ # Initializes the OptionParser instance using the given configuration
6
+ class Runger::OptionParserBuilder
7
+ class << self
8
+ def call(options)
9
+ OptionParser.new do |opts|
10
+ options.each do |key, descriptor|
11
+ opts.on(*option_parser_on_args(key, **descriptor)) do |val|
12
+ yield([key, val])
15
13
  end
16
14
  end
17
15
  end
16
+ end
18
17
 
19
- private
18
+ private
20
19
 
21
- def option_parser_on_args(key, flag: false, desc: nil, type: ::String)
22
- on_args = ["--#{key.to_s.tr("_", "-")}#{flag ? "" : " VALUE"}"]
23
- on_args << type unless flag
24
- on_args << desc unless desc.nil?
25
- on_args
26
- end
20
+ def option_parser_on_args(key, flag: false, desc: nil, type: ::String)
21
+ on_args = ["--#{key.to_s.tr('_', '-')}#{flag ? '' : ' VALUE'}"]
22
+ on_args << type unless flag
23
+ on_args << desc unless desc.nil?
24
+ on_args
27
25
  end
28
26
  end
29
27
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "runger/option_parser_builder"
3
+ require 'runger/option_parser_builder'
4
4
 
5
- require "runger/ext/deep_dup"
5
+ require 'runger/ext/deep_dup'
6
6
 
7
7
  module Runger
8
8
  using Runger::Ext::DeepDup
@@ -19,7 +19,7 @@ module Runger
19
19
 
20
20
  def describe_options(**hargs)
21
21
  hargs.each do |name, desc|
22
- if String === desc
22
+ if desc.is_a?(String)
23
23
  option_parser_descriptors[name.to_s][:desc] = desc
24
24
  else
25
25
  option_parser_descriptors[name.to_s].merge!(desc)
@@ -70,13 +70,14 @@ module Runger
70
70
  end
71
71
 
72
72
  def option_parser
73
- @option_parser ||= OptionParserBuilder.call(self.class.option_parser_options) do |key, val|
74
- write_config_attr(key, val)
75
- end.tap do |parser|
76
- self.class.option_parser_extensions.map do |extension|
77
- extension.call(parser, self)
73
+ @option_parser ||=
74
+ OptionParserBuilder.call(self.class.option_parser_options) do |key, val|
75
+ write_config_attr(key, val)
76
+ end.tap do |parser|
77
+ self.class.option_parser_extensions.map do |extension|
78
+ extension.call(parser, self)
79
+ end
78
80
  end
79
- end
80
81
  end
81
82
 
82
83
  def parse_options!(options)
@@ -86,7 +87,7 @@ module Runger
86
87
  end
87
88
 
88
89
  def self.included(base)
89
- base.extend ClassMethods
90
+ base.extend(ClassMethods)
90
91
  end
91
92
  end
92
93
  end
@@ -2,39 +2,37 @@
2
2
 
3
3
  # This module is used to detect a Rails application and activate the corresponding plugins
4
4
  # when Runger Config is loaded before Rails (e.g., in config/puma.rb).
5
- module Runger
6
- module Rails
7
- class << self
8
- attr_reader :tracer, :name_method
9
- attr_accessor :disable_postponed_load_warning
5
+ module Runger::Rails
6
+ class << self
7
+ attr_reader :tracer, :name_method
8
+ attr_accessor :disable_postponed_load_warning
10
9
 
11
- private
10
+ private
12
11
 
13
- def tracepoint_class_callback(event)
14
- # Ignore singletons
15
- return if event.self.singleton_class?
12
+ def tracepoint_class_callback(event)
13
+ # Ignore singletons
14
+ return if event.self.singleton_class?
16
15
 
17
- # We wait till `rails/application/configuration.rb` has been loaded, since we rely on it
18
- # See https://github.com/palkan/runger_config/issues/134
19
- return unless name_method.bind_call(event.self) == "Rails::Application::Configuration"
16
+ # We wait till `rails/application/configuration.rb` has been loaded, since we rely on it
17
+ # See https://github.com/palkan/runger_config/issues/134
18
+ return unless name_method.bind_call(event.self) == 'Rails::Application::Configuration'
20
19
 
21
- tracer.disable
20
+ tracer.disable
22
21
 
23
- unless disable_postponed_load_warning
24
- warn "Runger Config was loaded before Rails. Activating Runger Config Rails plugins now.\n" \
25
- "NOTE: Already loaded configs were provisioned without Rails-specific sources."
26
- end
27
-
28
- require "runger/rails"
22
+ unless disable_postponed_load_warning
23
+ warn("Runger Config was loaded before Rails. Activating Runger Config Rails plugins now.\n" \
24
+ 'NOTE: Already loaded configs were provisioned without Rails-specific sources.')
29
25
  end
30
- end
31
26
 
32
- # TruffleRuby doesn't support TracePoint's end event
33
- unless defined?(::TruffleRuby)
34
- @tracer = TracePoint.new(:end, &method(:tracepoint_class_callback))
35
- @tracer.enable
36
- # Use `Module#name` instead of `self.name` to handle overwritten `name` method
37
- @name_method = Module.instance_method(:name)
27
+ require 'runger/rails'
38
28
  end
39
29
  end
30
+
31
+ # TruffleRuby doesn't support TracePoint's end event
32
+ unless defined?(::TruffleRuby)
33
+ @tracer = TracePoint.new(:end, &method(:tracepoint_class_callback))
34
+ @tracer.enable
35
+ # Use `Module#name` instead of `self.name` to handle overwritten `name` method
36
+ @name_method = Module.instance_method(:name)
37
+ end
40
38
  end
@@ -1,23 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/hash/indifferent_access"
3
+ require 'active_support/core_ext/hash/indifferent_access'
4
4
 
5
- module Runger
6
- module Rails
7
- # Enhance config to be more Railsy-like:
8
- # – accept hashes with indeferent access
9
- # - load data from secrets
10
- # - recognize Rails env when loading from YML
11
- module Config
12
- module ClassMethods
13
- # Make defaults to be a Hash with indifferent access
14
- def new_empty_config
15
- {}.with_indifferent_access
16
- end
17
- end
18
- end
5
+ module Runger::Rails::Config ; end
6
+
7
+ # Enhance config to be more Railsy-like:
8
+ # – accept hashes with indeferent access
9
+ # - load data from secrets
10
+ # - recognize Rails env when loading from YML
11
+ module Runger::Rails::Config::ClassMethods
12
+ # Make defaults to be a Hash with indifferent access
13
+ def new_empty_config
14
+ {}.with_indifferent_access
19
15
  end
20
16
  end
21
17
 
22
- Runger::Config.prepend Runger::Rails::Config
23
- Runger::Config.singleton_class.prepend Runger::Rails::Config::ClassMethods
18
+ Runger::Config.prepend(Runger::Rails::Config)
19
+ Runger::Config.singleton_class.prepend(Runger::Rails::Config::ClassMethods)
@@ -1,62 +1,58 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Runger
4
- module Rails
5
- module Loaders
6
- class Credentials < Runger::Loaders::Base
7
- LOCAL_CONTENT_PATH = "config/credentials/local.yml.enc"
8
-
9
- def call(name:, **_options)
10
- return {} unless ::Rails.application.respond_to?(:credentials)
11
-
12
- # do not load from credentials if we're in the context
13
- # of the `credentials:edit` command
14
- return {} if defined?(::Rails::Command::CredentialsCommand)
15
-
16
- # Create a new hash cause credentials are mutable!
17
- config = {}
18
-
19
- trace!(
20
- :credentials,
21
- store: credentials_path
22
- ) do
23
- ::Rails.application.credentials.config[name.to_sym]
24
- end.then do |creds|
25
- Utils.deep_merge!(config, creds) if creds
26
- end
27
-
28
- if use_local?
29
- trace!(:credentials, store: LOCAL_CONTENT_PATH) do
30
- local_credentials(name)
31
- end.then { |creds| Utils.deep_merge!(config, creds) if creds }
32
- end
33
-
34
- config
35
- end
36
-
37
- private
38
-
39
- def local_credentials(name)
40
- local_creds_path = ::Rails.root.join(LOCAL_CONTENT_PATH).to_s
41
-
42
- return unless File.file?(local_creds_path)
43
-
44
- creds = ::Rails.application.encrypted(
45
- local_creds_path,
46
- key_path: ::Rails.root.join("config/credentials/local.key")
47
- )
48
-
49
- creds.config[name.to_sym]
50
- end
51
-
52
- def credentials_path
53
- if ::Rails.application.config.respond_to?(:credentials)
54
- ::Rails.root.join(::Rails.application.config.credentials.content_path).relative_path_from(::Rails.root).to_s
55
- else
56
- "config/credentials.yml.enc"
57
- end
58
- end
59
- end
3
+ module Runger::Rails::Loaders ; end
4
+
5
+ class Runger::Rails::Loaders::Credentials < Runger::Loaders::Base
6
+ LOCAL_CONTENT_PATH = 'config/credentials/local.yml.enc'
7
+
8
+ def call(name:, **_options)
9
+ return {} unless ::Rails.application.respond_to?(:credentials)
10
+
11
+ # do not load from credentials if we're in the context
12
+ # of the `credentials:edit` command
13
+ return {} if defined?(::Rails::Command::CredentialsCommand)
14
+
15
+ # Create a new hash cause credentials are mutable!
16
+ config = {}
17
+
18
+ trace!(
19
+ :credentials,
20
+ store: credentials_path,
21
+ ) do
22
+ ::Rails.application.credentials.config[name.to_sym]
23
+ end.then do |creds|
24
+ Runger::Utils.deep_merge!(config, creds) if creds
25
+ end
26
+
27
+ if use_local?
28
+ trace!(:credentials, store: LOCAL_CONTENT_PATH) do
29
+ local_credentials(name)
30
+ end.then { |creds| Runger::Utils.deep_merge!(config, creds) if creds }
31
+ end
32
+
33
+ config
34
+ end
35
+
36
+ private
37
+
38
+ def local_credentials(name)
39
+ local_creds_path = ::Rails.root.join(LOCAL_CONTENT_PATH).to_s
40
+
41
+ return unless File.file?(local_creds_path)
42
+
43
+ creds = ::Rails.application.encrypted(
44
+ local_creds_path,
45
+ key_path: ::Rails.root.join('config/credentials/local.key'),
46
+ )
47
+
48
+ creds.config[name.to_sym]
49
+ end
50
+
51
+ def credentials_path
52
+ if ::Rails.application.config.respond_to?(:credentials)
53
+ ::Rails.root.join(::Rails.application.config.credentials.content_path).relative_path_from(::Rails.root).to_s
54
+ else
55
+ 'config/credentials.yml.enc'
60
56
  end
61
57
  end
62
58
  end