Class: ReleaseHx::Configuration
- Inherits:
-
Object
- Object
- ReleaseHx::Configuration
- Defined in:
- lib/releasehx/configuration.rb
Overview
Manages the application's configuration by loading and merging settings
from a definition file and a user-provided configuration file.
Constant Summary collapse
- GEM_GLOBALS =
Public: Global gem attributes copied from the generated README attributes. This constant is used to locate the internal schema/definition file and to determine sane defaults for the user's configuration path.
ReleaseHx::ATTRIBUTES[:globals].freeze
- GEM_ROOT_PATH =
File.('../..', __dir__).freeze
- CONFIG_DEF_PATH =
Returns The path to the internal configuration definition file.
File.join( GEM_ROOT_PATH, GEM_GLOBALS['gem_config_definition_path']).freeze
- DEFAULT_CONFIG_PATH =
Returns The default path to the user's configuration file.
File.join( File.('.'), GEM_GLOBALS['app_default_config_path'] || 'releasehx.yml').freeze
- VALIDATION_RULES =
List of configuration validation rules used by validate_config. Each rule is a Hash with :scopes, :message and :check (callable). The :check callable should raise an ArgumentError when validation fails.
{ scopes: [:fetch], message: "'origin.href' is required for remote sources", check: lambda { |config| if %w[jira github gitlab].include?(config.origin['source']) && config.origin['href'].to_s.empty? raise ArgumentError, "'origin.href' is required for remote source '#{config.origin['source']}'" end } }, { scopes: [:fetch], message: "'rhyml' file must exist at origin.href", check: lambda { |config| if config.origin['source'] == 'rhyml' && !File.exist?(config.origin['href'].to_s) raise ArgumentError, "Missing RHYML file at: #{config.origin['href']}" end } } ].freeze
Instance Attribute Summary collapse
-
#settings ⇒ Hash
readonly
The underlying hash of configuration settings.
Class Method Summary collapse
-
.apply_property(prop_def, user_val) ⇒ Object
private
Applies a single property definition from the schema to a user-supplied value.
-
.apply_schema(schema_properties, user_hash) ⇒ Hash
private
Recursively applies schema defaults and normalizes the user's config.
-
.known_api_sources(config) ⇒ Array<String>
Scans built-in and custom mapping files and produces a unique list of known API source names.
-
.load(user_config_path = DEFAULT_CONFIG_PATH, definition_path = CONFIG_DEF_PATH) ⇒ Configuration
Loads and merges the user configuration with the internal definition/schema and performs the SGYML precompilation and staged rendering.
-
.validate_config(config, *scopes) ⇒ Object
Validates the configuration against rules that match the provided scopes.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Provides bracket access to configuration settings.
-
#initialize(settings = {}) ⇒ Configuration
constructor
A new instance of Configuration.
-
#method_missing(name, *args) ⇒ Object
Provides convenient dot-style access to top-level configuration sections.
-
#respond_to_missing?(name, include_private = false) ⇒ Boolean
Indicates whether the configuration has a setting for the given key.
Constructor Details
#initialize(settings = {}) ⇒ Configuration
Returns a new instance of Configuration.
27 28 29 |
# File 'lib/releasehx/configuration.rb', line 27 def initialize settings = {} @settings = settings end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args) ⇒ Object
Provides convenient dot-style access to top-level configuration sections.
Example:
config = ReleaseHx::Configuration.load
source = config.origin['source']
This method returns the sub-hash stored under the given key name when present;
otherwise it delegates to the normal method_missing implementation.
68 69 70 71 72 73 74 |
# File 'lib/releasehx/configuration.rb', line 68 def method_missing(name, *args, &) # If settings has a key matching the method name, return that sub-hash key_str = name.to_s return settings[key_str] if settings.key?(key_str) super end |
Instance Attribute Details
#settings ⇒ Hash (readonly)
Returns The underlying hash of configuration settings.
86 87 88 |
# File 'lib/releasehx/configuration.rb', line 86 def settings @settings end |
Class Method Details
.apply_property(prop_def, user_val) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Applies a single property definition from the schema to a user-supplied value. Handles nested objects and array defaults declared in the schema. User values are preserved unless they are absent (nil) or explicitly set to the literal "$nil" marker.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/releasehx/configuration.rb', line 138 def self.apply_property prop_def, user_val return nil if user_val.to_s.strip == '$nil' default_val = prop_def['dflt'] if prop_def.key?('dflt') val = user_val.nil? ? default_val : user_val # If this prop has nested "properties", treat as a sub-object if prop_def['properties'] val_hash = val.is_a?(Hash) ? val : {} # recursively handle sub-properties val = apply_schema(prop_def['properties'], val_hash) elsif prop_def['type'] == 'ArrayList' && val.nil? # It's an array type with a default and we have no user value val = default_val || [] end val end |
.apply_schema(schema_properties, user_hash) ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Recursively applies schema defaults and normalizes the user's config. Special handling: - A user value of the literal string "$nil" will explicitly remove the property (treated as nil) - Unknown user-supplied keys are preserved so extensions are not lost
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/releasehx/configuration.rb', line 109 def self.apply_schema schema_properties, user_hash final_hash = {} (schema_properties || {}).each do |prop_key, prop_def| user_val = user_hash.fetch(prop_key, nil) # Skip processing this property if user explicitly set it to $nil unless user_val.to_s.strip == '$nil' final_val = apply_property(prop_def, user_val) final_hash[prop_key] = final_val end end # Preserves extra user-supplied keys that aren't in the definition/schema user_hash.each do |unk_key, unk_val| final_hash[unk_key] = unk_val unless final_hash.key?(unk_key) || unk_val.to_s.strip == '$nil' end final_hash end |
.known_api_sources(config) ⇒ Array<String>
Scans built-in and custom mapping files and produces a unique list of known API source names.
The result always includes the special entries 'rhyml' and 'git'.
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/releasehx/configuration.rb', line 199 def self.known_api_sources config builtin_path = File.join(GEM_ROOT_PATH, 'lib/releasehx/rhyml/mappings') custom_path = File.(config.paths['mappings_dir'] || '_mappings') mapping_files = Dir["#{builtin_path}/*.{yml,yaml}", "#{custom_path}/*-api.yml"] base_names = mapping_files.map do |file| base = File.basename(file).sub(/\.ya?ml$/, '') base.sub('-api', '') end base_names = base_names.reject { |name| name == 'verb_past_tenses' } (base_names + %w[rhyml git]).uniq end |
.load(user_config_path = DEFAULT_CONFIG_PATH, definition_path = CONFIG_DEF_PATH) ⇒ Configuration
Loads and merges the user configuration with the internal definition/schema
and performs the SGYML precompilation and staged rendering.
This method returns a fully-resolved Configuration object suitable for use across the application.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/releasehx/configuration.rb', line 39 def self.load user_config_path = DEFAULT_CONFIG_PATH, definition_path = CONFIG_DEF_PATH ReleaseHx.logger.debug "Loading configuration from: #{user_config_path}" # Use SchemaGraphy to load config definition with resolved attributes attrs = ReleaseHx::ATTRIBUTES[:globals] definition = SchemaGraphy::Loader.load_yaml_with_attributes(definition_path, attrs) SchemaGraphy::SchemaUtils.(definition, 'history.head') user_config = File.exist?(user_config_path) ? SchemaGraphy::Loader.(user_config_path) : {} merged_settings = apply_schema(definition['properties'], user_config) config = new(merged_settings) ReleaseHx::SgymlHelpers.precompile_from_schema!( config.settings, definition, # should contain $schema or be the schema scope: { 'config' => config.settings }) ReleaseHx::SgymlHelpers.render_stage_fields!(config.settings, :load) config end |
.validate_config(config, *scopes) ⇒ Object
Validates the configuration against rules that match the provided scopes.
188 189 190 191 192 |
# File 'lib/releasehx/configuration.rb', line 188 def self.validate_config config, *scopes scopes.flatten! rules = VALIDATION_RULES.select { |rule| rule[:scopes].intersect?(scopes) } rules.each { |rule| rule[:check].call(config) } end |
Instance Method Details
#[](key) ⇒ Object
Provides bracket access to configuration settings.
Accepts String or Symbol keys and returns the stored value (or nil).
94 95 96 |
# File 'lib/releasehx/configuration.rb', line 94 def [] key @settings[key.to_s] end |
#respond_to_missing?(name, include_private = false) ⇒ Boolean
Indicates whether the configuration has a setting for the given key.
81 82 83 |
# File 'lib/releasehx/configuration.rb', line 81 def respond_to_missing? name, include_private = false settings.key?(name.to_s) || super end |